Manuseio de exceção em C ++

Manuseio de exceção em C ++
Existem três tipos de erros de software que existem. Estes são erros de sintaxe, erros lógicos e erros de tempo de execução.

Erros de sintaxe

Uma expressão, declaração ou construção digitada incorretamente é um erro de sintaxe.

Considere as duas declarações a seguir:

int arr [] = 1, 2, 3; //correto
int arr = 1, 2, 3; // Erro de sintaxe, ausente []

São definições da mesma matriz. O primeiro está correto. O segundo está faltando [], e isso é um erro de sintaxe. Um programa com um erro de sintaxe não consegue compilar. A compilação falha com uma mensagem de erro indicando o erro de sintaxe. O bom é que um erro de sintaxe sempre pode ser corrigido se o programador souber o que está fazendo.

Erro lógico

Um erro lógico é um erro cometido pelo programador quando alguma codificação lógica errada é feita. Pode ser o resultado da ignorância do programador para os recursos da linguagem de programação ou um mal -entendido do que o programa deve fazer.

Nesta situação, o programa é compilado com sucesso. O programa funciona bem, mas produz resultados errados. Tal erro pode ser por causa de um loop iterate 5 vezes quando é feito para iterar 10 vezes. Também pode ser que um loop seja inconscientemente feito para iterar infinitamente. A única maneira de resolver esse tipo de erro é fazer uma programação cuidadosa e testar o programa cuidadosamente antes de entregá -lo ao cliente.

Erros de tempo de execução

Entradas erradas ou excepcionais causam erros de tempo de execução. Nesse caso, o programa foi compilado com sucesso e funciona bem em muitas situações. Em determinadas situações, o programa trava (e para).

Imagine que em um segmento de código de programa, 8 deve ser dividido por vários denominadores. Portanto, se o numerador 8 for dividido pelo denominador 4, a resposta (quociente) seria 2. No entanto, se o usuário inserir 0 como denominador, o programa falharia. A divisão por 0 não é permitida em matemática e também não é permitida na computação. Divisão por zero deve ser evitada na programação. O manuseio de exceção lida com erros de tempo de execução, como divisão por zero. O programa a seguir mostra como lidar com o problema de divisão por zero sem usar o recurso de exceção em C ++:

#incluir
usando namespace std;
int main ()

int numerator = 8;
int denominador = 2;
if (denominador != 0)

int resultado = numerador/denominador;
cout << result << '\n';

outro

cout << "Division by zero is not permitted!" << '\n';

retornar 0;

A saída é 4. Se o denominador fosse 0, a saída teria sido:

“A divisão por zero não é permitida!”

O código principal aqui é um construto if-else. Se o denominador não for 0, a divisão ocorrerá; Se for 0, a divisão não ocorrerá. Uma mensagem de erro será enviada ao usuário e o programa continua a ser executado sem travar. Os erros de tempo de execução geralmente são tratados evitando a execução de um segmento de código e enviando uma mensagem de erro ao usuário.

O recurso de exceção no C ++ usa um bloqueio para o bloco if e um bloco de captura para o bloco de eliminação para lidar com o erro, exatamente como:

#incluir
usando namespace std;
int main ()

int numerator = 8;
int denominador = 2;
tentar

if (denominador != 0)

int resultado = numerador/denominador;
cout << result << '\n';

outro

jogue 0;


Catch (int err)

if (err == 0)
cout << "Division by zero is not permitted!" << '\n';

retornar 0;

Observe que o cabeçalho de tentativa não tem um argumento. Observe também que o bloco de captura, que é como uma definição de função, tem um parâmetro. O tipo de parâmetro deve ser o mesmo que o operando (argumento) da expressão de arremesso. A expressão de arremesso está no bloco de tentativa. Ele apresenta um argumento da escolha do programador que está relacionado ao erro, e o bloco de captura o pega. Dessa forma, o código no bloco de tentativa não é executado. Então, o bloco de captura exibe a mensagem de erro.

Este artigo explica o tratamento de exceções em C++. O conhecimento básico em C ++ é um pré -requisito para o leitor entender este artigo.

Conteúdo do artigo:

  • Função jogando uma exceção
  • Mais de um bloco de captura para um bloqueio de tentativa
  • Blocos de tentativa/captura aninhados
  • NoExcept-especificador
  • A função Special STD :: encerrinate ()
  • Conclusão

Função jogando uma exceção:

Uma função também pode lançar uma exceção como o que o bloqueio de tentativa faz. O arremesso ocorre dentro da definição da função. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
void fn (const char* str)

if (islower (str [0]))
jogar 'l';

int main ()

tentar

fn ("Smith");

Catch (char ch)

if (ch == 'l')
cout << "Person's name cannot begin in lowercase!" << '\n';

retornar 0;

Observe que desta vez, o bloco de tentativa tem apenas a chamada de função. É a função chamada que tem a operação de arremesso. O bloco de captura pega a exceção e a saída é:

“O nome da pessoa não pode começar em minúsculas!”

Desta vez, o tipo jogado e capturado é um char.

Mais de um bloco de captura para um bloco de tentativa:

