Istruzione Condizionale if in Object Pascal
L'istruzione if, chiamata anche istruzione condizionale, permette di eseguire del codice solo nel caso in cui una condizione venga soddisfatta.
Quando la condizione specificata è soddisfatta, l'istruzione if permette di eseguire l'istruzione che segue la clausola then.
Esiste anche la possibilità, attraverso la tripletta if then else, di specificare un'altra istruzione che venga eseguita nel caso opposto, ossia quando la condizione non è soddisfatta.
In questa lezione vedremo la sintassi delle istruzioni if then e if then else. Vedremo, anche, come gestire casi più complessi in cui è necessario concatenare oppure innestare più istruzioni if tra di loro.
Istruzione condizionale if
La prima tipologia di istruzioni condizionali che studieremo sono le istruzioni if.
Un'istruzione if permette di eseguire una o più istruzioni solo nel caso in cui una certa condizione booleana è soddisfatta. Essa può essere usata anche per scegliere tra due alternative: eseguire un gruppo di istruzioni se la condizione è soddisfatta o, in caso negativo, eseguire un altro gruppo di istruzioni.
Nel primo caso si parla di istruzione if-then, mentre nel secondo caso di istruzione if-then-else.
Istruzione if then
Studiamo il primo tipo di istruzione if partendo da un semplice esempio di programma che determina se un numero intero introdotto dall'utente sia pari:
1 2 3 4 5 6 7 8 9 10 | |
Nel programma dell'esempio, alla riga 8 andiamo a testare se il valore inserito dall'utente sia pari; in particolare, andiamo a controllare se X modulo 2 sia pari a zero. Quindi la condizione da soddisfare è:
(X mod 2) = 0
che è un'espressione booleana. Questa espressione è seguita dalla parola chiave then e dall'istruzione da eseguire in caso la condizione sia soddisfatta. In particolare, l'istruzione da eseguire nel caso in cui X sia pari è:
WriteLn('Il numero inserito è pari');
Quindi la sintassi dell'istruzione if è:
if condizione then
istruzione;
Al posto di istruzione possiamo anche inserire istruzioni composte ricordandoci di racchiudere le sotto-istruzioni tra begin e end. Ad esempio, avremmo potuto scrivere:
if (X mod 2) = 0 then
begin
Write('Il numero inserito ');
WriteLn('è pari');
end;
In tal caso, le due istruzioni Write e WriteLn saranno eseguite in sequenza.
Ricapitolando:
Istruzioni if then
In Object Pascal, un'istruzione condizionale if then permette di eseguire un'istruzione nel caso in cui si verifichi una condizione. In particolare, quando la condizione, che deve essere un'espressione booleana, risulti pari a true. La sintassi dell'istruzione if then è la seguente:
if condizione then
istruzione;
condizioneè un'espressione booleana;istruzionepuò essere un'istruzione semplice o composta, ossia formata da più istruzioni comprese trabegineend:
if condizione then
begin
istruzione_1;
istruzione_2;
{ ... }
istruzione_n;
end;
Istruzione if then else
Il secondo tipo di istruzioni if ci permette di scegliere tra due istruzioni alternative: una per il caso in cui la condizione sia verificata, l'altra in caso contrario.
Ritornando all'esempio di prima, il programma stampa un messaggio nel caso in cui il numero intero introdotto dall'utente sia pari. In caso contrario non fa nulla. Modifichiamo, quindi, il programma in maniera tale da mostrare un messaggio diverso nel caso in cui il numero sia dispari:
1 2 3 4 5 6 7 8 9 10 11 12 | |
In questo caso abbiamo aggiunto la clausola else alla riga 10, che ci permette di specificare cosa fare nel caso in cui la condizione non è soddisfatta.
Nel gergo tecnico, le istruzioni da eseguire nel caso in cui la condizione sia positiva e quelle da eseguire nel caso in cui, invece, sia negativa, prendono il nome, rispettivamente, di ramo then e ramo else.
Un'importante dettaglio da notare riguarda la riga 9: al termine dell'istruzione non abbiamo inserito un punto e virgola ;. Infatti, il compilatore object pascal considera il costrutto if then else come un'unica istruzione complessa. Per cui, il punto e virgola va posto esclusivamente alla fine dopo l'istruzione del ramo else.
Anche nel caso di istruzioni if then else vale il discorso che le istruzioni da eseguire nel ramo then e else possono essere istruzioni complesse, purché racchiuse tra begin e else. Avremmo, infatti, potuto scrivere:
if (X mod 2) = 0 then
begin
Write('Il numero inserito è ');
WriteLn('pari');
end
else
begin
Write('Il numero inserito è ');
WriteLn('dispari');
end;
Anche in questo caso bisogna ricordarsi di non inserire il punto e virgola al termine del primo end
Ricapitolando:
Istruzioni if then else
In Object Pascal, un'istruzione condizionale if then else permette di scegliere tra due istruzioni da eseguire in base al valore di una condizione booleana. In particolare, quando la condizione booleana risulta pari a true viene eseguita l'istruzione che segue la parola chiave then. Se, invece, la condizione risulta pari a false viene eseguita l'istruzione che segue la parola chiave else. La sintassi dell'istruzione if then else è la seguente:
if condizione then
istruzione_1
else
istruzione_2;
condizioneè un'espressione booleana;istruzione_1eistruzione_2prendono il nome di rami dell'istruzioneif. In particolare:istruzione_1prende il nome di ramothenistruzione_2prende il nome di ramoelse
istruzione_1eistruzione_2possono essere istruzioni semplici o composte, ossia formate da più istruzioni comprese trabegineend:
if condizione then
begin
istruzione_1_1;
istruzione_1_2;
{ ... }
istruzione_1_n;
end
else
begin
istruzione_2_1;
istruzione_2_2;
{ ... }
istruzione_2_m;
end;
Istruzioni else if
Le istruzioni if then else permettono di scegliere tra due rami o percorsi di istruzioni differenti in base al fatto che una condizione booleana sia vera o falsa.
Nella stesura di programmi potrebbe sorgere la necessità di poter scegliere tra più di due rami in base al valore di più condizioni. Supponiamo di voler realizzare un programma che, dato un numero intero in ingresso, stampi a schermo un messaggio in base al fatto che il numero sia minore di 100, compreso tra 100 e 200 oppure maggiore di 200. In tal caso, stiamo parlando di tre possibilità. Per poter far questo dobbiamo utilizzare l'istruzione else if, ossia concatenare due istruzioni if then else tra di loro. Per capire come fare, osserviamo l'esempio:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
In questo programma abbiamo ben tre rami di esecuzione diversi in base al valore della variabile X. In particolare, nella riga 10 abbiamo concatenato un'altra istruzione if alla precedente. La concatenazione non ha limiti e possiamo aggiungere quante clausole if then vogliamo. In questo modo, tuttavia, il codice può risultare complesso, per cui a volte conviene utilizzare le istruzioni case che vedremo nella prossima lezione.
Riassumendo:
Concatenazione di istruzioni if then else
In Object Pascal, è possibile concatenare più istruzioni if then else. Questo risulta necessario nei casi in cui non vi sia un'unica condizione booleana, che può essere vera o falsa, ma più condizioni complesse. In tal caso la sintassi da utilizzare è:
if condizione_1 then
istruzione_1
else if condizione_2 then
istruzione_2
else if condizione_3 then
istruzione_3
{ ... }
else
istruzione_finale;
condizione_isono espressioni booleane;istruzione_ipossono essere istruzioni semplici o composte, ossia formate da più istruzioni comprese trabegineend- le istruzioni
istruzione_iprendono il nome di rami.
Quando si usano istruzioni if then else concatenate bisogna prestare attenzione all'ordine di valutazione. Prendiamo l'esempio che segue:
if condizione_1 then
istruzione_1
else if condizione_2 then
istruzione_2
else if condizione_3 then
istruzione_3
else
istruzione_4;
In questo caso, se la condizione condizione_1 risulta essere pari a true allora verrà eseguita l'istruzione istruzione_1. In caso contrario viene valutata la condizione condizione_2. Nel caso in cui sia pari a true viene eseguita l'istruzione istruzione_2. E così via.
Ordine di valutazione nelle istruzioni if then else concatenate
In Object Pascal, quando più istruzioni if then else sono concatenate tra di loro, le condizioni vengono valutate in sequenza. Pertanto, verrà eseguita l'istruzione del ramo then corrispondente alla prima condizione pari a true. Nel caso in cui nessuna condizione risulti vera, verrà, infine, eseguita l'istruzione corrispondente al ramo else finale, se presente.
Prendendo la sintassi seguente:
if condizione_1 then
istruzione_1
else if condizione_2 then
istruzione_2
else if condizione_3 then
istruzione_3
{ ... }
else
istruzione_finale;
Le condizioni verranno valutate in ordine.
- Verrà valutata la condizione
condizione_1. - Se la condizione
condizione_1risulta vera verrà eseguita l'istruzioneistruzione_1 - In caso contrario verrà valutata la condizione
condizione_2 - Se la condizione
condizione_2risulta vera verrà eseguita l'istruzioneistruzione_2 - Si procede in ordine fino alla condizione
condizione_n - Se l'ultima condizione
condizione_nrisulta falsa viene eseguita l'istruzioneistruzione_finale
Per questo motivo bisogna fare attenzione ad usare le istruzioni if then else concatenate. Prendiamo un esempio: supponiamo di volere scrivere un programma che prende in ingresso due numeri interi A e B. In base al valore di questi due numeri il programma deve stampare un diverso messaggio a schermo:
- Se
Aè maggiore o uguale a zero eBè maggiore o uguale a zero deve stampare il messaggioCOND1; - Se
Bè minore di zero deve stampare il messaggioCOND2; - Se
Aè minore di zero deve scrivere il messaggioCOND3.
In base a queste specifiche potremmo essere tentati di scrivere il programma in questo modo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Il problema di questo programma sta nel fatto di aver usato delle istruzioni if then else concatenate. Infatti, supponiamo di dare in input al programma i valori:
- A = -1
- B = -1
Quindi entrambe negativi. Arrivati alla riga 11 il programma andrà dapprima a verificare la condizione:
(A >= 0) and (B >= 0)
che risulta negativa. Per cui, il programma andrà alla riga 13 e valuterà la condizione:
(B < 0)
che risulta positiva. Quindi verrà stampato a schermo il messaggio COND2. A questo punto, però, il programma uscirà dalla catena di if then else. La condizione
(A < 0)
che è vera, non verrà valutata, per cui il messaggio COND3 non verrà stampato a schermo. Il modo corretto di scrivere il programma è il seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
Quindi, piuttosto che concatenare le istruzioni if then else, bisogna mettere due istruzioni if separate in un blocco begin end nel ramo else. Questa versione del programma, se diamo in input due numeri negativi, si comporta correttamente stampando a schermo due messaggi:
COND2
COND3
In questo caso, quello che abbiamo fatto nel secondo programma è stato di innestare un'istruzione if all'interno di un'altra.
Istruzioni if innestate
Nell'ultimo esempio abbiamo visto che è possibile innestare delle istruzioni if all'interno di altre:
Innestare le istruzioni if
In Object Pascal, è possibile innestare delle istruzioni if all'interno di altre istruzioni if. Per farlo basta semplicemente sostituire al posto di una delle istruzioni relative al ramo then o else l'istruzione if desiderata:
if condizione then
if condizione_innestata then
istruzione_1
else
istruzione_2
else
if condizione_innestata_2 then
istruzione_3
else
istruzione_4;
Le istruzioni if interne possono, a loro volta, ospitare altre istruzioni if innestate.
Nell'innestare le istruzioni if bisogna, però, prestare molta attenzione. Esiste, infatti, il cosiddetto problema dell'else appeso (dall'inglese Dangling else problem).
Per capire cosa sia, partiamo da un esempio:
1 2 3 4 5 6 7 8 9 10 | |
In questo esempio, abbiamo delle funzioni if innestate che scrivono un messaggio diverso a seconda del fatto che le variabili X e Y siano positive o meno. Esistono, infatti, quattro combinazioni possibili coperte dai vari rami delle istruzioni if.
A questo punto, se rimuoviamo le righe 4 e 5 otteniamo il seguente stralcio di codice:
1 2 3 4 5 6 7 8 | |
A prima vista può sembrare banale, ma questo pezzo di codice nasconde un'insidia: l'else di riga 4 a quale if si riferisce?
Si potrebbe pensare che quell'else si riferisca all'if della riga 1 ma ciò è sbagliato! Infatti, l'Object Pascal, in casi ambigui come questo, associa l'else all'istruzione if più vicina, che in questo caso risulta essere quella di riga 2.
L'indentazione in questo caso ci ha tirato un brutto scherzo. Dal punto di vista del compilatore, l'indentazione del codice è ininfluente. Sarebbe stato più corretto scrivere in questo modo:
1 2 3 4 5 6 7 8 | |
Per cui, rimuovendo quelle righe di codice, il programma si comporterà in maniera diversa da quanto ci saremmo aspettati.
Come si può risolvere questo problema? Semplicemente racchiudendo il ramo di codice tra begin e end, nel modo che segue:
1 2 3 4 5 6 7 8 9 10 | |
Solo in questo modo il compilatore potrà capire che l'else fa riferimento al primo if di riga 1.
Riassumendo:
Problema del Dangling else
In Object Pascal, in presenza di istruzioni if then else innestate, se non vengono esplicitamente racchiuse le istruzioni tra begin e end, si usa la convenzione di associare un else al più vicino if di cui ne è sprovvisto.
In questo caso, la clausola else è associata al secondo if:
if condizione_1 then
if condizione_2 then
istruzione_1
else
istruzione_2;
In quest'altro caso, usando esplicitamente begin e end, la clausola else è associata al primo if:
if condizione_1 then
begin
if condizione_2 then
istruzione_1
end
else
istruzione_2;
In entrambe i casi, l'indentazione del codice è ininfluente.
Riassumendo
In questa lezione abbiamo visto la sintassi delle istruzioni condizionali if. Abbiamo visto come specificare la condizione booleana da verificare e come specificare le istruzioni da eseguire nel caso in cui la condizione sia soddisfatta e viceversa attraverso la tripletta if then else.
Per condizioni più complesse, che non si limitino al caso true o false abbiamo visto come concatenare più istruzioni if tra di loro. Inoltre, abbiamo visto anche come innestare più if, l'una dentro l'altra, scoprendo, anche, che in tal caso vi sono delle insidie: il problema del Dangling else.
Esiste, tuttavia, un altro tipo di istruzioni condizionali che possono essere usate quando le condizioni da gestire diventano troppo complesse: le istruzioni case che vedremo nella prossima lezione.