Fino ad ora abbiamo visto che la modalità generale di programmazione è quella procedurale, ma esiste un'altra logica, meno comune, ed è quella iterativa; il concetto fondamentale è quello di eseguire un'istruzione (o una serie di istruzioni) continuamente, fino a quando non sopraggiungono delle condizioni che fanno terminare tale computazione. Facciamo l'esempio più semplice, voler stampare a video per mille volte la solita frase; la programmazione procedurale suggerisce di scrivere mille volte il codice, mentre quella iterativa permette di scrivere il comando una ed una sola volta e poi ripeterlo per mille volte, dopo le quali una struttura di controllo adeguata (ad esempio un contatore da uno a mille) termine l'esecuzione del ciclo.
I tre costrutti comunemente usati sono il WHILE, il DO ed il FOR che fanno praticamente la stessa cosa solo che il secondo, a differenza degli altri, esegue almeno una volta il ciclo.
L'istruzione WHILE viene schematizzata come segue:
istruzione-while :
while ( condizione ) istruzione |
Con questa istruzione viene prima valutata la condizione racchiusa tra le parentesi tonde, se l'espressione risulta vera viene eseguita l'istruzione all'interno del while e il while viene ripetuto, altrimenti si esce dal ciclo del while e si procede con il resto del programma.
Il DO può essere considerato una variante dell'istruzione while ed è strutturato nella maniera seguente:
istruzione-do :
do istruzione while ( condizione ) ; |
Prima di tutto viene eseguita l'istruzione racchiusa tra DO e WHILE (quindi si esegue almeno una volta), poi si verifica il risultato dell'espressione, se è vero si riesegue il DO, altrimenti si continua con l'esecuzione del resto del programma.
Il FOR, schematizzato qui sotto secondo la notazione di Backus-Naur, inizializza una variabile, pone una condizione (che deve essere vera o falsa) e poi modifica (incrementa o decrementa) la variabile iniziale.
istruzione-for :
for ( inzializzazione ; condizione ; incremento ) istruzione |
Volendo schematizzare questo ciclo con il WHILE, ecco la struttura che vi si presenta:
inzializzazione
while ( condizione ) { istruzione incremento } |
Il potere del FOR è appunto quello di poter modificare la variabile che serve per verificare la condizione iniziale, la quale decide se eseguire o meno il corpo del ciclo.
Tanto per far capire la potenza di questi strumenti, facciamo un esempio un po' più complesso, supponendo di dover trovare un nominativo all'interno di un elenco telefonico, come procediamo? la programmazione procedurale ci suggerisce di partire dalla A fino ad arrivare alla Z, in questo modo impiegheremmo molto tempo a trovare il numero di telefono, se ad esempio il cognome che volessimo cercare fosse "Valente" (nda :D). Sarebbe molto più comodo aprire l'elenco a metà e verificare se il cognome che stiamo cercando si trova a sinistra o a destra della pagina che abbiamo aperto, una volta scelta la metà opportuna (in questo caso quella di destra) basterà dividere in due parti anche quella e compiere di nuovo l'operazione di scelta. Questo signori è un processo ricorsivo che ci porterà molto più in fretta al numero di telefono che stiamo cercando:
carattere DACERCARE = "valente";
intero INDICE = 10000; carattere NOMI_ELENCO[INDICE] = -variabile che contiene tutti i nomi-; carattere NUMERI_ELENCO[INDICE] = -variabile che contiene tutti i numeri; for (intero A = 0; A < INDICE;) { |
In questo programma abbiamo due variabili strane, NOMI_ELENCO e NUMERI_ELENCO, che sono array, ovvero delle variabili che permettono di contenere più valori accessibili tramite un indice; a parte questo bisogna concentrarci sul for, qui viene inizializzata una variabile A con valore 0, questo per permettere di scorrere tutti i valori da 0 a 10000, la seconda parte, la condizione di controllo, permette l'esecuzione del FOR (se A fosse maggiore di INDICE si uscirebbe dal FOR), mentre la terza ed ultima parte del FOR aumenta ad ogni ciclo il valore di A. La variabile B di appoggio servirà per avvicinarsi sempre di più al valore dell'INDICE di DACERCARE; Il corpo del FOR contiene un IF che verifica se DACERCARE sta a sinistra, a destra o è uguale al valore di NOMI_ELENCO con indice B. Per chiarire, mettiamo in questo caso che "valente" corrisponda a NOMI_ELENCO[6250], eseguiremo questi passi:
- verifichiamo cha A (=0) sia minore di INDICE (=10000)
- poniamo B = (0 + 10000)/2 = 5000
- controlliamo che "valente" stia a sinistra di NOMI_ELENCO[5000]
- poiché ciò non accade controlliamo che "valente" stia a destra di NOMI_ELENCO[5000]
- poiché accade poniamo A = 5000
- ricominciamo il ciclo e verifichiamo che A (=5000) sia minore di INDICE (=10000)
- poniamo B = (5000 + 10000) / 2 = 7500
- controlliamo che "valente" stia a sinistra di NOMI_ELENCO[7500]
- poiché accade poniamo INDICE = 7500
- ricominciamo il ciclo e verifichiamo che A (=5000) sia minore di INDICE (=7500)
- poniamo B = (5000 + 7500) / 2 = 6250
- poiché "valente" è uguale (non essendo ne' maggiore ne' minore) a NOMI_ELENCO[6250] visualizziamo sullo schermo il numero di telefono corrispondente in base all'indice e usciamo dal programma
Anche se siamo stati fortunati, si può capire il netto vantaggio nel trovare una cosa cercata con un ciclo e qualche confronto, invece di scorrere tutto l'indice dall'inizio alla fine.