Cosa intendiamo per ciclo nell’ambito della programmazione? Essenzialmente ci riferiamo ad una serie di istruzioni che possono essere espresse in una forma sintetica attraverso una iterazione perchè risultano in qualche modo simili. Ad esempio immaginiamo di voler stampare una serie di nomi contenuti in un file.
L’istruzione elementare di riferimento è sempre la stessa, quella che consente di stampare uno dei nomi (immaginiamo di chiamarla stampa_nome). Per stampare tutti i nomi contenuti nel file non dovremo far altro che ripetere l’istruzione stampa_nome tante volte quanti sono i nomi presenti o anche, ipotizzando di avere un nome per riga, tante volte quante sono le righe.
Situazioni simili a quella descritta (ovvero con necessità di ripetere istruzioni simili) sono molto frequenti e si può dire che i cicli siano utilizzati praticamente in ogni tipo di programma.
Il vantaggio, utilizzando un ciclo, è di non dover scrivere l’istruzione stampa_nome tante volte quante è necessario ripeterla ma, come vedremo meglio in seguito, una volta soltanto, specificando il numero di ripetizioni.
In alcuni casi il numero delle ripetizioni viene specificato in forma esplicita (parliamo in questo caso di un tipo particolare di ciclo detto ciclo for) o in forma implicita (è il caso dei cicli di tipo while-do o do-while). Esaminiamo ora più nel dettaglio le caratteristiche dei vari tipi di ciclo appena menzionati nel linguaggio C++, cominciando dal ciclo for.
Il ciclo for
Come già accennato, nel caso del ciclo for specifichiamo in modo esplicito per quante volte l’istruzione deve essere ripetuta. Ipotizziamo, per semplicità e per mettere meglio in evidenza le caratteristiche strutturali del ciclo for, di voler stampare a video i primi 100 numeri interi.
Dobbiamo fare in modo di stampare per 100 volte un numero e modificare il numero stesso, incrementandolo di uno ad ogni esecuzione dell’istruzione. Ecco come ottenere questo risultato:
for(int i=1;i<=100;i++)
{
cout<<i;
cout<<"\n";
}
I tre elementi chiave da comprendere sono contenuti nella riga for(int i=1;i<=100;i++) e sono separati dai caratteri “;”. Il primo elemento, ovvero “int i=1” consente di dichiarare una variabile intera che utilizzeremo nella gestione del ciclo.
Il secondo blocco logico, cioè “i<=100” equivale ad asserire “ripeti l’istruzione compresa all’interno del ciclo fino a che i ha valore minore di 100 o uguale a 100″.
Il terzo e ultimo blocco logico è costituito in questo caso da “i++” e serve per specificare quali operazioni debbano essere effettuate dopo ogni esecuzione dell’istruzione. In questo caso, dopo ogni esecuzione di “cout<<i” (che serve per stampare il numero intero i), la variabile i viene incrementata di 1.
Verifichiamo il corretto funzionamento del ciclo. Inizialmente i è uguale a 1, perciò viene stampato il valore 1. Prima che l’istruzione venga ripetuta, il valore di i viene incrementato di 1. La seconda esecuzione dell’istruzione stampa il valore 2 e così via fino a che i non assume valore 101.
A questo punto il ciclo viene interrotto. Vengono quindi correttamente stampati i primi 100 numeri interi. L’istruzione cout<<“\n” consente di andare a capo ed è utile solo per una visualizzazione più ordinata. Per la corretta esecuzione dell’istruzione cout sarà inoltre necessario includere in questo modo la libreria iostream.h nel nostro programma:
#include <iostream.h>
Il ciclo while-do
Nel caso del ciclo while-do l’istruzione non viene ripetuta per un numero predeterminato di volte, ma viene eseguita se si verificano certe condizioni e ripetuta fino a che tali condizioni sono verificate.
Immaginiamo ad esempio di voler stampare i primi dieci numeri interi e poi chiedere all’utente se continuare con la stampa dei dieci successivi o interrompere il programma, continuando a riproporre la scelta fino a che l’utente non decide di interrompere.
Ecco il codice che realizza tale programma (ci serviamo di una variabile booleana di nome continua, che assume cioè valori vero o falso, per decidere se proseguire o meno con il programma):
int start=1;
while(continua==true)
{
int input;
for(int i=start;i<=start+10;i++)
{
cout<<i;
cout<<"\n";
}
start=i;
cout<<"Continuare? 1=si, 0=no\n";
cin>>input;
if(input==0) continua=false;
}
Come si può notare, il ciclo viene eseguito se e solo se la variabile continua ha valore true, cioè vero. Dopo la stampa, tramite le istruzioni cout e cin (anche in questo caso è necessario includere la libreria iostream) si richiede all’utente se continuare o meno con i successivi dieci numeri.
La decisione dell’utente può determinare un cambiamento di valore della variabile continua da true (vero) a false (falso) impedendo la prosecuzione del ciclo. Per garantire invece che, se l’utente decide di continuare con le stampe, la sequenza degli interi proceda correttamente, ci serviamo della variabile intera di nome start, che identifica di volta in volta da quale numero è necessario partire.
Un altro ciclo, molto simile al ciclo while-do con una sola leggera differenza, è il ciclo do-while.
Il ciclo do-while
La sostanziale differenza tra un ciclo di tipo do-while e uno di tipo while-do è che solo nel caso di un ciclo do-while si ha la garanzia che le istruzioni in esso contenute siano eseguite almeno una volta, indipendentemente dal verificarsi o meno delle condizioni.
La verifica delle condizioni stesse è infatti successiva rispetto alla prima esecuzione, mentre è precedente nel caso del ciclo while-do. Se, tornando all’esempio precedente, il valore della variabile continua fosse impostato inizialmente a false (cioè falso), il ciclo non verrebbe eseguito per intero.
Ecco invece il codice (che sostituisce il ciclo while-do con un ciclo do-while) che garantisce almeno un’esecuzione del ciclo, anche se la varibiale continua venisse impostata inizialmente a false:
int start=1;
do
{
int input;
for(int i=start;i<=start+10;i++)
{
cout<<i;
cout<<"\n";
}
start=i;
cout<<"Continuare? 1=si, 0=no\n";
cin>>input;
if(input==0) continua=false;
} while(continua==true);