我最近开始用C ++编码,我对以下代码有疑问。我在使用'throw'关键字时遇到问题。在中位数或等级函数何时会出错? throw和domain_error的确切用法是什么?我是否会从成绩或中位数函数中得到错误信息?
#include<iostream>
#include<string>
#include<vector>
#include<iomanip>
#include<ios>
#include<algorithm>
#include<stdexcept>
using std::cout; using std::cin;
using std::vector; using std::endl;
using std::string; using std::streamsize;
using std::setprecision; using std::domain_error;
using std::istream;
double grade(double midterm, double final, double homework)
{
return 0.2*midterm+0.4*final+0.4*homework;
}
double median(vector<double> vec)
{
typedef vector<double>::size_type vec_sz;
vec_sz size= vec.size();
if(size==0)
{
throw domain_error("Median of an empty vector"); //when will i get this error msg??
}
sort(vec.begin(),vec.end());
vec_sz mid=size/2;
return size%2==0?(vec[mid]+vec[mid-1])/2:vec[mid];
}
double grade(double midterm, double final, const vector<double>& hw)
{
if(hw.size()==0)
{
throw domain_error("Student has done no homework");// when will i get this error?
}
return grade(midterm, final, median(hw));
}
istream& read_hw(istream& in, vector<double>& hw)
{
if(in)
{
hw.clear();
double x;
while(in>>x)
hw.push_back(x);
in.clear();
}
return in;
}
int main()
{
string name;
cout<<"Please enter your name:";
cin>>name;
cout<<"Hello "<<name<<"!"<<endl;
cout << "Please enter your midterm and final exam grades: ";
double midterm, final;
cin >> midterm >> final;
cout << "Enter all your homework grades, "
"followed by end-of-file: ";
vector<double> homework;
read_hw(cin, homework);
try {
double final_grade = grade(midterm, final, homework);
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3)
<< final_grade << setprecision(prec) << endl;
} catch (domain_error) {
cout << endl << "You must enter your grades. "
"Please try again." << endl;
return 1;
}
return 0;
}
答案 0 :(得分:4)
您可以从catch
声明中获取异常消息。
try {
double final_grade = grade(midterm, final, homework);
streamsize prec = cout.precision();
cout << "Your final grade is " << setprecision(3) << final_grade
<< setprecision(prec) << endl;
} catch (const domain_error& error) {
cout << error.what(); // <-- Will print your message.
}
答案 1 :(得分:1)
函数double median(vector<double> vec)
将抛出domain_error
,以防{i}}传递包含任何元素。vec
将因同样的原因抛出它 - 如果{{1}向量是空的。
执行double grade(double midterm, double final, const vector<double>& hw)
后,hw
或throw domain_error("...")
将停止执行,控件将立即传递到最近的相应catch块,median
位于{ {1}}。可以使用grade
对象的函数catch (domain_error)
来检索消息。
main
答案 2 :(得分:1)
想象一下相互调用的一系列函数:
A -> B -> C -> D -> E -> F -> G
如果G
抛出X
类型的异常,D
是捕获类型X
或其父类之一的异常的最近函数,或{ {1}},然后关闭函数...
,G
和F
,E
将捕获异常。
在您的情况下,D
:
main
然而,在这个接球手的身体里,你没有太多用处:
} catch (domain_error) {
首先,您不打印cout << endl << "You must enter your grades. "
"Please try again." << endl;
return 1;
引发的实际消息。请参阅Bo Persson的答案。
其次,如果你想再试一次,你应该将整个主要内容放在一个循环中,而不是domain_error
,而是return
。
最后,不要将异常视为一种闪亮的错误处理方式,they are not so great。
答案 3 :(得分:1)
throw
关键字表示如果达到这行代码(即if中的语句为true),则会在堆栈中引发错误,直到它被捕获为止。
这是什么意思?
这意味着如果您调用函数grade
并且抛出错误,则有两个选项:
1)如果对函数的调用在try and catch
块内,即:
try {
grade();
} catch(domain_error) {
cout << "An error occured" << endl;
}
然后它将捕获它,执行catch子句中的内容,程序将继续。
2)如果调用不在try和catch块中,那么它将以递归方式弹出调用此函数的函数,直到达到try和catch块,或者堆栈中没有其他函数。在这种情况下,由于未被捕获的异常,它很可能会被粉碎(这就是它在java中的作用)。
希望事情清楚。
另外,请注意catch子句中的错误应该与抛出相同,否则,它将无法捕获它。
答案 4 :(得分:0)
您的问题已经得到解答,但我想提一下您写的内容。
在我个人看来,我认为你在这里使用exception
是完全不必要的。
你重载了函数grade
并使你的代码混淆了。
您的median
函数会在std::vector
之前使用value
参数,而不需要复制(在您的示例中)。
您正在检查两个向量的长度,内容完全相同两次,并抛出两个异常。 median
中的例外情况永远会在您的示例中被抛出。
这一切都可以避免。
double median(vector<double>& vec)
{
sort(vec.begin(),vec.end());
vec_sz mid = size/2;
return size%2==0?(vec[mid]+vec[mid-1])/2:vec[mid];
}
double grade(double midterm, double final, double homework)
{
return 0.2*midterm+0.4*final+0.4*homework;
}
在你的主要:
if(hw.size())
{
double final_grade = grade(midterm, final, median(hw));
}
else
{
cout << endl << "You must enter your grades. "
"Please try again." << endl;
return 1;
}
答案 5 :(得分:0)
@Aesthete。我认为中位数函数会通过值获取 std :: vector 参数。 在Accelerated C++书中,作者解释了原因。
中位数函数通过调用排序来更改其参数的值。复制参数可防止排序所做的更改从推送回到呼叫者。这种行为是有道理的,因为采用向量的中位数不应该改变vecotr本身。
如果不喜欢这样,我将在编译此文件时收到以下错误消息(mingw32-g ++。exe)
错误:'std :: vector&amp;'类型引用的初始化无效来自'const std :: vector'|
类型的表达式错误:传递'double median(std :: vector&amp;)'|
的参数1