Pode haver mais de um bloco de captura para um bloqueio de tentativa. Imagine a situação em que uma entrada pode ser qualquer um dos caracteres do teclado, mas não um dígito e não um alfabeto. Nesse caso, deve haver dois blocos de captura: um para um número inteiro verificar o dígito e outro para um char de checar o alfabeto. O código a seguir ilustra o seguinte:

#incluir
usando namespace std;
char input = '*';
int main ()

tentar

if (isdigit (entrada))
jogar 10;
if (isalpha (entrada))
jogar 'z';

Catch (int)

cout << "Digit input is forbidden!" << '\n';

Catch (char)

cout << "Character input is forbidden!" << '\n';

retornar 0;

Não há saída. Se o valor da entrada fosse um dígito, e.g., '1', a saída teria sido:

"A entrada de dígitos é proibida!"

Se o valor da entrada fosse um alfabeto, e.g., 'a', a saída teria sido:

"A entrada do personagem é proibida!"

Observe que na lista de parâmetros dos dois blocos de captura, não há nome de identificador. Observe também que, na definição dos dois blocos de captura, os argumentos específicos lançados não foram verificados se seus valores são exatos ou não.

O que importa para uma captura é o tipo; Uma captura deve corresponder ao tipo de operando jogado. O valor particular do argumento (operando) jogado pode ser usado para verificação adicional, se necessário.

Mais de um manipulador para o mesmo tipo

É possível ter dois manipuladores do mesmo tipo. Quando uma exceção é lançada, o controle é transferido para o manipulador mais próximo com um tipo de correspondência. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
Char input = '1';
int main ()

tentar

if (isdigit (entrada))
jogar 10;

Catch (int)

cout << "Digit input is forbidden!" << '\n';

Catch (int)

cout << "Not allowed at all: digit input!" << '\n';

retornar 0;

A saída é:

"A entrada de dígitos é proibida!"

Blocos de tentativa/captura aninhados:

Blocos de tentativa/captura podem ser aninhados. O programa acima para a entrada de caracteres não alfanuméricos do teclado é repetido aqui, mas com o código de erro alfabético aninhado:

#incluir
usando namespace std;
char input = '*';
int main ()

tentar

if (isdigit (entrada))
jogar 10;
tentar

if (isalpha (entrada))
jogar 'z';

Catch (char)

cout << "Character input is forbidden!" << '\n';


Catch (int)

cout << "Digit input is forbidden!" << '\n';

retornar 0;

O erro de tentativa alfabética/bloco de captura é aninhado no bloco de tentativa do código do dígito. A operação deste programa e a operação anterior da qual é copiada são iguais.

NoExcept-especificador

Considere a seguinte função:

void fn (const char* str) NoExcept

if (islower (str [0]))
jogar 'l';

Observe o especificador 'NoExcept' logo após o parêntese correto da lista de parâmetros da função. Isso significa que a função não deve lançar uma exceção. Se a função lançar uma exceção, como neste caso, ela será compilada com uma mensagem de aviso, mas não será executada. Uma tentativa de executar o programa chamará a função especial std :: encernine (), que deve interromper o programa graciosamente, em vez de apenas permitir que ele tenha lutado literalmente.

O especificador NoExcept está em diferentes formas. Estes são os seguintes:

tipo func () noexcept; : não permite uma expressão de arremesso
tipo func () noexcept (true); : permite uma expressão de arremesso
tipo func () throw (); : não permite uma expressão de arremesso
tipo func () noexcept (false); : permite uma expressão de arremesso, que é opcional
tipo func (); : permite uma expressão de arremesso, que é opcional

verdadeiro ou falso nos parênteses pode ser substituído por uma expressão que resulta em verdadeiro ou falso.

A função especial std :: encernine ():

Se uma exceção não puder ser manuseada, deve ser re-arruinada. Nesse caso, a expressão jogada pode ou não ter um operando. A função especial std :: encernine () será chamada no tempo de execução, o que deve interromper o programa graciosamente, em vez de apenas permitir que ele tenha lutado literalmente.

Digite, compilar e execute o seguinte programa:

#incluir
usando namespace std;
Char input = '1';
int main ()

tentar

if (isdigit (entrada))
jogar 10;

Catch (int)

lançar;

retornar 0;

Após uma compilação bem -sucedida, o programa terminou sem execução e a mensagem de erro do computador do autor é:

“Encerrar chamado depois de jogar uma instância de 'int'

Abortado (core despejado) ”

Conclusão:

O recurso de exceção em C ++ impede que um segmento de código seja executado com base em algum tipo de entrada. O programa continua a executar conforme necessário. A construção de exceção (prevenção de erros) consiste em um bloco de tentativa e um bloco de captura. O bloqueio de tentativa tem o segmento de interesse do código, que pode ser ignorado, dependendo de alguma condição de entrada. O bloqueio de tentativa tem a expressão de arremesso, que lança um operando. Este operando também é chamado de exceção. Se o tipo de operando e o tipo para o parâmetro do bloco de captura forem iguais, a exceção será capturada (manuseada). Se a exceção não for capturada, o programa será encerrado, mas ainda assim, estará seguro, pois o segmento de código que deveria ser executado para dar o resultado errado não foi executado. O manuseio de exceção típico significa ignorar o segmento de código e enviar uma mensagem de erro ao usuário. O segmento de código é executado para entrada normal, mas ignorada para entradas erradas.