Contenuto del capitolo |
---|
Come usare i cicli per ridurre le parti ripetitive. I differenti tipi di cicli e come usarli. |
Nell'ultimo esercizio abbiamo visualizzato una parte della tavola pitagorica del 12. Ma è stato necessario parecchio lavoro di battitura e se fosse necessario estenderla dovremmo perdere ancora altro tempo. Fortunatamente c'è un modo migliore per farlo e qui cominceremo a comprendere la vera potenza dei linguaggi di programmazione.
Adesso vedremo come utilizzare il linguaggio di programmazione per effettuare le ripetizioni, facendo uso di una variabile che viene incrementata ad ogni ripetizione. In Python tutto questo si può esprimere cosí:
>>>for i in range(1,13): ... print "%d x 12 = %d" % (i, i*12) ...
Nota 1: si utilizza range(1,13) per specificare il numero 12 perché la funzione range() genera una sequenza di numeri a partire dal primo fino al secondo, non incluso. Questo fatto a prima vista può sembrare bizzarro ma c'è una ragione che sarà chiara in seguito. .
Nota 2: L'operatore for in Python è in effetti un operatore foreach in quanto applica la sequenza di operazioni che lo segue a ciascun membro di una collezione. La collezione in questo caso è la lista di numeri generata da range(). Potete verificarlo scrivendo print range(1,13) al prompt di Python ed osservando il risultato.
Nota 3: la linea print è scritta indentata verso destra rispetto alla linea for che la precede. Questo è un dettaglio assai importante perché è questo che iin Python specifica quale è la porzione di programma da ripetere. Non importa di quanto le linee siano indentate, purché lo siano tutte della stessa quantità.
Nota 4: Usando l'interprete in modo interattivo è necessario premere il tasto INVIO due volte per mandare il programma in esecuzione. Ciò è dovuto al fatto che l'interprete Python non può sapere se dopo il primo INVIO segue un'altra linea che deve essere aggiunta alle istruzioni del ciclo oppure no. Quando si preme INVIO per la seconda volta, allora è chiaro che le istruzioni sono terminate e possono essere eseguite.
Come funziona dunque il programma? Procediamo passo passo.
Prima di tutto Python usa la funzione range() per creare
una lista di numeri da 1 a 12.
Poi Python assegna ad i il primo valore preso dalla lista, in questo caso 1. Subito dopo esegue la parte di programma scritta indentata, usando il valore i = 1:
print "%d x 12 = %d" % (1, 1*12)
Python quindi torna alla linea for ed assegna ad i il valore successivo nella lista, cioè 2. Quindi esegue nuovamente la parte di programma indentata, questa volta con i = 2:
print "%d x 12 = %d" % (2, 2*12)
Questa sequenza di operazioni viene ripetuta fino a che non sono esauriti i valori della lista. A questo punto Python passa ad eseguire la prima linea successiva non indentata; in questo caso non ci sono altre istruzioni e quindi il programma si arresta.
FOR I = 1 to 12 PRINT I, " x 12 = ", I*12 NEXT I
Questa forma è più esplicita ed è più facile da comprendere. Però la versione Python è più flessibile in quanto è possibile iterare su un insieme di numeri, sugli elementi di una lista e su qualunque tipo di collezione (ad esempio una lista di stringhe).
Tcl usa un costrutto for modellato su quello del linguaggio C, comune a molti altri linguaggi di programmazione. Ha la forma seguente:
for {set i 1} {$i <= 12} {incr i} { puts [format "%d x 12 = %d" $i [expr $i*12]] }
Nota: Questo costrutto è fatto di tre parti:
Tcl ha anche un costrutto foreach che può essere applicato alle liste.
I cicli FOR non sono l'unico tipo di costrutto disponibile per le iterazioni. Questo sarebbe limitativo perché in un ciclo FOR è necessario conoscere, o poter calcolare, in anticipo il numero di iterazioni che si devono effettuare. Cosa si può fare invece quando vogliamo continuare ad eseguire un gruppo di istruzioni fino a che non si verifica una qualche condizione, ma non conosciamo in precedenza quando ciò può accadere? Supponiamo ad esempio di voler leggere ed analizzare i dati di un file senza sapere in anticipo quanti dati sono contenuti nel file. In questo caso è necessario proseguire con le operazioni fino a raggiungere la fine del file. Questo è possibile, ma non facile da fare con un ciclo FOR.
Per risolvere questo problema disponiamo di un altro tipo di ciclo: il ciclo WHILE. In BASIC si presenta cosí:
J = 1 WHILE J <= 12 PRINT J, " x 12 = ", J*12 J = J + 1 WEND
Questo produce lo stesso risultato mostrato prima, ma usa il ciclo while invece del for. Notate che la struttura è composta da while, seguito da una espressione che ha come risultato un valore Booleano (vero o falso, come già detto). Se l'espressione ha valore vero, viene eseguito il codice all'interno del ciclo.
Vediamo come alternativa la versione Tcl:
set j 1 while {$j <= 12} { puts [format "%d x 12 = %s" $j [expr $j*12]] set j [expr $j + 1] }
Come vedete la struttura è assai simile, usa solo alcune parentesi graffe invece del WEND del BASIC. Ma cosa rappresenta la complessa istruzione all'interno del ciclo? Ricordate le stringhe di formato in Python? format è l'equivalente in Tcl. Il $j significa semplicemente 'il valore di j' (e non: la lettera 'j'!) ed expr significa "considera la porzione che segue come un'espressione da calcolare". Le parentesi quadre indicano in Tcl quali parti della linea devono essere eseguite per prime. Tcl è un linguaggio inusuale perché cerca di interpretare il codice in una sola passata, quindi senza le parentesi cercherebbe di visualizzare la parola 'expr' e successivamente trovando alcuni altri valori terminerebbe con un codice di errore. Dobbiamo essere noi a specificare di calcolare le somme, poi di formare la stringa, poi di visualizzare il risultato. Vi sembra complicato? Non ve ne preoccupate. Come già detto Tcl è un linguaggio inusuale con alcune caratteristiche specifiche assai buone e parecchie stranezze.
Diamo ora uno sguardo a Python:
>>> j = 1 >>> while j <= 12: ... print "%d x 12 = %d" % (j, j*12) ... j = j + 1
A questo punto il programma dovrebbe risultarvi abbastanza semplice. C'è solo una cosa da notare; il carattere (:) alla fine delle linee while e for che abbiamo visto. Questo ha il solo scopo di indicare che sta per seguire un blocco di codice. La maggior parte dei linguaggi hanno un simbolo di fine blocco (come WEND in BASIC e le parentesi graffe in Tcl) ma Python usa la scrittura indentata per indicare la struttura del programma. Questo significa che è importante che tutte le istruzioni del corpo di un ciclo siano indentate della stessa quantità, e questa è comunque una buona pratica in quanto il programma risulta più facile da leggere!
Torniamo adesso alla tabellina che abbiamo visto all'inizio del capitolo. Il ciclo che abbiamo creato va benissimo per la tabellina del dodici. Ma cosa accade per altri valori? Possiamo modificare il ciclo per visualizzare, diciamo, la tabellina del sette? dobbiamo fare più o meno cosí:
>>> for j in range(1,13): ... print "%d x 7 = %d" % (j,j*7)
Abbiamo dovuto cambiare due volte un 12 in un 7. E se volessimo un'altra tabellina ancora dovremmo cambiarli di nuovo. Non sarebbe meglio se potessimo specificare il moltiplicatore che vogliamo?
Possiamo farlo sostituendo i valori nella stringa dell'istruzione print con un'altra variabile e poi assegnando il valore alla variabile prima del ciclo:
>>> moltiplicatore = 12 >>> for j in range(1,13): ... print "%d x %d = %d" % (j, moltiplicatore, j*moltiplicatore)
Questa è la tabellina del dodici che ci è familiare. Ma adesso per trasformarla nella tabellina del sette dobbiamo solo cambiare il valore di 'moltiplicatore'.
Notate che abbiamo combinato una sequenza di istruzioni con un ciclo. Abbiamo infatti prima una istruzione singola moltiplicatore = 12 seguita in sequenza da un ciclo for.
Riprendiamo ora l'esempio precedente e avanziamo ancora di un passo. Supponiamo di voler visualizzare tutte le tabelline da quella del due a quella del dodici (evitiamo quella dell'uno che è banale). Dobbiamo solo sistemare la variabile moltiplicatore all'interno di un altro ciclo, cioè:
>>> for moltiplicatore in range(2,13): ... for j in range(1,13): ... print "%d x %d = %d" % (j,moltiplicatore,j*moltiplicatore)
Notate che la parte indentata che segue il primo
ciclo for
è identica al ciclo che abbiamo visto subito sopra.
Il tutto funziona come segue:
Viene assegnato a moltiplicatore il primo valore (2) e quindi si passa ad eseguire
il ciclo più interno.
Finito questo si assegna a moltiplicatore il secondo valore (3) e di nuovo si
esegue il ciclo interno,
e cosí via. Questa tecnica viene chiamata nidificazione
dei cicli.
Rimane un piccolo inconveniente: tutte le tabelline vengono visualizzate di seguito, ma possiamo risolverlo semplicemente facendo scrivere al programma una linea di separazione alla fine del primo ciclo, cosí:
>>> for moltiplicatore in range(2,13): ... for j in range(1,13): ... print "%d x %d = %d" % (j,moltiplicatore,j*moltiplicatore) ... print "------------------- "
Notate che la seconda istruzione print è allineata con la seconda istruzione 'for', e quindi rappresenta la seconda istruzione nella sequenza che costituisce il corpo del primo ciclo. Non dimenticate che l'indentazione è fondamentale in Python.
Potete ulteriormente sperimentare facendo in modo che il separatore indichi quale tabellina lo segue, trasformandolo cosí in una didascalia. Suggerimento: dovrete utilizare la variabile moltiplicatore ed una stringa di formato.
Altri linguaggi forniscono altri tipi di costrutti per i cicli ma di solito qualche forma di for e di while la troverete sempre. (Modula 2 e Oberon hanno solo i cicli while in quanto con questi si possono simulare cicli for come abbiamo visto sopra.) Altri cicli che potrete incontrare sono:
Punti da ricordare |
---|
|
Se avete domande o suggerimenti relativi a questa pagina
mandate un e-mail all'autore:
alan.gauld@yahoo.co.uk
o al traduttore italiano:
lfini@arcetri.astro.it