Tratamento de exceções no C++ usando try e catch

Programas sempre estão sujeitos a erros. Alguns erros potenciais nós conseguimos identificar e evitar em nosso algoritmo, mas o ideal seria tratar esses erros para caso os esqueçamos em um momento posterior. Nesse sentido o C++ oferece o recurso de tratamento de exceções composto por essas três instruções: try, catch e throw.

Para ilustrar o uso desse recurso, vamos considerar uma situação comum de erros que é a divisão por zero. O algoritmo a seguir ilustra a operação de divisão sujeita a divizão por zero.

#include <iostream>

using namespace std;

float divide(float x, float y) {
    return x / y;
}

int main() {
    int a, b;
    cout << "Digite os valores: ";
    cin >> a >> b;

    cout << divide(a, b);

    return 0;
}

Na função divide() existe a possibilidade do segundo argumento ser zero e gerar um erro na divisão. Então adicicionamos o tratamento de exceção a essa operação.  Veja se no bloco try foi adicionado um teste com o segundo valor (o valor do denominador) e verificando se ele é igual a zero. Se ele for igual a zero é lançado, utilizando o comando throw, o erro com o valor “1” (conforme a linha 4 do código abaixo). Esse erro lançado será capturado pelo bloco do catch, sendo o erro lançado recebido no argumento (no caso do exemplo ele está sendo chamado de erro e é um valor inteiro).

float divide(float x, float y) {
    try {
        if(y == 0) {
            throw 1;
        } else {
            return a/b;
        }
    } catch(int erro) {
        if (erro == 1) {
            cout << "Erro de divisao por zero" << endl;
        }
    }
}

No bloco catch foi testado o valor do erro para mostrar a mensagem apropriada sobre o erro. Nesse caso somente um erro foi identificado, então o teste não precisaria ser feito, deixei apenas para ilustrar a possibilidade. Se várias exceções fossem possíveis, então seria interessante lançá-las com códigos diferentes para mostrar mensagens apropriadas.

Um problema com a função definida é que ela retorna um valor definido apenas caso seja possível fazer a divisão, caso contrário ela retornará qualquer valor. Após o try catch é possível continuar o código sem problemas. No caso do código abaixo foi pedido para retornar zero.

float divide(float x, float y) {
    try {
        if(y == 0) {
            throw 1;
        } else {
            return x/y;
        }
    } catch(int erro) {
        if (erro == 1) {
            cout << "Erro de divisao por zero" << endl;
        }
    }
    return 0;
}

Veja que zero não é realmente uma boa opção de retorno pois zero pode ser um resultado possível de uma divisão (por exemplo zero dividido por 5). Um tratamento melhor nesse caso é mostrado no código a seguir. No código, a função divide() utiliza o throw para lançar o erro para fora da função e esse pode ser capturado na função principal e tratado como foi tratado no código anterior.

#include <iostream>

using namespace std;

float divide(float x, float y) {
    if (y == 0) {
        throw 1;
    } else {
        return x/y;
    }
}

int main() {
    int a, b;
    cout << "Digite os valores: ";
    cin >> a >> b;

    try {
        cout << divide(a, b);
    } catch(int erro) {
        if (erro == 1) {
            cout << "Erro de divisao por zero" << endl;
        }
    }

    return 0;
}

Complementando ainda mais o código, supondo que você queria que o usuário informe um valor válido para fazer a operação e, enquanto ele não fornecer um valor valor, continuar solicitando um valor válido. O código abaixo envolve o bloco try catch em um laço de repetição controlado por uma variável chamada error.

int main() {
    int a, b;
    bool error = false;
    cout << "Digite os valores: ";
    cin >> a >> b;

    do {
        try {
            cout << divide(a, b);
            error = false;
        } catch(int erro) {
            if (erro == 1) {
                cout << "Erro por divisao por zero. Digite outro valor: ";
                cin >> b;
            }
            error = true;
        }
    } while (error);

    return 0;
}

Espero que o tutorial tenha sido útil. Dúvidas, deixe nos comentários.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.