Contenuto del capitolo |
---|
|
Tradizionalmente quando i programmatori fanno qualche cosa, ad esempio chiamano una funzione, il risultato può essere verificato per accertarne la validità. Ad esempio se cercate di aprire un file che non esiste il risultato può essere un valore nullo. Ci sono due possibili strategie per trattare questo tipo di situazione:
In entrambi i casi viene lasciato al programmatore il compito di verificare se si è verificato un errore ed eventualmente eseguire un'azione appropriata.
In BASIC si potrebbe fare cosí:
OPEN "A:\DATI.TXT" FOR INPUT AS #1 IF ERR = 53 THEN CALL ErroreFileInesistente ELSE REM SI CONTINUA CON LE OPERAZIONI SUL FILE END IF
Questo in programmi di qualità professionale può portare ad avere oltre metà del codice dedicato a verificare il risultato di ciascuna azione per identificare errori. Questo può risultare pesante e rende il codice difficile da leggere (anche se in pratica la maggior parte dei programmi funzionano proprio cosí). Un approccio sistematico è in questo caso indispensabile ad evitare errori banali.
In ambienti di programmazione più recenti è stato sviluppato un modo alternativo di trattare gli errori. Questo è conosciuto come gestione delle eccezioni e funziona consentendo ad una funzione di lanciare (throw, N.d.t.) o alzare (raise, N.d.t.) una eccezione (exception, N.d.t.). Il sistema in tal caso abbandona il blocco di codice che sta eseguendo e passa al più prossimo blocco di codice per la gestione delle eccezioni. Il sistema fornisce un gestore standard che riceve (catch, Nd.t.) tutte le eccezioni e solitamente esce dopo aver scritto un messaggio di errore.
Il blocco per la gestione delle eccezioni, invece viene scritto in modo molto simile ad un blocco if...then...else:
try: # Qui ci va il codice per l'esecuzione normale except EccezioneTipo1: # Qui ci va il trattamento per un tipo di eccezione except EccezioneTipo2: # Qui ci va il trattamento per un'altro tipo di eccezione else: # Qui si effettuano le operazioni per il caso # in cui non si verificano eccezioni
Esiste un secondo tipo di blocco per il trattamento delle eccezioni che consente di effettuare operazioni dopo che si è verificato un errore, si tratta del blocco try...finally ed è tipicamente usato per chiudere files, trasferire buffers sul disco ecc. Il blocco finally viene sempre eseguito per ultimo indipendentemente da ciò che si è verificato nella sezione try.
try: # Flusso del programma normale finally: # Questo viene eseguito indipendentemente # dal successo o dal fallimento del blocco try
Il Tcl possiede un meccanismo simile che usa la parola chiave catch:
set codicerrore [catch {
unset x
} msg ]
if {$codicerrore != 0} {
# Qui si tratta l'errore
}
In questo caso x non esiste quindi l'istruzione unset non può essere applicata. Il Tcl lancia un'eccezione ma l'istruzione catch impedisce al programma di terminare ed invece scrive il messaggio di errore nella variabile msg e riporta un valore diverso da zero (che può essere definito dal programmatore). È possibile quindi verificare il valore definito da catch nella variabile codicerrore. Se è diverso da zero significa che si è verificato un errore ed è possibile esaminare la variabile msg per i dettagli.
Il BASIC non prevede la gestione delle eccezioni ma fornisce un costrutto che aiuta a matenere "pulito" il codice:
100 OPEN "A:\Temp.dat" FOR INPUT AS #1
110 ON ERROR GOTO 10010
120 REM QUI CI VA IL CODICE DEL PROGRAMMA
130 ...
10000 REM GESTIONE ERRORI:
10010 IF ERR = 54 THEN....
Si noti l'uso dei numeri di linea. Questa era una prassi comune nei primi linguaggi di programmazione, incluso il BASIC. Adesso è possibile ottenere lo stesso risultato usando le etichette:
ON ERROR GOTO Handler
REM Qui viene generato un errore "divisione per zero"
x = 5/0
Handler:
IF ERR = 23 THEN
PRINT "E' vietato dividere per 0"
x = 0
RESUME NEXT
END IF
Si noti l'istruzione RESUME NEXT che consente di tornare esattamente al punto successivo all'errore e proseguire con il programma.
Supponiamo di voler generare una eccezione che debba essere ricevuta da qualcun altro, ad esempio all'interno di un modulo. In Python si usa la parola chiave raise:
numeratore = 42 denominatore = input("Per quale valore devo dividere '42'?") if denominatore == 0: raise "zero denominatore"
Questo genera una eccezione di tipo stringa che può essere ricevuta da un blocco try/except.
In Tcl l'istruzione return accetta un'opzione -code che viene catturata da ogni istruzione catch che la racchiude:
proc prosciutto {val} { set x $val return -code 3 [expr $x] } set errore [catch { set pippo [prosciutto 7] } messaggio]
errore dovrebbe assumere il valore 3 e messaggio il valore 7. Ecco un altro caso in cui la sintassi di Tcl risulta piuttosto poco intuitiva.
In BASIC è possibile assegnare un valore alla variabile ERR mediante l'istruzione ERROR:
ON ERROR GOTO ERRORI INPUT "INTRODUCI IL CODICE DI ERRORE"; E ERROR E ERRORI: IF ERR = 142 THEN PRINT "Generato Errore 142" STOP ELSE PRINT "Nessun errore" STOP END IF
Promemoria |
---|
|
Se avete domande o suggerimenti relativi a questa pagina
mandate un e-mail all'autore:
alan.gauld@yahoo.co.uk
o al traduttore italiano:
lfini@arcetri.astro.it