Linguaggi | Manuali | Compilatori | Programmi | Script | Software | Linux | Windows | Html
Linguaggi

C
C++
JAVA
PERL
COBOL
PASCAL
MATLAB
FORTRAN77
FORTRAN90

JAVASCRIPT

VISUALBASIC

Sistemi operativi

LINUX
WINDOWS
UNIX
MAC

Software

AUTOCAD
GNUPLOT
OCTAVE
SCILAB

Istruzioni di controllo - seconda parte
Tutorial 6
Scritto da Roberto Navigli (roberto.navigli@iol.it)
Game Programming Italia: www.gpi.eden.it

Istruzioni di controllo - seconda parte

Il concetto di iterazione è uno dei pilastri della programmazione imperativa. Ripetere un blocco di istruzioni finché sono mantenute determinate condizioni è di importanza fondamentale nella maggior parte dei programmi.

L'istruzione while

Uno dei modi di realizzare l'iterazione è quello di utilizzare l'istruzione while. Essa permette di ripetere l'esecuzione del blocco di istruzioni finché è vera l'espressione indicata tra parentesi subito dopo il while:

while(espressione di test) istruzioni

dove istruzioni può essere una singola istruzione oppure un blocco di istruzioni racchiuso da parentesi graffe. Ad esempio:

int n = 100;
while(n--) cout << n << " ";

Questo frammento stampa tutti i numeri da 99 a 0 separati da uno spazio. Soffermiamoci per un momento sull'espressione:

n--

Questa espressione vale n ma essa include anche l'esecuzione di un'operazione di decremento, dovuta all'operatore --. Quindi il valore dell'espressione è n, ma la variabile n verrà subito dopo decrementata di 1. Si controlla che il valore di n (100) sia diverso da 0, si decrementa n, quindi si esegue l'istruzione di stampa, si controlla che il valore di n (99) sia diverso da 0, si decrementa n e si esegue la stampa e così via finché n non vale 0. A quel punto l'iterazione si interrompe.

Vediamo ora un esempio completo:

#include <iostream>

using namespace std;

void main()
{
char c = 0;

while(c != 'x')
{
cout << "Inserisci un carattere (x per uscire) e premi invio: ";
cin >> c;

cout << "Hai inserito il carattere: " << c << endl;
}
}

Nel main viene dichiarata una variabile di tipo carattere e inizializzata a zero,

char c = 0;

quindi si richiede l'inserimento di un carattere (memorizzato nella variabile c) ripetutamente finché c non è uguale al carattere 'x' (i caratteri sono indicati tra apici).

L'istruzione do ... while

Questa istruzione è simile al while, con la differenza che la condizione è posta alla fine del blocco di istruzioni (o della singola istruzione). La forma generale è:

do istruzioni
while(espressione di test);

Ad esempio:

int n = 100;
do
cout << n << " ";
while(n--);

Stampa tutti i numeri da 100 a 0. Infatti il decremento della variabile n avviene solo dopo la stampa della stessa.
L'utilità del do ... while rispetto all'istruzione while è che a volte può essere utile eseguire il blocco di istruzioni almeno una volta. Vediamo ancora un esempio:

int n = 0;

// tutti i numeri pari da 0 a 100
do
{
// stampa la variabile
cout << n << " ";

// incrementa di due la variabile n
n += 2;
} while(n <= 100);

L'istruzione for

Spesso le iterazioni sono basate su contatori o variabili che determinano la validità della condizione di "test", come si è visto anche negli esempi precedenti. La forma generale del for è la seguente:

for (inizializzazione; espressione; aggiornamento) istruzioni

Ci sono tre campi che determinano il tipo di iterazione: l'inizializzazione, l'espressione di test e l'aggiornamento.
La sezione di inizializzazione assegna il valore iniziale alla variabile che controlla l'iterazione. Essa viene eseguita una volta sola prima che abbia inizio il ciclo. La seconda sezione contiene l'espressione di test, ovvero quell'espressione che determina il proseguimento o la definitiva interruzione dell'iterazione, secondo se essa è vera oppure falsa rispettivamente. La condizione di test viene verificata all'inizio di ogni esecuzione del blocco di istruzioni. La terza sezione contiene l'istruzione di aggiornamento della variabile che controlla il ciclo. Tale istruzione viene eseguita al termine di ciascuna esecuzione del blocco di istruzioni.
Vediamo subito un esempio:

#include <iostream>

using namespace std;

void main()
{
int numero;

for (numero = 1; numero <= 15; numero++)
cout << numero << " ";
}

Nel for dell'esempio, l'intero numero viene inizializzato a 1. La condizione che determina il proseguimento del ciclo è:

numero <= 15

e ad ogni ciclo la variabile viene incrementata di uno mediante l'istruzione:

numero++

Il programma stampa i primi 15 interi a partire da 1:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Vediamo ancora in dettaglio l'ordine con cui vengono eseguite le diverse sezioni del for.
Per prima cosa viene inizializzata la variabile numero a 1. Quindi viene controllato che numero sia minore o uguale a 15. A questo punto viene eseguito il corpo del for, ovvero viene stampato il valore della variabile numero, che è pari a 1. Quindi essa viene incrementata di 1. Viene controllato che numero sia minore o uguale a 15, viene stampato il valore 2 e numero è di nuovo incrementato di 1 e così via finché numero non assume il valore 16. A quel punto, quando si effettua il controllo sulla condizione, l'iterazione termina.

Così come nel while, poiché il test viene eseguito prima delle istruzioni specificate nel corpo del for, è possibile che il ciclo non venga eseguito neanche una volta. Ad esempio:

#include <iostream>

using namespace std;

void main()
{
int numero = 20;

for (; numero <= 15; numero++) cout << numero << " ";
cout << "Nessun numero stampato!" << endl;
}

