Istruzione Condizionale case in Object Pascal
- L'istruzione
case
in Object Pascal consente di selezionare uno tra molti percorsi di esecuzione basati sul valore di una singola espressione di tipo ordinale. - La sintassi generale dell'istruzione
case
include l'espressione da valutare, una serie di clausole con valori costanti e un'istruzione opzionaleelse
per gestire i casi non previsti. - Le clausole dell'istruzione
case
possono includere più valori separati da virgole o intervalli di valori utilizzando la sintassivaloreInizio..valoreFine
. - L'istruzione
case
migliora la leggibilità e la manutenibilità del codice rispetto a una serie di istruzioniif...then...else
annidate.
Istruzione case
Vi sono casi in cui le istruzioni if
possono diventare piuttosto complesse, specialmente quando si devono testare molti valori diversi di una singola variabile. In questi casi, l'uso di più clausole if...then...else
, nonché di istruzioni else if
annidate, può rendere il codice difficile da leggere e da manutenere.
Esiste un modo più semplice per gestire tali situazioni in molti linguaggi di programmazione, incluso Object Pascal. Questo metodo è l'istruzione case
, che in altri linguaggi è nota come switch
. L'istruzione case
consente di selezionare uno tra molti percorsi di esecuzione in base al valore di una singola espressione. La restrizione, però, è che l'espressione deve essere di un tipo ordinale, come un intero, un carattere o un enumerato.
Un'istruzione case
consiste di un'espressione usata per selezionare un valore e una lista di possibili valori, o un intervallo di valori. Questi valori sono costanti, e devono essere unici e di un tipo ordinale. Eventualmente, può esserci un'istruzione else
che viene eseguita se nessuno dei valori specificati corrisponde al valore del selettore.
Mentre non c'è una specifica istruzione endcase, che termini la serie di valori, un case
è sempre terminato da un end
(che in questo caso non è un terminatore di blocco, dato che non c'è un begin corrispondente).
La sintassi generale di un'istruzione case
in Object Pascal è la seguente:
case <espressione> of
<valore1>: <istruzione1>;
<valore2>: <istruzione2>;
...
<valoreN>: <istruzioneN>;
else
<istruzioneElse>;
end;
L'istruzione case
richiede un valore ordinale
Creare un'istruzione case richiede un valore ordinale. Un'istruzione case
basata su un valore stringa non è permessa. In quel caso è necessario usare istruzioni if annidate o una struttura dati diversa, come un dizionario che vedremo nelle prossime lezioni.
Ricapitolando:
Istruzione condizionale case
Un'istruzione case
consente di selezionare uno tra molti percorsi di esecuzione in base al valore di una singola espressione di tipo ordinale. La sintassi generale è la seguente:
case <espressione> of
<valore1>: <istruzione1>;
<valore2>: <istruzione2>;
...
<valoreN>: <istruzioneN>;
else
<istruzioneElse>;
end;
Dove:
<espressione>
è un'espressione di tipo ordinale il cui valore determina quale ramo dell'istruzionecase
verrà eseguito.<valore1>
,<valore2>
, ...,<valoreN>
sono costanti uniche di tipo ordinale che rappresentano i possibili valori dell'espressione.<istruzione1>
,<istruzione2>
, ...,<istruzioneN>
sono le istruzioni o i blocchi di codice che verranno eseguiti se l'espressione corrisponde al rispettivo valore.else
è una clausola opzionale che specifica un'istruzione o un blocco di codice da eseguire se nessuno dei valori specificati corrisponde al valore dell'espressione.
Nel caso in cui l'espressione non corrisponda a nessuno dei valori elencati, e non sia presente una clausola else
, l'istruzione case
non eseguirà alcuna azione.
Esempio
Vediamo un primo semplice esempio di utilizzo dell'istruzione case
.
Vogliamo scrivere un programma che, dato in ingresso un numero intero compreso tra 1 e 10, restituisca il corrispondente nome in italiano del numero. Se il numero non è compreso tra 1 e 10, il programma deve restituire un messaggio di errore.
Se volessimo implementare questo programma usando le istruzioni if
, potremmo scrivere qualcosa del genere:
program ConvertiNumero;
var
numero: Integer;
nomeNumero: string;
begin
Write('Inserisci un numero intero tra 1 e 10: ');
ReadLn(numero);
if numero = 1 then
nomeNumero := 'uno'
else if numero = 2 then
nomeNumero := 'due'
else if numero = 3 then
nomeNumero := 'tre'
else if numero = 4 then
nomeNumero := 'quattro'
else if numero = 5 then
nomeNumero := 'cinque'
else if numero = 6 then
nomeNumero := 'sei'
else if numero = 7 then
nomeNumero := 'sette'
else if numero = 8 then
nomeNumero := 'otto'
else if numero = 9 then
nomeNumero := 'nove'
else if numero = 10 then
nomeNumero := 'dieci'
else
nomeNumero := 'Errore: il numero non è compreso tra 1 e 10';
WriteLn('Il numero in italiano è: ', nomeNumero);
end.
Come si può notare, il codice risulta piuttosto lungo e difficile da leggere a causa delle numerose clausole if...then...else
.
Possiamo riscrivere lo stesso programma utilizzando l'istruzione case
, ottenendo un codice più compatto e leggibile:
program ConvertiNumero2;
var
numero: Integer;
nomeNumero: string;
begin
Write('Inserisci un numero intero tra 1 e 10: ');
ReadLn(numero);
case numero of
1: nomeNumero := 'uno';
2: nomeNumero := 'due';
3: nomeNumero := 'tre';
4: nomeNumero := 'quattro';
5: nomeNumero := 'cinque';
6: nomeNumero := 'sei';
7: nomeNumero := 'sette';
8: nomeNumero := 'otto';
9: nomeNumero := 'nove';
10: nomeNumero := 'dieci';
else
nomeNumero := 'Errore: il numero non è compreso tra 1 e 10';
end;
WriteLn('Il numero in italiano è: ', nomeNumero);
end.
Il risultato è lo stesso, ma il codice è più chiaro ed è facilmente modificabile. Ad esempio, se volessimo aggiungere il numero 11, basterebbe aggiungere una sola riga all'interno dell'istruzione case
:
11: nomeNumero := 'undici';
Intervalli e Valori Multipli
L'istruzione case
in Object Pascal supporta anche l'uso di intervalli di valori e la specifica di più valori per un singolo ramo.
Per specificare più valori per un singolo ramo, si possono separare i valori con una virgola. Ad esempio:
case <espressione> of
valore1, valore2: <istruzione>;
{ ... }
end;
Mentre per specificare un intervallo di valori, si usa la sintassi valoreInizio..valoreFine
. Ad esempio:
case <espressione> of
valoreInizio..valoreFine: <istruzione>;
{ ... }
end;
Vediamo un esempio che utilizza entrambe queste funzionalità:
program ClassificaCarattere;
var
carattere: Char;
tipoCarattere: string;
begin
Write('Inserisci un carattere: ');
ReadLn(carattere);
case carattere of
'a', 'e', 'i', 'o', 'u': tipoCarattere := 'Vocale';
'b', 'c', 'd', 'f', 'g',
'h', 'j', 'k', 'l', 'm',
'n', 'p', 'q', 'r', 's',
't', 'v', 'w', 'x', 'y',
'z': tipoCarattere := 'Consonante';
'0'..'9': tipoCarattere := 'Cifra';
else
tipoCarattere := 'Altro carattere';
end;
WriteLn('Il carattere inserito è: ', tipoCarattere);
end.
In questo esempio, l'istruzione case
classifica il carattere inserito come vocale, consonante, cifra o altro carattere, utilizzando sia valori multipli che un intervallo. Per le vocali e le consonanti, sono stati specificati più valori separati da virgole, mentre per le cifre è stato utilizzato un intervallo.
Ricapitolando:
Clausole con valori multipli e intervalli per l'istruzione case
In un'istruzione case
, è possibile specificare più valori per un singolo ramo separandoli con una virgola, oppure definire un intervallo di valori utilizzando la sintassi valoreInizio..valoreFine
. Ad esempio:
case <espressione> of
valore1, valore2: <istruzione>;
valoreInizio..valoreFine: <istruzione>;
{ ... }
end;
Clausole ripetute non permesse
Un'importante restrizione nell'uso dell'istruzione case
è che ogni valore o intervallo di valori può apparire una sola volta. Non è permesso avere clausole ripetute. Ad esempio, il seguente codice non è valido:
case <espressione> of
1: <istruzione1>;
1: <istruzione2>; // Errore: clausola ripetuta
2..5: <istruzione3>;
3..7: <istruzione4>; // Errore: intervallo sovrapposto
end;
Quindi, bisogna assicurarsi che ogni valore o intervallo sia unico all'interno dell'istruzione case
e che gli intervalli non si sovrappongano.
In ogni caso, il compilatore di Object Pascal segnalerà un errore se si tenta di utilizzare clausole ripetute o intervalli sovrapposti.
Clausola else
È considerata buona pratica includere la parte else
per segnalare una condizione indefinita o inaspettata. Un'istruzione case in Object Pascal seleziona un percorso di esecuzione, non effettua un salto. In altre parole, esegue l'istruzione o blocco dopo i due punti del valore selezionato e salta all'istruzione dopo il case.
Questo è molto diverso da ciò che accade in linguaggio C (e alcuni dei suoi linguaggi derivati) che trattano i rami di un'istruzione switch come salti ed eseguiranno tutte le istruzioni seguenti a meno che non si usi specificamente una richiesta break
(anche se questo è uno scenario specifico in cui Java e C# differiscono realmente nella loro implementazione).
La clausola else
è simile al blocco default
in C, Java e C#. Serve a gestire i casi in cui il valore dell'espressione non corrisponde a nessuno dei valori specificati nei rami precedenti.
Ricapitolando:
Clausole else
nell'istruzione case
La clausola else
in un'istruzione case
viene eseguita se nessuno dei valori specificati corrisponde al valore dell'espressione.
Essa è opzionale. In sua assenza, se l'espressione non corrisponde a nessuno dei valori elencati, l'istruzione case
non eseguirà alcuna azione.
La sintassi è la seguente:
case <espressione> of
<valore1>: <istruzione1>;
<valore2>: <istruzione2>;
...
<valoreN>: <istruzioneN>;
else
<istruzioneElse>;
end;
Blocchi di codice nelle istruzioni case
Negli esempi precedenti, ogni ramo dell'istruzione case
eseguiva una singola istruzione. Tuttavia, è possibile eseguire più istruzioni per un singolo ramo racchiudendole tra begin
ed end
.
In altre parole, possiamo adoperare istruzioni composte all'interno di un ramo case
.
Ad esempio:
case <espressione> of
valore1: begin
<istruzione1>;
<istruzione2>;
...
end;
valore2: begin
<istruzione1>;
<istruzione2>;
...
end;
{ ... }
end;
Ecco un esempio che mostra come utilizzare un blocco di codice in un ramo case
:
program EsempioCaseConBlocchi;
var
giorno: Integer;
nomeGiorno: string;
begin
WriteLn('Inserisci un numero intero tra 1 e 7');
WriteLn('dove 1 = Lunedì, 2 = Martedì, ..., 7 = Domenica: ');
ReadLn(giorno);
case giorno of
1: begin
nomeGiorno := 'Lunedì';
WriteLn('Inizio della settimana lavorativa.');
end;
2: begin
nomeGiorno := 'Martedì';
WriteLn('Secondo giorno della settimana.');
end;
3: begin
nomeGiorno := 'Mercoledì';
WriteLn('Metà settimana!');
end;
4: begin
nomeGiorno := 'Giovedì';
WriteLn('Quasi alla fine della settimana.');
end;
5: begin
nomeGiorno := 'Venerdì';
WriteLn('Ultimo giorno lavorativo!');
end;
6: begin
nomeGiorno := 'Sabato';
WriteLn('Finalmente il weekend!');
end;
7: begin
nomeGiorno := 'Domenica';
WriteLn('Giorno di riposo.');
end;
else
begin
nomeGiorno := 'Errore: il numero non è compreso tra 1 e 7';
WriteLn(nomeGiorno);
end;
end;
if giorno in [1..7] then
WriteLn('Il giorno della settimana è: ', nomeGiorno);
end.
In questo esempio, ogni ramo dell'istruzione case
contiene un blocco di codice racchiuso tra begin
ed end
, che esegue più istruzioni. Se l'utente inserisce un numero non compreso tra 1 e 7, viene eseguito il blocco else
, che gestisce l'errore.