C++

Gestione delle eccezioni in C++

Gestione delle eccezioni in C++
Esistono tre tipi di errori software. Questi sono errori di sintassi, errori logici ed errori di runtime.

Errori di sintassi

Un'espressione, un'istruzione o una costruzione digitata in modo errato è un errore di sintassi.

Considera le due seguenti affermazioni:

int arr[] = 1, 2, 3; //corretta
int arr = 1, 2, 3; //errore di sintassi, mancante []

Sono definizioni dello stesso array. La prima è corretta. Manca il secondo [], e questo è un errore di sintassi. Un programma con un errore di sintassi non riesce a compilare. La compilazione fallisce con un messaggio di errore che indica l'errore di sintassi. La cosa buona è che un errore di sintassi può sempre essere corretto se il programmatore sa cosa sta facendo.

Errore logico

Un errore logico è un errore commesso dal programmatore quando viene eseguita una codifica logica errata. Potrebbe essere il risultato dell'ignoranza del programmatore sulle funzionalità del linguaggio di programmazione o di un malinteso su ciò che il programma dovrebbe fare.

In questa situazione, il programma viene compilato con successo. Il programma funziona bene, ma produce risultati errati. Un tale errore potrebbe essere dovuto al fatto che un ciclo itera 5 volte quando viene fatto iterare 10 volte. Può anche essere che un ciclo sia inconsciamente fatto per iterare all'infinito. L'unico modo per risolvere questo tipo di errore è eseguire un'attenta programmazione e testare accuratamente il programma prima di consegnarlo al cliente.

Errori di runtime

Ingressi errati o eccezionali causano errori di runtime. In questo caso, il programma è stato compilato con successo e funziona bene in molte situazioni. In determinate situazioni, il programma va in crash (e si ferma).

Immagina che in un segmento di codice di programma, 8 debba essere diviso per un numero di denominatori. Quindi se il numeratore 8 è diviso per il denominatore 4, la risposta (quoziente) sarebbe 2. Tuttavia, se l'utente immette 0 come denominatore, il programma andrebbe in crash. La divisione per 0 non è consentita in matematica e non è consentita nemmeno in informatica. La divisione per zero dovrebbe essere evitata nella programmazione. La gestione delle eccezioni gestisce gli errori di runtime, come la divisione per zero. Il seguente programma mostra come gestire il problema della divisione per zero senza utilizzare la funzione di eccezione in C++:

#includere
usando lo spazio dei nomi std;
intero principale()

int numeratore = 8;
int denominatore = 2;
se (denominatore != 0 )

int risultato = numeratore/denominatore;
cout << result << '\n';

altro

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

restituisce 0;

L'uscita è 4. Se il denominatore fosse 0, l'output sarebbe stato:

“La divisione per zero non è consentita!"

Il codice principale qui è un costrutto if-else. Se il denominatore non è 0, la divisione avverrà; se è 0, la divisione non avrà luogo. Verrà inviato un messaggio di errore all'utente e il programma continuerà a funzionare senza arresti anomali. Gli errori di runtime vengono generalmente gestiti evitando l'esecuzione di un segmento di codice e inviando un messaggio di errore all'utente.

La funzione di eccezione in C++ utilizza un blocco try per il blocco if e un blocco catch per il blocco else per gestire l'errore, proprio come segue:

#includere
usando lo spazio dei nomi std;
intero principale()

int numeratore = 8;
int denominatore = 2;
provare

se (denominatore != 0 )

int risultato = numeratore/denominatore;
cout << result << '\n';

altro

lanciare 0;


cattura (int err)

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

restituisce 0;

Nota che l'intestazione di prova non ha un argomento. Nota anche che il catch-block, che è come una definizione di funzione, ha un parametro. Il tipo di parametro deve essere lo stesso dell'operando (argomento) dell'espressione throw. L'espressione di lancio è nel blocco di prova. Genera un argomento a scelta del programmatore correlato all'errore e il blocco catch lo rileva catch. In questo modo, il codice nel blocco try non viene eseguito. Quindi, il catch-block visualizza il messaggio di errore.

Questo articolo spiega la gestione delle eccezioni in C++. La conoscenza di base in C++ è un prerequisito per il lettore per comprendere questo articolo.

Contenuto dell'articolo:

  • Funzione che genera un'eccezione
  • Più di un blocco di cattura per un blocco di prova
  • Blocchi prova/cattura nidificati
  • specificatore-no-eccetto
  • La funzione speciale std::terminate()
  • Conclusione

Funzione che genera un'eccezione:

Una funzione può anche lanciare un'eccezione proprio come fa il try-block. Il lancio avviene all'interno della definizione della funzione. Il seguente programma lo illustra:

#includere
usando lo spazio dei nomi std;
void fn(const char* str)

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

intero principale()

provare

fn("fabbro");

prendere (char ch)

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

restituisce 0;

Nota che questa volta, il blocco try ha solo la chiamata di funzione. È la funzione chiamata che ha l'operazione di lancio. Il blocco catch cattura l'eccezione e l'output è:

“Il nome della persona non può iniziare in minuscolo!"

Questa volta, il tipo lanciato e catturato è un char.

Più di un blocco di cattura per un blocco di prova:

Ci può essere più di un catch-block per un try-block. Immagina la situazione in cui un input può essere uno qualsiasi dei caratteri della tastiera, ma non una cifra e non un alfabeto. In questo caso, devono esserci due blocchi catch: uno per un intero per controllare la cifra e uno per un carattere per controllare l'alfabeto. Il codice seguente lo illustra:

#includere
usando lo spazio dei nomi std;
char input = '*';
intero principale()

