2012-08-09 62 views
2

我最近开始使用C++进行编码,并对以下代码有所怀疑。我在'throw'关键字遇到问题。在中位数或分数函数中它何时会给出错误? throw和domain_error的确切用法是什么?我会从等级或中位数函数得到错误信息吗?throw关键字的用法

#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; 

} 
+2

你会得到它随时随地'大小收到以下错误消息== 0' 。 – Morwenn 2012-08-09 11:56:59

+0

这段代码看起来很像* Accelerated C++ *,如果我可以这样说,这是一本很好的介绍性书籍。 – 2012-08-09 12:18:49

+0

是它的一本书的代码。我现在就明白了。感谢大家的帮助。实际上,这本书不断地从各处跳来跳去,所以有时候会让像我这样的初学者感到困惑。 – pratZ 2012-08-09 16:37:50

回答

1

想象一系列功能相互调用:

A -> B -> C -> D -> E -> F -> G 

如果G抛出X类型的异常,并D是映入X类型的异常的最接近的功能,或一种其父母或...,则功能G,FE将被关闭,D将捕获该异常。

在你的情况下,两个异常将被main被抓:

} catch (domain_error) { 

在然而,这捕手的身体,你不这样做很多有用:

cout << endl << "You must enter your grades. " 
    "Please try again." << endl; 
return 1; 

首先,您不打印与domain_error一起抛出的实际消息。请参阅Bo Persson的答案。

二,如果你想再试一次,你应该把整个主循环,而不是return,你continue

最后,不要将异常看作错误处理的一种很好的方式,they are not so great

3

您可以从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

功能double median(vector<double> vec)将抛出的情况下,vec一个domain_error传递不含elements.The double grade(double midterm, double final, const vector<double>& hw)将它扔出于同样的原因 - 如果hw向量是空的。

一旦throw domain_error("...")被执行,mediangrade将停止其执行并控制将被立即传递到最近的相应catch块,这是在maincatch (domain_error)。可以使用domain_error对象的函数what检索消息。

} catch (const domain_error& ex) { 
     cout << ex.what() << endl; 
     return 1; 
} 
1

throw关键字意味着如果这段代码已经到达(即if内部的语句为真),那么它会向堆栈发出错误,直到它被捕获。

这是什么意思? 这意味着,如果你有一个呼吁功能grade和错误被抛出,有两种选择:

1)如果调用函数是try and catch块里面,我。e:

try { 
    grade(); 
} catch(domain_error) { 
    cout << "An error occured" << endl; 
} 

然后它会抓住它,执行catch子句中的内容,程序将继续。如果调用不在try和catch块内,那么它会递归地调用调用该函数的函数,直到到达try和catch块,或者堆栈中没有更多函数。在这种情况下,由于未捕获的异常,它很可能会粉碎(这就是它在java中所做的)。

希望是十分明显的事情了。

另外,还要注意的catch子句中的错误,应该是一样被抛出,否则,也不会抓住它。

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; 
} 
0

@Aesthete。我觉得位数功能shouble通过采取的std ::矢量参数。 在Accelerated C++书中,作者解释了原因。

The median function changes the value of its parameter by calling sort.Copying the argument prevents changes made by sort from propageting back to the caller. This behavior makes sense,because taking the median of a vector should not change the vecotr itself.

如果不喜欢这样,我会在这个文件编译(的mingw32-G ++。exe文件)

error: invalid initialization of reference of type 'std::vector&' from expression of type 'const std::vector'|

error: in passing argument 1 of 'double median(std::vector&)'|