Fácil C++
Divisão segura com exceção
Enunciado
Escreva uma função safe_divide que recebe dois double e retorna a / b. Se b for zero, lance std::invalid_argument com a mensagem "divisao por zero". No main, chame a função com (10, 2) e (5, 0), capturando a exceção e imprimindo a mensagem.
Requisitos
- A função
safe_dividedeve lançarstd::invalid_argumentquandob == 0. - O
catchdeve capturarconst std::exception&e imprimire.what(). - O programa deve continuar após a exceção e imprimir
"Fim".
Código inicial
#include <iostream>
#include <stdexcept>
double safe_divide(double a, double b) {
// TODO: lance std::invalid_argument se b for zero
return a / b;
}
int main() {
// TODO: chame safe_divide e capture exceções
return 0;
}
Saída esperada
10 / 2 = 5
Erro: divisao por zero
Fim
Ver dica
Use throw std::invalid_argument("divisao por zero"); e no main envolva as chamadas em try { ... } catch (const std::exception& e) { ... }.
Mostrar solução
#include <iostream>
#include <stdexcept>
double safe_divide(double a, double b) {
if (b == 0.0)
throw std::invalid_argument("divisao por zero"); // lança exceção
return a / b;
}
int main() {
try {
std::cout << "10 / 2 = " << safe_divide(10, 2) << '\n';
std::cout << "5 / 0 = " << safe_divide(5, 0) << '\n'; // lança
} catch (const std::exception& e) {
std::cout << "Erro: " << e.what() << '\n';
}
std::cout << "Fim\n";
return 0;
}
Passo a passo
- Incluímos
<stdexcept>para ter acesso astd::invalid_argument. - A função
safe_divideverifica sebé zero; se for, lança uma exceção com mensagem descritiva. - No
main, a primeira chamadasafe_divide(10, 2)ocorre normalmente e imprime10 / 2 = 5. - A segunda chamada
safe_divide(5, 0)lançastd::invalid_argument. - O fluxo sai imediatamente do
trye entra nocatch (const std::exception& e). - Dentro do
catch, imprimimose.what(), que retorna a mensagem"divisao por zero". - Após o
catch, a execução continua e imprimeFim.
Por que funciona
O throw interrompe o fluxo normal e procura um catch compatível na pilha de chamadas. Como std::invalid_argument herda de std::exception, o catch por referência captura a exceção sem slicing e permite acessar what(). O programa não aborta porque a exceção foi tratada.
Erros comuns
- Capturar por valor:
catch (std::exception e)causa slicing e perde informações da classe derivada. Useconst std::exception&. - Esquecer de incluir
<stdexcept>: o compilador não conhecestd::invalid_argument. - Lançar tipo primitivo:
throw "divisao por zero";lançaconst char*, que não é capturado porstd::exception. Prefira classes da biblioteca padrão. - Não tratar a exceção: se ninguém capturar,
std::terminateé chamado e o programa aborta.
Outra forma de resolver
Poderia capturar especificamente std::invalid_argument:
catch (const std::invalid_argument& e) {
std::cout << "Erro: " << e.what() << '\n';
}
Isso é útil quando se deseja tratar tipos diferentes de exceção de maneiras distintas.
Saída esperada
10 / 2 = 5
Erro: divisao por zero
Fim