provare

if (isdigit(input))
lanciare 10;
if (isalpha(input))
lanciare 'z';

prendere (int)

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

prendere (char)

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

restituisce 0;

Non c'è uscita. Se il valore di input fosse una cifra, e.g., '1', l'output sarebbe stato:

"L'immissione di cifre è vietata!"

Se il valore di input fosse un alfabeto, e.g., 'a', l'output sarebbe stato:

"L'immissione di caratteri è vietata!"

Nota che nell'elenco dei parametri dei due blocchi catch, non c'è un nome identificativo. Si noti inoltre che nella definizione dei due catch-block, i particolari argomenti lanciati non sono stati verificati se i loro valori sono esatti o meno.

Ciò che conta per una cattura è il tipo; una cattura deve corrispondere al tipo di operando lanciato. Il particolare valore dell'argomento (operando) lanciato può essere utilizzato per ulteriori verifiche, se necessario.

Più di un gestore per lo stesso tipo

È possibile avere due gestori dello stesso tipo. Quando viene generata un'eccezione, il controllo viene trasferito al gestore più vicino con un tipo corrispondente. Il seguente programma lo illustra:

#includere
usando lo spazio dei nomi std;
char input = '1';
intero principale()

provare

if (isdigit(input))
lanciare 10;

prendere (int)

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

prendere (int)

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

restituisce 0;

L'uscita è:

"L'immissione di cifre è vietata!"

Blocchi prova/cattura nidificati:

i blocchi try/catch possono essere annidati. Si ripete qui il programma sopra per l'inserimento di caratteri non alfanumerici da tastiera, ma con il codice di errore alfabetico nidificato:

#includere
usando lo spazio dei nomi std;
char input = '*';
intero principale()

provare

if (isdigit(input))
lanciare 10;
provare

if (isalpha(input))
lanciare 'z';

prendere (char)

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


prendere (int)

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

restituisce 0;

L'errore alfabetico try/catch-block è annidato nel try-block del codice numerico. Il funzionamento di questo programma e l'operazione precedente da cui viene copiato sono le stesse.

specificatore-no-eccetto

Considera la seguente funzione:

void fn(const char* str) noeccetto

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

Notare l'identificatore 'noException' subito dopo la parentesi destra dell'elenco dei parametri della funzione. Ciò significa che la funzione non dovrebbe generare un'eccezione. Se la funzione genera un'eccezione, come in questo caso, verrà compilata con un messaggio di avviso ma non verrà eseguita. Un tentativo di eseguire il programma chiamerà la funzione speciale std::terminate(), che dovrebbe arrestare il programma con grazia invece di consentirgli di andare letteralmente in crash.

L'identificatore noetc è in forme diverse different. Questi sono i seguenti:

digita func() noeccetto; : non consente un'espressione throw
digitare func() noException(true); : consente un'espressione throw
digita func() throw(); : non consente un'espressione throw
digita func() noex(false); : consente un'espressione throw, che è facoltativa
digita funzione(); : consente un'espressione throw, che è facoltativa

vero o falso tra parentesi può essere sostituito da un'espressione che risulta vero o falso.

La funzione speciale std::terminate():

Se un'eccezione non può essere gestita, dovrebbe essere generata nuovamente. In questo caso, l'espressione generata può avere o meno un operando. La funzione speciale std::terminate() verrà chiamata in fase di esecuzione, il che dovrebbe arrestare il programma con grazia invece di consentirgli di andare letteralmente in crash.

Digita, compila ed esegui il seguente programma:

#includere
usando lo spazio dei nomi std;
char input = '1';
intero principale()

provare

if (isdigit(input))
lanciare 10;

prendere (int)

gettare;

restituisce 0;

Dopo una compilazione riuscita, il programma è terminato senza essere eseguito e il messaggio di errore dal computer dell'autore è:

“terminare chiamato dopo aver lanciato un'istanza di 'int'

Interrotto (core dump)”

Conclusione:

La funzionalità di eccezione in C++ impedisce l'esecuzione di un segmento di codice in base a un qualche tipo di input. Il programma continua ad essere eseguito se necessario. Il costrutto di eccezione (prevenzione degli errori) consiste in un try-block e un catch-block. Il try-block ha il segmento di codice di interesse, che può essere bypassato, a seconda di alcune condizioni di input. Il blocco try ha l'espressione throw, che lancia un operando. Questo operando è anche chiamato eccezione. Se il tipo di operando e il tipo per il parametro del blocco catch coincidono, l'eccezione viene rilevata (gestita). Se l'eccezione non viene rilevata, il programma verrà terminato, ma comunque sii sicuro poiché il segmento di codice che doveva essere eseguito per dare il risultato sbagliato non è stato eseguito. La tipica gestione delle eccezioni significa bypassare il segmento di codice e inviare un messaggio di errore all'utente. Il segmento di codice viene eseguito per input normale ma bypassato per input errati.

Rimappa i pulsanti del mouse in modo diverso per software diversi con X-Mouse Button Control
Forse hai bisogno di uno strumento che possa cambiare il controllo del tuo mouse con ogni applicazione che utilizzi. In questo caso, puoi provare un'a...
Recensione del mouse wireless Microsoft Sculpt Touch
Ho letto di recente del Microsoft Scolpisci il tocco mouse wireless e ho deciso di acquistarlo. Dopo averlo usato per un po', ho deciso di condividere...
Trackpad e puntatore del mouse su schermo AppyMouse per tablet Windows
Gli utenti di tablet spesso mancano il puntatore del mouse, soprattutto quando sono abituati a usare i laptop laptop. Gli smartphone e i tablet touchs...