捕捉exception:除以零

当我尝试除以0时,以下代码不会捕获exception。我是否需要抛出exception,或者计算机在运行时是否自动抛出一个exception?

int i = 0; cin >> i; // what if someone enters zero? try { i = 5/i; } catch (std::logic_error e) { cerr << e.what(); } 

你需要自己检查并抛出exception。 标准C ++中整数除零不是一个例外。

浮点除以零也不是,但至less具有处理它的具体手段。

ISO标准中列出的例外是:

 namespace std { class logic_error; class domain_error; class invalid_argument; class length_error; class out_of_range; class runtime_error; class range_error; class overflow_error; class underflow_error; } 

你会认为overflow_error对于用零来表示除法是理想的。

但是第5.6节( C++11 ,虽然我认为这与之前的迭代没有什么不同)具体说明:

如果/%的第二个操作数是零,则行为是未定义的。

所以,它可能会抛出(或其他)exception。 它也可以格式化你的硬盘,嘲笑嘲笑:-)


如果你想实现这样一个野兽,你可以在下面的程序中使用像intDivEx

 #include <iostream> #include <stdexcept> // Integer division, catching divide by zero. inline int intDivEx (int numerator, int denominator) { if (denominator == 0) throw std::overflow_error("Divide by zero exception"); return numerator / denominator; } int main (void) { int i = 42; try { i = intDivEx (10, 2); } catch (std::overflow_error e) { std::cout << e.what() << " -> "; } std::cout << i << std::endl; try { i = intDivEx (10, 0); } catch (std::overflow_error e) { std::cout << e.what() << " -> "; } std::cout << i << std::endl; return 0; } 

这输出:

 5 Divide by zero exception -> 5 

你可以看到它抛出并捕获除以零情况的例外。


相当的%几乎是完全一样的:

 // Integer remainder, catching divide by zero. inline int intModEx (int numerator, int denominator) { if (denominator == 0) throw std::overflow_error("Divide by zero exception"); return numerator % denominator; } 

更新了ExcessPhase的评论

海湾合作委员会(至less4.8版本)将让你模仿这种行为:

 #include <signal.h> #include <memory> int main() { std::shared_ptr<void(int)> handler( signal(SIGFPE, [](int signum) {throw std::logic_error("FPE"); }), [](__sighandler_t f) { signal(SIGFPE, f); }); int i = 0; cin >> i; // what if someone enters zero? try { i = 5/i; } catch (std::logic_error e) { std::cerr << e.what(); } } 

这将设置一个新的信号处理程序,它引发一个exception,并将一个shared_ptr传递给旧的信号处理程序,并具有一个自定义的“删除”function,在旧的处理程序超出范围时恢复它。

您至less需要编译这些选项:

 g++ -c Foo.cc -o Foo.o -fnon-call-exceptions -std=c++11 

Visual C ++也会让你做类似的事情:

 #include <eh.h> #include <memory> int main() { std::shared_ptr<void(unsigned, EXCEPTION_POINTERS*)> handler( _set_se_translator([](unsigned u, EXCEPTION_POINTERS* p) { switch(u) { case FLT_DIVIDE_BY_ZERO: throw std::logic_error("Divide by zero"); ... default: throw std::logic_error("SEH exception"); } }), [](_se_translator_function f) { _set_se_translator(f); }); int i = 0; try { i = 5 / i; } catch(std::logic_error e) { std::cerr << e.what(); } } 

当然,你也可以跳过所有的C ++ 11,把它们放在一个传统的RAIIpipe理结构中。

据我所知,C ++规范没有提到任何有关被零除的除法。 我相信你需要自己动手

Stroustrup在“C ++的devise与发展”(Addison Wesley,1994)中指出,“低级事件,比如算术溢出和零除,被认为是由专门的低层机制来处理,而不是由exception。这使得C ++能够在算术时与其他语言的行为相匹配,同时也避免了在大量stream水线架构上出现的问题,例如被零除的事件是asynchronous的。

你应该检查,如果i = 0而不是那么分开。

(可选的,在检查之后,你可以抛出exception并在以后处理)。

更多信息: http : //www.cprogramming.com/tutorial/exceptions.html

您需要使用throw关键字手动throwexception。

例:

 #include <iostream> using namespace std; double division(int a, int b) { if( b == 0 ) { throw "Division by zero condition!"; } return (a/b); } int main () { int x = 50; int y = 0; double z = 0; try { z = division(x, y); cout << z << endl; }catch (const char* msg) { cerr << msg << endl; } return 0; } 

do i need to throw an exception or does the computer automatically throws one at runtime?

要么你需要throwexception,并catch它。 例如

 try { //... throw int(); } catch(int i) { } 

或者catch你的代码抛出的exception。

 try { int *p = new int(); } catch (std::bad_alloc e) { cerr << e.what(); } 

在你的情况下,我不知道是否有任何标准的例外,除以零。 如果没有这样的例外,那么你可以使用,

 catch(...) { // catch 'any' exception } 

你可以做assert(2 * i != i) ,它会抛出一个断言。 你可以写你自己的exception类,如果你需要更奇特的东西。