In un qualunque programma, si dispone di due tipi di strutture di controllo:
La vera bacchetta magica di un programmatore sono le iterazioni (dette anche cicli). I cicli più importanti che offre JavaScript sono:
Il ciclo while (in italiano mentre, sinché) ripete l'esecuzione di un blocco di istruzioni sinché una condizione è verificata (condizione è true).
La sua sintassi è:
while (condizione) { istruzioni }
La cosa importante da notare è che il controllo della condizione è in ingresso al ciclo, quindi, per entrare nel ciclo, la condizione deve essere già verificata: se condizione non è true, quando si arriva al ciclo while, non si entra nel ciclo ed il programma passa alle istruzioni successive.
In caso contrario (condizione è true), si entra nel ciclo, si eseguono tutte le istruzioni e, giunti all'ultima, la condizione viene ancora controllata, quindi se è ancora true (mentre, sinché è vera la condizione), si ripete l'esecuzione delle istruzioni, altrimenti si esce dal ciclo.
Ne deriva che se in condizione si verifica lo stato (il contenuto) di una variabile, questa dovrà essere almeno dichiarata prima del ciclo se non inizializzata ad un determinato valore.
È implicito che nel ciclo, condizione deve necessariamente cambiare perché questo possa terminare. Si incorrebbe semmai in un ciclo infinito: errore di programmazione detto loop infinito.
In generale, si usa il ciclo while quando un gruppo di istruzioni deve essere ripetuto per un numero di volte che non si conosce a priori.
Volendo, ad esempio che l'utente continui ad immettere dei valori sinché non venga immesso stop, dovremo:
risp != 'stop'
è verificata (true), ovvero finché l'utente non scrive 'stop'.var risp = ''; while (risp != 'stop') { risp = window.prompt('immettere un valore',''); }
Potremmo anche evitare all'utente di scrivere stop consentendogli di uscire dal ciclo
In questi due casi il metodo prompt() restituirebbe:
Se l'utente ha le due alterative per uscire, significa che bisogna ripetere il ciclo sinché l'utente immette un valore valido, ovvero finché risp != null
e (AND) risp != ''
.
Ne deriva che non è possibile inizializzare la variabile risp come stringa nulla, perché non entreremmo nel ciclo. Per iniziare il ciclo, inizializiamo risp al valore start:
var risp = 'start'; while (risp != null && risp != '') { risp = window.prompt('immettere un valore',''); }
Vogliamo adesso scrivere un elenco di numeri immessi dall'utente.
In questo script usiamo i tag html (vedi sezione) per produrre un elenco puntato.
var risp = 'start', num, cont = 1; while (risp != null && risp != '') { risp = window.prompt('immettere il ' + cont + '° valore numerico',''); num = parseFloat(risp); if (!isNaN(num)) { document.write('<li>' + num + '</li>'); cont++; } }
Il ciclo do-while è una variante del cilclo while utile nel caso in cui le istruzioni debbano essere eseguite almeno una volta.
La sua sintassi prevede:
do { istruzioni } while (condizione)
Come si nota, questo ciclo è come il ciclo while salvo una differenza:
Ne consegue che se condizione non è true prima del ciclo:
Un esempio d'uso del ciclo do-while può essere una pagina protetta da password.
Usando il ciclo while, la variabile che compare nella condizione va dichiarata e spesso anche inizializzata prima del ciclo altrimenti non si entrerebbe nel ciclo.
Usando per la nostra pagina protetta da password (123) il ciclo while, dovremo inizializzare la variabile psw ad un valore diverso da '123', ad esempio stringa nulla:
var psw = '' //inizializzazione della variabile indispensabile ad entrare nel ciclo while (psw != '123') { psw = window.prompt('password:',''); } window.alert('Benvenuto nella pagina protetta');
Come visto sopra, la dichiarazione delle variabili è facoltativa (salvo le variabili interne alle funzioni di cui ancora non si è parlato).
Visto che per entrare nel ciclo do-while, non serve che la condizione sia verificata, possiamo benissimo usare la variabile psw "al volo" e verificare soltanto dopo la risposta dell'utente che la password sia corretta o meno.
do { psw = window.prompt('password:',''); } while (psw != '123') window.alert('Benvenuto nella pagina protetta');
Finché non si digita 123, non si esce dal ciclo.
La pagina appena vista (esempio 1), che protegge la pagina con una password costringerebbe l'utente che non la conoscesse ad una chiusura forzata del browser.
Diamogli la possibilità di premere il pulsante .
do { psw = window.prompt('password:',''); } while (psw != '123' && psw != null) if (psw == '123') { window.alert('Benvenuto nella pagina protetta'); } else { window.alert('non si ha diritto ad entrare'); }
Come detto introducendo il ciclo while (vero anche per la variante do-while), esso sarà indispensabile quando bisogna eseguire delle istruzioni per un numero indeterminato di volte.
Qualora invece si conoscesse il numero di ripetizioni necessarie, avremmo due alternative:
Reputo la seconda un uso improprio del ciclo while, ma è questione di gusti: il risultato è lo stesso.
A scopo didattico, comunque, è senz'altro utile.
Ecco come organizzarci:
inizializzazione contatore while (condizione) { ... incremento contatore }
Come fare a scrivere nella pagina 10 numeri (da 0 a 9)? Ecco:
var c = 0;
)while (c < 10)
)c = c + 1;
o l'equivalente c++;
).Provando:
var c = 0; // inizializzazione del contatore while (c < 10) { // verifica della condizione document.write('<p>' + c + ' </p>'); c++; // incremento del contatore }
Che succede?
Osservando, al 1º ciclo il contatore valeva 0, al 2º valeva 1, al 3º 2... sino al 10º quando il contatore valeva 9.
Quindi il ciclo si è ripetuto 10 volte (e il contatore è passato da 0 a 9).
Grazie alle iterazioni possiamo risolvere problemi anche complessi con poche istruzioni.
Immaginiamo di avere una tabella con una dato numero di righe e colonne, le colonne numerate con i numeri naturali (1, 2, 3, ecc.) e idem le righe.
Vogliamo scrivere in ciascuna cella la coppia di numeri colonna-riga a cui la cella appartiene.
Ad esempio, con 5 colonne e 3 righe, il risultato sarebbe:
11 | 21 | 31 | 41 | 51 |
12 | 22 | 32 | 42 | 52 |
13 | 23 | 33 | 43 | 53 |
Possiamo vedere il problema come contare da 1 a 5, avendo la prima volta (per la prima riga) un suffisso 1, la seconda 2, poi 3.
Abbiamo bisogno di un ciclo while con un contatore da 1 a 5, nidificato (o annidato che dir si voglia) in un ciclo che conti da 1 a 3.
Il numero di colonne e righe lo impostiamo definendo le variabili nCol e nRig, così da poterlo cambiare a piacimento.
Lo script sara il seguente:
var nCol = 5; // numero delle colonne var nRig = 3; // numero delle righe var cR = 1; // inizializzazione ad 1 del contatore per le righe while (cR <= nRig) { // ciclo per scorrere le righe var cC = 1; // inizializzazione ad 1 del contatore per le colonne while (cC <= nCol) { // ciclo per scorrere le colonne document.write('' + cC + cR + ' '); cC++; // incremento del contatore delle colonne } document.write('<br />'); // a capo cR++; // incremento del contatore delle colonne }
Non sarebbe un esercizio inutile rifare questo script chiedendo il numero di righe e colonne all'utente, ovviamente, verificando che sia un numero valido. Si tratterebbe soltanto di unire conoscenze già sperimentate.
Troppo veloce?
Forse si apprezza meglio cosa succeda nelll'esercitazione appena svolta (questa sopra) aggiungendo un avvertimento ad ogni passaggio tramite il metodo alert dell'oggetto window, così:
var nCol = 5; var nRig = 3; var cR = 1; while (cR <= nRig) { window.alert('riga: ' + cR); // aggiunta 1 var cC = 1; while (cC <= nCol) { window.alert('colonna: ' + cC); // aggiunta 2 document.write('' + cC + cR + ' '); cC++; } document.write('<br />'); cR++; }
Come detto sopra, il ciclo while+contatore, secondo il sottoscritto, ha una sua valenza didattica, ma costituisce un uso non del tutto appropriato del ciclo while. Una volta acquisita un po' d'esperienza, quando si avesse l'esigenza di ripetere un gruppo di istruzioni per un numero di volte prestabilito, a questo provvede il ciclo for.
Nel ciclo while+contatore si adotta questa strategia:
inizializzazione contatore while (condizione) { ... incremento contatore }
Con il ciclo for avremo un codice molto più pulito, secondo la seguente sintassi:
for (inizializzazione contatore ; condizione ; incremento contatore) { ... }
Le tre espressioni tra le parentesi del for sono separate dal ; (punto e virgola). Per evitare di confondersi, è da notare che il punto e virgola, compare soltanto in questo caso (oltre ovviamente al suo uso canonico: terminare un'istruzione).
Risolviamo il problema dell'esercitazione precedente usando il ciclo for.
Bisognava scrivere i numeri da 0 a 9, ecco quindi il programma:
var i; // dichiarazione for (i = 0 ; i < 10 ; i++) { document.write('<p>' + i + ' </p>'); }
Abbiamo sprecato una riga?
Quale?
La prima!
for (var i = 0 ; i < 10 ; i++) { document.write('<p>' + i + ' </p>'); }
Ecco fatto.
Se il principiante non si dovesse trovare a proprio agio con una struttura così sintetica, può sempre usare i cicli while+contatore, ma sono sicuro che a forza di chiudere forzatamente il browser per essersi dimenticato di incrementare il contatore, comincerà a credere che quello che potrebbe confondere il neofita, si rivela una soluzione particolarmente agevole.
Visto che spesso i cicli for si usano per scorrere l'inidice di un array (prossimo argomento), è consuetudine indicare con la lettera i la "variabile di servizio" che funge da contatore.
Adesso un esercizio particolarmente semplice: scriviamo i numeri interi pari da 2 a 100.
for (var i = 2 ; i <= 100 ; i = i + 2) { document.write(i + ' '); }
Costriamo ora la tavola pitagorica.
Lasciamo da parte la grafica, anzi accontentiamoci di un aspetto a dir poco spartano, vogliamo soltanto svolgere tutti i prodotti tra un primo numero che va da 1 a 10 ed un secondo che va sempre da 1 a 10.
Avremo quindi un for per scorrere il primo fattore delle moltiplicazioni da 1 al 10 (indice i) ed nidificato nel primo, un secondo for per scorrere il secondo fattore fattore (indice j).
for (var j = 1; j <= 10 ; j++) {...
.for (var i = 1 ; i <= 10 ; i++) { for (var j = 1 ; j <= 10 ; j++) { document.write(i * j + ' '); } document.write('<br /> '); }