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;istruzione
può essere un'istruzione semplice o composta, ossia formata da più istruzioni comprese trabegin
eend
:
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_1
eistruzione_2
prendono il nome di rami dell'istruzioneif
. In particolare:istruzione_1
prende il nome di ramothen
istruzione_2
prende il nome di ramoelse
istruzione_1
eistruzione_2
possono essere istruzioni semplici o composte, ossia formate da più istruzioni comprese trabegin
eend
:
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_i
sono espressioni booleane;istruzione_i
possono essere istruzioni semplici o composte, ossia formate da più istruzioni comprese trabegin
eend
- le istruzioni
istruzione_i
prendono 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_1
risulta vera verrà eseguita l'istruzioneistruzione_1
- In caso contrario verrà valutata la condizione
condizione_2
- Se la condizione
condizione_2
risulta vera verrà eseguita l'istruzioneistruzione_2
- Si procede in ordine fino alla condizione
condizione_n
- Se l'ultima condizione
condizione_n
risulta 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.