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; //correttaint 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++:
#includereusando 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:
#includereusando 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:
#includereusando 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:
#includereusando 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:
#includereusando 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:
#includereusando 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) noeccettoif (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 throwdigitare 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:
#includereusando 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.