Le iterazioni nel C++

Il C++ offre tre tipi di strutture di controllo delle iterazioni: for, while e do while.
Vedremo prima il ciclo while (di cui il do while è una variante) perché è il più semplice da capire.

Il ciclo while permette di eseguire il codice al suo interno finché si verifica una data condizione.
Ad esempio, nel nostro videogioco il ciclo while potrebbe far sì che il livello di gioco continui sinché la vita del nostro personaggio è maggiore di zero.

Facciamo un esempio:
la vita del nostro personaggio è memorizzata in una variabile int;
all'inizio del livello il personaggio ha 100 punti vita;
un algoritmo gestisce quello che succede quando il nostro personaggio è sott'acqua, e cioé man mano che resta sottacqua la vita diminuisce sinché non raggiunge lo 0 ed il personaggio muore annegato;

Scriviamo questo ipotetico algoritmo nella nostra funzione main():
int varVita = 100;

while(varVita > 0)
{
    cout << "hai " << varVita << " punti vita" << endl;
    varVita = varVita - 1;
}
cout << "sei annegato! " << endl;
Vediamo le righe di codice una ad una:

Nella prima riga dichiariamo la variabile int varVita che tiene conto della vita del nostro personaggio, e la inizializziamo al valore 100.

Nella seconda riga vediamo il ciclo while in funzione.

Possiamo notare che il ciclo while è composto dalla parola chiave while, seguita da delle parentesi tonde, e infine da delle parentesi graffe:
while()
{
    //CICLO WHILE
}
All'interno delle parentesi tonde va l'espressione relazionale, e cioé la condizione che il ciclo while verifica prima di eseguire il codice all'interno del suo blocco.

Se l'espressione viene confermata, e cioé se è vera, viene eseguito il codice all'interno del blocco. E questo continua ad avvenire sinché la condizione è vera.

Quando invece la condizione è falsa, il ciclo while si conclude e il controllo passa all'istruzione successiva, subito al di fuori del blocco di codice di while.

Nel nostro esempio l'espressione relazionale (varVita > 0) controlla se il valore di varVita è maggiore di zero.
In altre parole sinché la vita è maggiore di 0 il ciclo while esegue il codice all'interno del proprio blocco.

Il codice eseguito sarà, come è intuibile, quello racchiuso all'interno delle parentesi graffe.

All'interno delle parentesi graffe ci sono due righe di codice:
la prima stampa a video "hai tot punti vita";
la seconda riga decrementa il valore di varVita di 1;

