捕捉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
关键字手动throw
exception。
例:
#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?
要么你需要throw
exception,并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类,如果你需要更奇特的东西。