validar usar una try tratamiento que propagacion programacion por poo objetivo manejo lista las jerarquia handling excepción excepciones errores ejemplos ejemplo controlada control con como clases catch atrapar c++ exception-handling

c++ - usar - Captura de excepción: dividir por cero



try catch ejemplo (7)

El siguiente código no capta una excepción cuando trato de dividir por 0. ¿Tengo que lanzar una excepción, o la computadora lanza automáticamente una en el tiempo de ejecución?

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


Debe lanzar la excepción manualmente usando throw keyword.

Ejemplo:

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


Debe verificarlo usted mismo y lanzar una excepción. La división de enteros por cero no es una excepción en C ++ estándar.

Tampoco el punto flotante se divide por cero, pero al menos eso tiene medios específicos para manejarlo.

Las excepciones enumeradas en el estándar ISO son:

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

y pensarías que overflow_error sería ideal para indicar una división por cero.

Pero la sección 5.6 (de C++11 , aunque no creo que esto haya cambiado respecto a la iteración anterior) establece específicamente:

Si el segundo operando de / o % es cero, el comportamiento no está definido.

Por lo tanto, podría arrojar esa (o cualquier otra) excepción. También podría formatear su disco duro y reírse burlonamente :-)

Si desea implementar tal bestia, podría usar algo como intDivEx en el siguiente programa:

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

Esto produce:

5 Divide by zero exception -> 5

y puede ver que arroja y atrapa la excepción de la división por cero.

El % equivalente es casi exactamente el mismo:

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



Por lo que sé, las especificaciones de C ++ no mencionan nada acerca de dividir por cero excepción. Creo que debes hacerlo tú mismo ...

Stroustrup dice, en "El diseño y la evolución de C ++" (Addison Wesley, 1994), "se supone que los eventos de bajo nivel, como los desbordamientos aritméticos y la división por cero, son manejados por un mecanismo dedicado de nivel inferior en lugar de por excepciones Esto permite que C ++ haga coincidir el comportamiento de otros lenguajes cuando se trata de aritmética, y también evita los problemas que ocurren en las arquitecturas de gran cantidad de pipas donde eventos como dividir por cero son asincrónicos ".


Puedes hacer assert(2 * i != i) que arrojará una afirmación. Puedes escribir tu propia clase de excepción si necesitas algo más elegante.


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

O necesita throw la excepción y catch . p.ej

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

O catch la excepción que arroja tu código.

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

En su caso, no estoy seguro de si existe alguna excepción estándar para dividir por cero. Si no existe tal excepción, entonces puede usar,

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


Actualizado con comentarios de ExcessPhase

GCC (al menos la versión 4.8) le permitirá emular este comportamiento:

#include <signal.h> #include <memory> #include <iostream> 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; std::cin >> i; // what if someone enters zero? try { i = 5/i; } catch (std::logic_error e) { std::cerr << e.what(); } }

Esto configura un nuevo manejador de señal que arroja una excepción y un shared_ptr al antiguo manejador de señal, con una función de "eliminación" personalizada que restaura el controlador anterior cuando se sale del alcance.

Necesitas compilar con al menos estas opciones:

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

Visual C ++ también te permitirá hacer algo similar:

#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(); } }

Y, por supuesto, puede omitir todo el C ++ 11-ishness de esto y ponerlos en una estructura de gestión de RAII tradicional.