next up previous contents index
Next: Il costrutto di scelta Up: Costrutti condizionali e iterativi Previous: Costrutti ciclici: while e   Indice   Indice analitico

Interruzione di un ciclo

Da quanto detto fin'ora, l'unica via per uscire da un ciclo consiste nel far sì che la condizione di controllo del ciclo sia falsa; esistono però due parole chiave che consentono delle scorciatoie all'interno dei cicli: break (rompi) e continue (continua). Esse interrompono il normale flusso all'interno del corpo del ciclo e portano il programma all'inizio del corpo (continue) alla fine di esso (break). La differenza tra di esse è sottile eppure sostanziale:
while (condizione) {
istruzione-1

continue;

istruzione-N }

while (condizione) {
istruzione-1

break;

istruzione-N }

In entrambi i casi le istruzioni successive a continue o break fino a istruzione-N non vengono eseguite mai; però nel primo esempio quando il programma incontra continue, comincia ad eseguire nuovamente l'istruzione-1 e le successive fino a continue; nel secondo esempio quando il programma incontra break esce dal ciclo, cioè non esegue più nessuna istruzione interna al corpo del while. Vediamo un semplice esempio:


// ex3_5_1.cpp
// il programma accetta numeri interi e, se viene
// inserito 0 viene restituita la somma e esce
#include <iostream.h>
void main () {
   int somma = 0;
   int n;
   while (true) {   // ciclo infinito: true e' sempre vero
      cout << "? "; cin >> n;
      if (n == 0) {
         cout << "\n somma = " << somma;
         break;
      }
      somma += n;
   }
}

Nel prossimo esempio, oltre ad utilizzare continue, mostriamo un utilizzo tipido di alcune funzioni di libreria per calcolare dei numeri pseudocasuali 3.3. Si faccia bene attenzione a tale procedura, che verrà spesso ripresa negli esempi in questo testo; essa consiste in tre passaggi fondamentali:

  1. si sceglie un seme (ovvero un numero intero) che abbia una parvenza di casualità; ad esempio non è una buona idea scegliere come seme l'anno in corso, perché avremmo per tutto l'anno lo stesso seme e dunque gli stessi numeri pseudocasuali; è invece una idea migliore, e per questo la adottiamo nei nostri esempi, scegliere il numero dei secondi trascorsi da un certo momento 3.4 perché il ripetersi dello stesso seme è praticamente impossibile, a meno di far girare il programma due volte in un solo secondo;
  2. si inizializza il generatore di numeri pseudocasuali con il seme scelto; in pratica viene automaticamente creato un lungo elenco di numeri interi pseudocasuali basati sul seme da noi fornito; ovviamente fornendo due semi uguali si ottiene lo stesso elenco;
  3. si ``pesca'' quando occorre il numero successivo da tale lista; si noti che si tratta in genere di numeri interi molto grandi (potrebbero essere dell'ordine di $4 \cdot 10^9$ o anche molto di più), mentre i numeri che solitamente servono ai nostri scopi sono piccoli (fino a 6 se vogliamo simulare il lancio di un dado, fino a 90 per l'estrazione di un numero al lotto, fino a 52 per estrarre una carta da un mazzo di carte da poker e simili); dobbiamo quindi fare in modo di ``rimpicciolire'' il numero, senza perdere la componente aleatoria: il trucco da noi utilizzato è quello di prendere il resto della divisione intera del numero pseudocasuale per il massimo numero che vogliamo potere estrarre; ad esempio per un mazzo di carte da poker, se $n$ è il numero pseudocasuale, possiamo essere sicuri che $(n \, \% \, 52) + 1$ è un numero pseudocasuale che fa al nostro caso.

Vediamo in pratica questo procedimento:


// ex3_5_2.cpp
// simula il lancio di un dado
#include <iostream.h>
#include <stdlib.h>    // contiene srand() e rand()
#include <time.h>      // contiene time(0)
void main() {
   // scegliamo un seme prendendo il numero di secondi trascorsi
   // dalla mezzanotte del 1 gennaio 1970
   // nota: la data e' puramente indicativa e potrebbe dipendere
   // dal compilatore utilizzato
   int seme = time(0);  // passaggio 1
   // inizializziamo il generatore di numeri pseudocasuali
   srand (seme);       // passaggio 2
   int dado, tentativo;
   while (1) {         // infinite loop
      cout << "scegli un numero da 1 a 6: ";
      cin >> tentativo;
      if ( (tentativo < 1) || (tentativo > 6) )
         continue;     // l'utente immette un dato non valido
                       // si ricomincia all'inizio del ciclo
      dado = ( rand() % 6 ) + 1;   // passaggio 3
      cout << "e' uscito " << dado << "\n";
      if (dado == tentativo)
         cout << "hai vinto :-)\n";
      else
         cout << "hai perso :-(\n";
      cout << "vuoi giocare ancora (s/n) ? ";
      char ancora;
      cin >> ancora;
      if ( (ancora == 'n') || (ancora == 'N') )
         break;
   }
}

esempio di output:
scegli un numero da 1 a 6: 5
e' uscito 4
hai perso :-(
vuoi giocare ancora (s/n) ? s
scegli un numero da 1 a 6: 5
e' uscito 5
hai vinto :-)
vuoi giocare ancora (s/n) ? n

ex-2
si scriva un programma che accetti numeri reali positivi; se viene fornito un numero reale negativo, il programma restituisce il loro prodotto e esce
ex-3
si scriva un programma che simuli il lancio di due dadi e stampi il risultato, fino a quando l'utente non decida di terminare il programma, utilizzando la stessa tecnica dell'esempio ex3_5_2.cpp


next up previous contents index
Next: Il costrutto di scelta Up: Costrutti condizionali e iterativi Previous: Costrutti ciclici: while e   Indice   Indice analitico
Claudio Cicconetti
2000-09-06