Compilando ed eseguendo questo programma, nessun numero verrà stampato. Si otterrà in output la sola stringa:

Nessun numero stampato!

Questo avviene perché la condizione

numero <= 15

viene controllata prima dell'esecuzione delle istruzioni che costituiscono il corpo del for.
In questo esempio, la sezione di inizializzazione è vuota. Ciascuna sezione del for può essere vuota. Ci si chiederà quale utilità può avere un for senza l'istruzione di incremento o senza la condizione di test. In realtà esse possono essere inserite all'interno del blocco di istruzioni. Ad esempio:

// inizializzazione
int n = 0;

for (; n < 10; )
{
cout << n << " ";

// aggiornamento della variabile di controllo
n += 2;
}

Questo frammento stampa i numeri pari da 0 a 8:

0 2 4 6 8

La tecnica di incrementare la variabile nelle istruzioni che costituiscono il corpo del for torna utile quando questo incremento è condizionato da altri eventi o quando esso deve avvenire a metà del blocco di istruzioni. Il caso estremo di for con nessuna delle tre sezioni specificate è quello del for infinito:

for (;;)
{
// queste istruzioni vengono eseguite all'infinito
}

che è equivalente a:

while(true)
{
// queste istruzioni vengono eseguite all'infinito
}

Le istruzioni vengono eseguite all'infinito, poiché la condizione di test è sempre vera.

Può capitare inoltre che il corpo del for sia vuoto, ad esempio:

int n;
for (n = 0; n < 100; n++);

Finora abbiamo considerato il caso in cui ci sia una sola variabile di controllo. In realtà l'istruzione for ammette la presenza di più variabili di controllo. Ad esempio:

int a, b;
for (a = 0, b = 2; a*2 <= b; a++, b++)
cout << "a = " << a << ", b = " << b << endl;

Esaminiamo i singoli passi:

inizializzazione: a = 0, b = 2
test: 0*2 <= 2 cioè 0 <= 2 ? sì
istruzione: stampa "a = 0, b = 2"
aggiornamento: a = 1; b = 3;
test: 1*2 <= 3 cioè 2 <= 3 ? sì
istruzione: stampa "a = 1, b = 3"
aggiornamento: a = 2, b = 4
test: 2*2 <= 4 cioè 4 <= 4 ? sì
istruzione: stampa "a = 2, b = 4"
aggiornamento: a = 3, b = 5
test: 3*2 <= 5 cioè 6 <= 5 ? no, esce

Le istruzioni break e continue

Parlando del for, abbiamo visto che è possibile omettere la condizione di test. Ma come è possibile allora uscire dall'iterazione? L'istruzione break ha proprio questa funzione. Ad esempio:

int x;
for (;;)
{
cout << "Inserisci un numero (0 per uscire): ";

// richiede un numero in input
cin >> x;

// se x == 0, esci dal ciclo
if (!x) break;
}

Nell'esempio, se x è uguale a zero, si esegue l'istruzione break che esce dal ciclo, altrimenti si continua a chiedere un numero all'utente. Chiaramente questo frammento poteva anche essere scritto così:

int x;
for (; x;)
{
cout << "Inserisci un numero (0 per uscire): ";
cin >> x;
}

O anche:

int x;
while(x)
{
cout << "Inserisci un numero (0 per uscire): ";
cin >> x;
}

Ma in generale questa equivalenza non è sempre possibile, perché il codice può essere molto più complicato e i break possono essere più d'uno.

L'istruzione continue permette di interrompere una iterazione senza completarla per passare direttamente alla successiva. Ad esempio:

for (int x = 0; x < 10; x++)
{
// se x è dispari passa all'iterazione successiva
if (x % 2) continue;

cout << x << " è un numero pari!" << endl;
}

Quando l'espressione x % 2 è vera (cioè quando x % 2 è uguale a uno, ovvero x è dispari) si passa all'iterazione successiva e non viene emesso il messaggio in output.
L'istruzione goto

L'istruzione goto realizza un concetto molto semplice della programmazione imperativa: vai a questo punto del codice. La forma generica del goto è la seguente:

goto etichetta;

Dove l'etichetta è presente in un punto del programma. Ma che cos'è un'etichetta? E' una sorta di segnaposto che individua un punto specifico di un programma. Quando si specifica l'etichetta, essa deve essere seguita dai due punti. Vediamo un esempio:

#include <iostream>

using namespace std;

void main()
{
int x;

cout << "Inserisci un numero: " << endl;
cin >> x;

if (x > 10) goto maggiore;

cout << "Hai inserito un numero <= 10!" << endl;
goto esci;

maggiore:
cout << "Hai inserito un numero > 10!" << endl;

esci:
cout << "Goto? No grazie" << endl;
}

L'istruzione goto è stata bistrattata da quando Dijkstra pubblicò l'articolo "Goto considered harmful". In effetti, si può sempre fare a meno del goto, sostituendolo con le altre istruzioni di controllo. Avremmo potuto scrivere l'esempio precedente senza goto e più elegantemente:

#include <iostream>

using namespace std;

void main()
{
int x;

cout << "Inserisci un numero: ";
cin >> x;

if (x > 10) cout << "Hai inserito un numero > 10!" << endl;
else cout << "Hai inserito un numero <= 10!" << endl;
}

L'uso del goto è oggi limitato a quelle applicazioni real-time che hanno bisogno di garantire in alcuni punti la massima efficienza possibile o a sorgenti generati da programmi come ad esempio i generatori di parser.

 

Partner

Guida Fortran
Guida Matlab

English Version
Tutorials
Programming
Lavoro
Lavoro in rete
Telelavoro
Webmaster
Webmaster
Xml

Gratis
Autore
G. Ciaburro
Curriculum
Tesi