Sezione 2.1 Strutture di controllo. |
||
![]() |
Normalmente un programma non è semplicemente una sequenza di istruzioni da eseguire una dopo l'altra. Durante la sua esecuzione esso può scegliere tra gruppi di istruzioni o ripetere più volte uno stesso gruppo di istruzioni. A questo scopo il C++ fornisce delle strutture di controllo che servono a specificare come si deve comportare il programma.
Per parlare di strutture di controllo occorre introdurre il concetto di blocco di istruzioni. Un blocco di istruzioni è un gruppo di istruzioni separate da punti e virgola (; ) e racchiuse tra parentesi graffe: { e } .
Nella maggior parte delle strutture di controllo che vedremo ora viene indicata una (o più) generica Istruzione come parametro, questa può essere sia una singola istruzione che un blocco di istruzioni. Se mettiamo una singola istruzione non è necessario racchiuderla tra parentesi graffe ( {}), ma naturalmente occorre mettere il punto e virgola ( ;) che la termina. Se vogliamo mettere più di una istruzione allora occorre racchiuderle tra parentesi graffe ( {} ) per formare un blocco.
if (Condizione) Istruzionedove Condizione è una espressione di tipo bool (ossia una espressione il cui risultato è uno dei due valori di verità true o false ). L'espressione booleana Condizione viene valutata e se essa ritorna il valore true l'istruzione (o gruppo di istruzioni) Istruzione viene eseguita mentre se essa ritorna il valore false l'istruzione Istruzione viene ignorata (non eseguita) e l'esecuzione del programma continua con le istruzioni che seguono imediatamente la struttura condizionale.
Ad esempio il seguente frammento di codice stampa x e' 100 soltanto se il valore della variabile x è proprio 100:
if (x == 100)Se vogliamo che vengano eseguite più istruzioni nel caso in cui Condizione è true dobbiamo racchiuderle tra parentesi graffe per formare un unico blocco di istruzioni :
cout << "x e' 100";
if (x == 100)Possiamo anche usare la parola chiave else per specificare una diversa istruzione o blocco di istruzioni da eseguire nel caso in cui la condizione sia falsa. La forma della struttura condizionale è in questo caso la seguente:
{
cout << "x e' ";
cout << x;
}
if (Condizione) Istruzione1 else Istruzione2Ad esempio:
if (x == 100)stampa x e' 100 se x vale proprio 100, ma se non è così -e solo se non è così- stampa x non e' 100.
cout << "x e' 100";
else
cout << "x non e' 100";
La struttura if + else si può concatenare per verificare un insieme di valori. Il seguente esempio illustra il suo uso per verificare se il valore della variabile x è negativo, positivo o nessuno dei due (ossia è zero).
if (x > 0)
cout << "x e' positivo";
else if (x < 0)
cout << "x e' negativo";
else
cout << "x e' 0";
while (Espressione ) Istruzioneed il suo effetto è semplicemente ripetere Istruzione fintanto che Espressione ha il valore true .
Vediamo, ad esempio, un programma che effettua un conto alla rovescia utilizzando un ciclo while:
// conto alla rovescia usando while |
Dammi il valore da cui partire > 8 8, 7, 6, 5, 4, 3, 2, 1, FUOCO! |
Quando il programma inizia viene chiesto all'utente il numero da cui partire con il conto alla rovescia. Quando inizia il ciclo while, se il valore introdotto soddisfa la condizione n>0 (ossia se n è maggiore di 0 ), il blocco di istruzioni viene ripetuto un numero indefinito di volte fintanto che la condizione (n>0) rimane vera.
L'esecuzione del programma precedente si può descrivere
con la seguente procedura: cominciando da main
:
Occorre assicurarsi che il ciclo ad un certo punto termini.
Per questo occorre prevedere, all'interno del blocco di istruzioni
da ripetere, qualche metodo per fare in modo che prima o poi la condizione
del ciclo diventi falsa. In caso contrario il ciclo continua indefinitamente.
Nel nostro caso abbiamo inserito l'istruzione --n;
che ci assicura che la condizione diventerà sicuramente falsa
dopo un certo numero di ripetizioni: e precisamente quando n
diventa 0
, ossia quando termina il nostro conto alla rovescia.
Naturalmente, siccome il blocco da ripetere è molto
semplice, il calcolatore esegue il programma pressoché istantaneamente,
senza apprezzabile intervallo tra un numero e il successivo del conto
alla rovescia.
do Istruzione while (Condizione );Esso funziona esattamente come il ciclo while tranne il fatto che Condizioneviene controllata dopo l'esecuzione di Istruzione invece che prima di eseguirla.Pertanto con il ciclo do-whilel'istruzione o blocco di istruzioni Istruzione viene eseguita sempre almeno una volta, anche se la condizione Condizione non dovesse risultare mai vera. Ad esempio, il seguente programma ripete ogni numero che l'utente inserisce finché non viene inserito 0.
// ripetitore di numeri |
Dammi un numero (0 per finire): 12345 Mi hai dato: 12345 Dammi un numero (0 per finire): 160277 Mi hai dato: 160277 Dammi un numero (0 per finire): 0 Mi hai dato: 0 |
Il ciclo do-while si usa quando la condizione
che deve terminare il ciclo viene determinata all'interno del ciclo
stesso, come nel programma precedente in cui la terminazione del ciclo
è determinata dall'input dato dall'utente. Se l'utente non
introduce mai il valore 0 il ciclo continua all'infinito.
for ( Inizializzazione; Condizione ; Incremento) Istruzioneed il suo scopo è quello di ripetere Istruzione finché la condizione Condizione rimane vera, esattamente come il ciclo while. A differenza di while il ciclo forpermette di indicare anche una istruzione di inizializzazione Inizializzazione ed una istruzione di incremento Incremento. Il ciclo forè quindi particolarmente adatto ad eseguire delle ripetizioni usando un contatore.
Esso opera in questo modo:
1, viene eseguita l'istruzione Inizializzazione . Generalmente essa è una assegnazione di un valore iniziale al contatore. Essa viene eseguita una sola volta.Ecco un esempio di conto alla rovescia realizzato con un ciclo for :
2, viene controllata la condizione Condizione , se essa è true il ciclo continua (al punto 3 ), altrimenti il ciclo termina.
3, viene eseguita l'istruzione (o blocco di istruzioni) Istruzione.
4, infine, viene eseguita l'istruzione Incremento e si ritorna al punto 2.
// conto alla rovescia usando un ciclo for |
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FUOCO! |
I campi Inizializzazione e Incremento sono opzionali. Essi si possono quindi omettere ma non si può omettere il punto e virgola che li separa de Condizione . Possiamo quindi scrivere for (;n<10;) se non vogliami indicare né Inizializzazione né Incremento oppure for (;n<10;n++) se vogliamo includere il campo Incremento ma non Inizializzazione .
Possiamo inoltre usare l'operatore virgola (,) per specificare più di una azione in uno qualsiasi dei campi di for. L'operatore virgola è un separatore di istruzioni che serve a separare più istruzioni dove ne è richiesta una soltanto. Ad esempio, supponiamo di voler inizializzare più di una variabile per il nostro ciclo:
Questo ciclo viene ripetuto 50 volte sempre che né n né i vengano modificate all'interno del ciclo:for ( n=0, i=100 ; n!=i ; n++, i-- )
{
// qualcosa...
}
n inizia da 0 e i da 100 e la condizione è n!=i (ossia che n sia diverso da i ). Siccome n viene aumentato di uno ed i viene diminuito di uno ad ogni iterazione, la condizione diventerà falsa esattamente dopo 50 iterazioni, quando sia n che i diventano uguali a 50.
// esempio di interruzione di un ciclo |
10, 9, 8, 7, 6, 5, 4, 3, conto alla rovescia interrotto! |
// esempio di interruzione di un ciclo |
10, 9, 8, 7, 6, 4, 3, 2, 1, FUOCO! |
Il punto di arrivo del salto è indicato dall'etichetta che compare come argomento dell'istruzione goto . L'etichetta deve essere premessa all'istruzione a cui saltare e separata da essa dal carattere due punti (: ).
Questa istruzione non ha una reale utilità nella programmazione strutturata e nella programmazione orientata agli oggetti. Soltanto i fanatici della programmazione a basso livello possono trovare utile usarla. Come esempio, ecco il nostro conto alla rovescia realizzato con l'istruzione goto:
// esempio di ciclo con goto |
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FUOCO! |
Essa termina l'esecuzione del programma ritornando un codice di terminazione intero. La sua forma è:
exit(cod) ;dove cod è un valore intero che viene ritornato al sistema operativo. Per convenzione il valore 0 di cod significa che il programma è terminato correttamente mentre un valore diverso da zero indica che è stato riscontrato un errore di esecuzione.
switch (Espressione) {Funziona così: switch valuta l'espressione Espressione e controlla se essa è uguale a Costante1, se lo è esegue il blocco di istruzioni 1 fino a quando arriva all'istruzione break che fa uscire dall'istruzione switch. Se Espressione non è uguale a Costante1 essa viene confrontata con Costante2. Se è uguale a Costante2 viene eseguito il blocco di istruzioni 2 fino all'istruzione break . Infine, se l'espressione non risulta uguale a nessuna delle costanti elencate viene eseguito il blocco di istruzioni di default se presente (la sezione default: è infatti opzionale).
case Costante1:
blocco di istruzioni 1
break;
case Costante2:
blocco di istruzioni 2
break;
.
.
.
default:
blocco di istruzioni di default
}
I seguenti frammenti di codice sono equivalenti:
Esempio switch | Equivalente if-else |
switch (x) { |
if (x == 1) { |
Attenzione : Se si dimentica di inserire l'istruzione break alla fine dei blocchi di istruzioni l'esecuzione continua controllando anche le successive costanti ed infine eseguendo il blocco di istruzioni di default. Questo può essere utile nel caso in cui vogliamo eseguire lo stesso blocco di istruzioni per diversi valori dell'espressione come nell'esempio seguente:
Notare che switch si può usare soltanto per confrontare una espressione con delle costanti. Non si possono usare variabili o espressioni o intervalli di valori (case (n*2): e case (1..3): non vanno bene).
switch (x) {
case 1:
case 2:
case 3:
cout << "x e' 1, 2 o 3";
break;
default:
cout << "x non e' 1, 2 o 3";
}
Se occorre controllare intervalli di valori o valori non costanti bisogna usare una sequenza di frasi if ed else if .
![]() |
![]() 1-4. Comunicazione da console. |
![]() indice |
![]() 2-2. Funzioni. |