In altre parole, appena viene eseguito il blocco di codice (e cioé nel nostro esempio quando il personaggio è sott'acqua), il nostro personaggio ha 100 punti vita.

Il ciclo while allora si chiede: varVita è maggiore di 0?
Essendo varVita uguale a 100 sì, varVita è maggiore di 0.
Quindi l'espressione relazionale è vera, ed il ciclo esegue il codice all'interno delle parentesi graffe.
Stampa "hai 100 punti vita", dopodiché decrementa la vita di 1 (varVita = varVita - 1), che assume il valore di 99 (ricordiamo che dobbiamo simulare l'effetto di annegamento, quindi sinché il personaggio è sott'acqua la vita deve diminuire).

A questo punto tutte le istruzioni all'interno del blocco sono state eseguite.

Cosa succede ora? Il ciclo while riparte da capo, e cioé verifica se varVita è maggiore di cento.
Essendo a 99, varVita è maggiore di cento, quindi l'espressione è vera di nuovo.
Così viene eseguito di nuovo il codice all'interno del blocco, viene stampato "hai 99 punti vita", e il valore di varVita viene decrementato di 1, diventando 98.

Il controllo passa di nuovo all'inizio del ciclo while, 98 è sempre maggiore di 0, quindi viene eseguito il codice all'interno del blocco, viene stampato "hai 98 punti vita" e la variabile varVita viene decrementata a 97, e così via sino al momento in cui varVita raggiunge il valore 0.

Quando la variabile varVita raggiunge lo 0, il controllo passa per l'ennesima volta all'inizio del ciclo while, per verificare se varVita è ancora maggiore di zero.
Questa volta varVita, essendo uguale a 0, non è maggiore di zero.
L'espressione quindi è falsa, la condizione di "varVita > 0" non si verifica.
Perciò il ciclo finisce, e passa il controllo all'istruzione successiva, e cioé quella subito dopo la parentesi graffa di chiusura, che non è altro che un cout che stampa a schermo la frase "sei annegato!".
int varVita = 100; //vita iniziale del personaggio

while(varVita > 0) //sinché varVita è maggiore di zero esegui il codice nel blocco:
{
    cout << "hai " << varVita << " punti vita" << endl;
    varVita = varVita - 1;
}

//quando varVita non è più maggiore di zero il ciclo termina e passa a:

cout << "sei annegato! " << endl;
Il ciclo while può essere quindi riassunto così:
while(//ESPRESSIONE RELAZIONALE)
{
    //ESEGUI IL CODICE ALL'INTERNO DEL BLOCCO
}
In pseudocodice possiamo scrivere:
SINCHE_SI_VERIFICA(QUESTA_CONDIZIONE)
{
    ESEGUI_QUESTO_CODICE
}
Come vedete è molto intuitivo, si tratta in poche parole di un blocco di codice che viene eseguito ciclicamente sinché si verifica una condizione.
Nel momento in cui viene a mancare quella condizione, il blocco di codice all'interno del ciclo cessa di essere eseguito.

Il nostro esempio stamperà qualcosa del genere:

/> hai 100 punti vita
/> hai 99 punti vita
/> hai 98 punti vita
...
/> hai 2 punti vita
/> hai 1 punti vita //dopo di questo varVita è = 0, quindi il ciclo termina
/> sei annegato!

Il ciclo do while è molto simile al ciclo while, tranne in un particolare.
Vediamo la sua forma:
do
{
    //...codice...
}
while(//condizione);
Prima di tutto notate come il while() termini con un punto e virgola.
Questo perché nel while, il while() è seguito dalla parentesi graffa di apertura, e non è quindi richiesto il punto e virgola, mentre nel do while il while() sarà seguito da altre istruzioni, e il compilatore ha bisogno del punto e virgola per capire quando termina l'istruzione while e ne inizia un'altra.

Detto questo analizziamo la forma del do while.
Il significato è quasi lo stesso del while, tranne per il fatto che nel do while viene prima eseguito il codice all'interno del blocco (do può essere tradotto come "esegui"), e poi viene verificata la condizione all'interno delle parentesi tonde di while().
Tradotto è qualcosa come:
ESEGUI
{
    QUESTO_CODICE
}
SINCHE_SI_VERIFICA(QUESTA_CONDIZIONE);
Nel caso del nostro esempio, il codice viene eseguito prima di verificare se varVita è maggiore di 0.
In altre parole, quando varVita sarà uguale a 0, il codice viene eseguito comunque, dopodiché viene verificata l'espressione relazionale, il ciclo capisce che la condizione non si verifica e termina passando il controllo all'istruzione successiva a while();

Quindi di fatto, quando utilizziamo il do while, saremo sicuri che il codice all'interno del suo blocco sarà sempre eseguito almeno una volta, anche se la condizione del while non si verifica.
Ad esempio:
int varNum = 10;

do

{
    cout << "SEI DENTRO AL BLOCCO DEL DO WHILE";
}
while(varNum > 20);
Nonostante l'espressione relazionale, per essere vera, richieda che varNum sia maggiore di 20, mentre nel nostro caso, essendo uguale a 10, è minore di 20; e quindi, nonostante l'espressione all'interno delle parentesi tonde non si verifichi, il codice all'interno del blocco viene eseguito comunque una volta.

Il ciclo:

- esegue (do) l'istruzione cout;
- controlla (varNum > 20) se varNum è maggiore di 20;
- verifica che non lo è (varNum è infatti uguale a 10);
- termina il ciclo;

Se compilate il codice ed eseguite il programma vedrete che la scritta "SEI DENTRO AL BLOCCO" verrà stampata una volta, nonostante varNum sia minore di 20.

Fate la stessa cosa ma al posto del do while utilizzate un while normale, e vedrete che la frase non verrà mai stampata a schermo, perché il while verifica prima la condizione, e non essendo vera, non eseguirà mai il codice all'interno del blocco.

Il ciclo for è un po' più complesso.
Prima di spiegarlo riscriviamo il nostro primo esempio, ma al posto del while usiamo il for.
Riporto prima la versione con il while, così sarà più facile confrontarle e le differenze salteranno subito all'occhio:
int varVita = 100;

while(varVita > 0)
{
    cout << "hai " << varVita << " punti vita" << endl;
    varVita = varVita - 1;
}
cout << "sei annegato! " << endl;
Ecco invece la versione con il for:
for(varVita = 100 ; varVita > 0 ; varVita = varVita - 1)
{
    cout << "hai " << varVita << " punti vita" << endl;
}
cout << "sei annegato! " << endl;
Come potete notare la forma è simile al while, tranne che dentro alle parentesi tonde, insieme all'espressione relazionale abbiamo messo anche l'inizializzazione della variabile a 100, che prima precedeva il ciclo while, e l'espressione che decrementa la variabile di 1, che prima era all'interno del blocco.

In altre parole il for è una versione condensata del while, all'interno delle cui parentesi tonde, insieme all'espressione relazionale, vanno inserite l'inizializzazione della variabile e l'istruzione che modifica tale variabile.

Scriviamo il ciclo for nella sua forma generale:
for(//INIZIALIZZAZIONE ; //CONDIZIONE ; //ISTRUZIONE)
{
    //!!!!!CODICE DA ESEGUIRE
}
Naturalmente l'inizializzazione della variabile, nel nostro caso varVita = 100, avviene solo la prima volta che viene eseguito il ciclo for.
Mentre nei cicli successivi viene verificata la condizione e viene eseguita l'istruzione di modifica della variabile (in questo caso di decremento).

Le tre espressioni vanno scritte rigorosamente in quest'ordine, e sono delimitate da un punto e virgola.

Chiaramente non si è limitati all'espressione > "maggiore di".
Nel prossimo post parleremo delle altre espressioni relazionali disponibili nel C++.

Nessun commento:

Posta un commento