Sei sulla pagina 1di 99

Corso di Fondamenti di Informatica

Ingegneria delle Comunicazioni – BCOR


Ingegneria Elettronica – BELR

Introduzione al C

Unità 4 – Istruzioni di Ciclo

D. Bloisi, A.Pennisi, S. Peluso, S. Salza


Sommario – Unità 4
•  Ripetizione di istruzioni
•  Istruzione while!
•  Ciclo di lettura
•  Schemi di ciclo
•  Istruzione for!
•  Istruzione do
•  Cicli annidati
•  Istruzioni di controllo del flusso

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 2


Istruzioni di controllo del flusso
Finora abbiamo visto diversi tipi di istruzioni
(senza contare le dichiarazioni):
• istruzioni semplici:
– invocazione di funzioni
– istruzioni semplici, ovvero assegnazione o uso di un
operatore di incremento/decremento seguito da ";"
– istruzioni di uscita (break e return)
• istruzioni composte (o strutturate)
– blocco di istruzioni ({})
– istruzioni condizionali (if-else, if, switch)

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 3


Ripetizione di istruzioni
Nei linguaggi di programmazione esistono due
modi per ottenere la ripetizione di istruzioni:

Ø  l'utilizzo di istruzioni di ciclo (o iterative),


che sono una forma di istruzione composta

Ø  l'utilizzo di funzioni ricorsive

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 4


Cicli definiti ed indefiniti
Si distinguono due tipi di ciclo, che si differenziano in
base a come viene determinato il numero di iterazioni
(ripetizioni del corpo del ciclo):

Ø  Nei cicli definiti il numero di iterazioni è noto


prima di iniziare l'esecuzione del ciclo.

Ø  Nei cicli indefiniti il numero di iterazioni non è noto


prima di iniziare l'esecuzione del ciclo, ma è legato al
verificarsi di una condizione (questo dipende a sua
volta dalle operazioni eseguite nel corpo del ciclo).

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 5


Esempi
Ciclo definito:
Per 10 volte ripeti la stampa di un *.
• Numero di iterazioni noto a tempo di compilazione.

Ciclo indefinito:
Finché l’utente non sceglie di smettere,
stampa un * e chiedi all’utente se smettere.
• Numero di iterazioni noto a tempo di esecuzione.

In C, entrambi i tipi di ciclo possono essere


realizzati attraverso l’istruzione while.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 6
Ciclo while!
L’istruzione while consente la ripetizione di una
istruzione.

Sintassi
while (condizione)!
istruzione!

• condizione è un’espressione
• istruzione (detta anche il corpo del ciclo) è una
singola istruzione (anche composta come un
blocco di istruzioni)
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 7
Semantica
1.  La condizione è valutata.
2.  Se la condizione è vera, allora l’istruzione è
eseguita e successivamente si ritorna sulla
valutazione della condizione, procedendo così
fino a quando la condizione risulta falsa.
3.  Si esegue poi l’istruzione successiva al ciclo
while.
Il corpo del ciclo viene eseguito finché la condizione si
mantiene vera. Non appena questa diventa falsa, si esce
dal ciclo e si continua l’esecuzione con l’istruzione
successiva al while.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 8
Esempio

stampa di 100 asterischi (ciclo definito)


int i = 0;
while (i < 100) {
printf("*");
i++;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 9


Controllo del flusso

≠0
while(condizione){! vero
!istruzione-1! condizione
!…!
!istruzione-n!
}! 0
istruzione-n+1! istruzione-1 falso

istruzione-n

istruzione-n+1

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 10


Ciclo while per la lettura
lettura e stampa su video di un insieme di
caratteri in input.
ciclo
#include <stdio.h>
Indefinito
int main () {
int c; Le iterazioni continuano
c = getchar(); fino a quando non
while (c != EOF) { vengono premuti
putchar(c); contemporaneamente i
c = getchar(); tasti CTRL e Z (Windows)
} oppure
return 0; CTRL e D (Unix)
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 11
Funzione getchar!
Legge il prossimo carattere dallo standard input
e lo restituisce come valore intero

int getchar( void );

Il carattere letto è restituito come int.


Se si raggiunge End Of File o viene riscontrato
un errore in lettura, la funzione ritorna il valore
della costante simbolica di tipo int EOF (che
generalmente vale -1) definita in stdio.h.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 12
Funzione putchar!
Visualizza sullo standard output il carattere
immagazzinato in c

int putchar( int c );

Se non ci sono errori, lo stesso carattere letto


viene restituito.
Se si verifica un errore, viene restituito EOF.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 13


Ciclo while per la lettura
Versione alternativa

Lettura e stampa su video di un insieme di


caratteri in input.
#include <stdio.h> ciclo
int main () { indefinito
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 14


Esempio di esecuzione

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 15


Esempio
stampa del doppio degli interi letti in input.
#include <stdio.h>
int main () { ciclo
int c, dato; indefinito
c = scanf("%d", &dato);
while (c != EOF) {
dato *= 2;
printf("%d\n", dato);
c = scanf("%d", &dato);
}
return 0;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 16
Struttura generale del ciclo di lettura

lettura del primo elemento;


while (elemento è valido) {
elaborazione elemento;
lettura elemento successivo;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 17


Esempio di ciclo while:
divisione con le sottrazioni
int dividendo, divisore, quoziente, resto;
dividendo = ...;
divisore = ...;
quoziente = 0;
resto = dividendo; ciclo
while (resto >= divisore) { definito
quoziente++;
resto -= divisore;
}
printf("quoziente = %d\n", quoziente);
printf("resto = %d\n", resto);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 18


Esempio di ciclo while: potenza
int base, esponente, potenza;
base = ...;
esponente = ...;
potenza = 1;
while (esponente > 0) { ciclo
potenza *= base; definito
esponente--;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 19


Esempio di ciclo while: prodotto con le
somme
int moltiplicando, moltiplicatore, prodotto;
moltiplicando = ...;
moltiplicatore = ...;
prodotto = 0;
while (moltiplicatore > 0) { ciclo
prodotto += moltiplicando; definito
moltiplicatore--;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 20


Elementi caratteristici nella progettazione
di un ciclo
Definizione del valore delle
variabili utilizzate nel ciclo prima
dell’inizio dell’esecuzione del ciclo Espressione valutata all’inizio di
ogni iterazione, il cui valore di
verità determina l’esecuzione del
inizialiazzazione corpo del ciclo o la fine del ciclo

while (condizione) {
operazione Calcolo del risultato parziale
ad ogni iterazione del ciclo
passo successivo (nel corpo del ciclo)

}
Operazione di incremento/decremento
della variabile che controlla le
ripetizioni del ciclo (nel corpo del ciclo)

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 21


Terminazione
Una volta progettato il ciclo occorre verificarne la
terminazione.
Occorre, cioè, verificare che l’esecuzione delle
istruzioni del ciclo possa modificare il valore
della condizione in modo da renderla falsa.
Esempio:
L'istruzione moltiplicatore--; consente di
rendere la condizione (moltiplicatore > 0)
falsa, se moltiplicatore è un numero intero
positivo.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 22
Errori comuni nella scrittura di cicli while
(1/3)
Mancata inizializzazione di una variabile che
viene utilizzata nella condizione del ciclo.
int i;
while (i != 0) {
printf("%d\n", i);
printf("%d\n", i*i);
printf("prossimo intero\n");
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 23


Errori comuni nella scrittura di cicli while
(2/3)
Mancato aggiornamento delle variabili che
compaiono nella condizione del ciclo.
int i, dato;
printf("inserisci intero:\n");
i = scanf("%d", &dato);
while (i != EOF) {
printf("quadrato di %d = %d\n",
dato, dato*dato);
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 24


Errori comuni nella scrittura di cicli while
(3/3)
Numero di iterazioni errato di 1

Esempio: stampa di 10 asterischi

int i = 0;
while (i <= 10) { // corretto: (i < 10)
printf("*");
i++;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 25


Schemi di ciclo
Ø  contatore: conta il numero di valori in un
insieme
Ø  accumulatore: accumula i valori di un insieme
Ø  valori caratteristici di un insieme: determina un
valore caratteristico tra i valori in un insieme
(ad esempio, il massimo, quando sui valori
dell'insieme e definito un ordinamento)

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 26


Schema di ciclo contatore: numero di interi
immessi in input
int d, i;
int contatore = 0;
printf("inserisci intero:\n");
i = scanf("%d", &d);
while (i != EOF) {
contatore++;
printf("ho letto: %d\n", d);
printf("inserisci intero:\n");
i = scanf("%d", &d);
}
printf("\nFine lettura, ho letto %d "
" interi\n", contatore);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 27


Schema di ciclo contatore: numero di interi
positivi immessi in input
int d, i;
int contatore = 0;
printf("inserisci intero:\n");
i = scanf("%d", &d);
while (i != EOF) {
if(d > 0) contatore++;
printf("ho letto: %d\n", d);
printf("inserisci intero:\n");
i = scanf("%d", &d);
}
printf("\nFine lettura, ho letto %d "
" interi positivi\n", contatore);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 28


Schema di ciclo accumulatore: somma valori
interi
int d; //intero corrente
int i;
int somma; //variabile usata come accumulatore
somma = 0;
printf("inserisci intero:\n");
i = scanf("%d", &d);
while (i != EOF) {
somma += d;
printf("inserisci intero:\n");
i = scanf("%d", &d);
}
printf("\nSomma totale = %d\n", somma);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 29


Schema di ciclo accumulatore: prodotto valori
interi
int n; //intero corrente
int i;
int prodotto; //variabile usata come accumulatore
prodotto = 1;
printf("inserisci intero:\n");
i = scanf("%d", &n);
while (i != EOF) {
prodotto *= n;
printf("inserisci intero:\n");
i = scanf("%d", &n);
}
printf("\nProdotto totale = %d\n", prodotto);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 30


Schema di ciclo valori caratteristici di un insieme:
massimo di un intervallo noto
Problema
int max; // massimo corrente
trovare il massimo di un
max = 0;
insieme di numeri interi
int d, i;
dati in input.
printf("inserisci intero:\n");
i = scanf("%d", &d); Assunzioni
while (i != EOF) { intervallo di interi noto,
if (d > max) max = d; è possibile denotare
printf("inserisci intero:\n"); valori estremi (es. tutti i
i = scanf("%d", &d); valori sono > 0)
}
printf("\n"); l’insieme di interi può
if (max == 0) essere vuoto
printf("Insieme di valori vuoto\n");
else
printf("Massimo intero letto = %d\n", max);
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 31
Schema di ciclo valori caratteristici di un insieme:
massimo di un insieme non vuoto
double f; // reale corrente Problema
double max; // massimo corrente trovare il massimo di un
int i; insieme di numeri reali
printf("inserisci dato:\n"); dati in input.
i = scanf("%lf", &f);
max = f;
Assunzioni
while (i != EOF) {
nell’insieme vi è almeno
if (f > max) max = f;
un reale
printf("inserisci dato:\n");
i = scanf("%lf", &f); l’intervallo di reali non è
} noto, non si possono
printf("\nMassimo = %f\n", max); denotare i valori estremi.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 32


Schema di ciclo valori caratteristici di un insieme:
massimo nel caso generale
double f; // reale corrente
double max = 0; // massimo corrente Problema
int i; trovare il massimo di un
printf("inserisci dato:\n"); insieme di numeri reali
i = scanf("%lf", &f); dati in input.
if(i == EOF)
printf("\nInsieme di valori vuoto\n");
else { Assunzioni
max = f; l’insieme di reali
while (i != EOF) { potrebbe essere
if (f > max) max = f; vuoto
printf("inserisci dato:\n");
i = scanf("%lf", &f); l’intervallo di reali
} non è noto
printf("\nMassimo = %f\n", max);
} Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 33
Istruzioni di ciclo
Il C mette a disposizione tre forme di istruzioni di
ciclo:
• ciclo while
• ciclo for
• ciclo do-while
Il ciclo while è sufficiente per esprimere qualsiasi
ciclo esprimibile con for e do.
In alcune situazioni è più conveniente codificare
un algoritmo utilizzando gli altri tipi di ciclo.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 34
Ciclo controllato da contatore (while)
Una situazione comune di utilizzo dei cicli è quella in cui il
ciclo fa uso di una variabile (detta di controllo) che ad ogni
iterazione varia di un valore costante, ed il cui valore
determina la fine del ciclo.
variabile di controllo i
verifica
inizializzazione int i = 1;
while (i <= 10) {
printf("%d\n", i * i);
incremento /
i++;
decremento }
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 35
Ciclo controllato da contatore (for)
L’istruzione di ciclo for è adatta ad esprimere le situazioni
in cui si utilizzano variabili di controllo.

variabile di inizializzazione verifica incremento /


controllo i decremento
int i;
for (i = 1; i <= 10; i++ )
printf("%d\n", i * i);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 36


Istruzione for!
Sintassi
for (inizializzazione ; condizione ; incremento )
!
!istruzione!

• inizializzazione è un’espressione con side-effect di


inizializzazione di una variabile di controllo (tipicamente
un’assegnazione).
• condizione è un’espressione condizionale.
• incremento è un’espressione con side-effect che
tipicamente consiste nell’incremento della variabile di
controllo.
• istruzione è una singola istruzione (detta anche il
corpo del ciclo for ).
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 37
Semantica
for (inizializzazione ; condizione ; incremento )
istruzione
è equivalente a

inizializzazione ;
while (condizione) {
istruzione
incremento ;
}
Nota: C’è un’eccezione che riguarda l’istruzione
continue, che viene tradotta in modo più complicato.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 38


Controllo del flusso
for (inizializzazione ; condizione ; incremento ) {
istruzione-1 inizializzazione

istruzione-n
}
istruzione-n+1 ≠0
vero
condizione

istruzione-1 0

falso
istruzione-n
incremento
istruzione-n+1

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 39


Osservazioni sul ciclo for (1/3)
Ciascuna delle tre parti del for (inizializzazione ,
condizione e incremento ) può mancare.
In ogni caso i ";" vanno comunque inseriti.
Se manca condizione, viene assunta pari al valore 1
(vero).

Esempio:
for(;;)

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 40


Osservazioni sul ciclo for (2/3)
La sintassi del for permette che le tre parti siano delle
espressioni qualsiasi, purché inizializzazione ; e incremento ;
siano delle istruzioni (in particolare, facciano side-effect).

Nell’uso del ciclo for è però buona norma:


– usare le tre parti del for in base al significato descritto,
con riferimento ad una variabile di controllo;
– non modificare la variabile di controllo nel corpo del
ciclo.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 41


Osservazioni sul ciclo for (3/3)
In generale, inizializzazione e/o incremento possono
essere una sequenza di espressioni con
side-effect separate da ",".
Questo permette di inizializzare e/o
incrementare più variabili contemporaneamente.
int i, potDi2;
for (i=0, potDi2=1; i < 10; i++, potDi2 *= 2)
printf("2^%d = %d\n", i, potDi2);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 42


Cicli for: esempi
Il ciclo for è usato principalmente per realizzare cicli definiti.
int i;
• for (i = 1; i <= 10; i++) ...
valori assunti da i: 1, 2, 3, ..., 10
• for (i = 10; i >= 1; i--) ...
valori assunti da i: 10, 9, 8, ..., 2, 1
• for (i = -4; i <= 4; i = i+2) ...
valori assunti da i: -4, -2, 0, 2, 4
• for (i = 0; i >= -10; i = i-3) ...
valori assunti da i: 0, -3, -6, -9
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 43
Esempio: codice caratteri

int i;
for (i = 33; i <= 62; i++) {
char c = (char)i;
printf("i = %d -> c = %c\n", i, c);
}

Stampa dei caratteri ASCII compresi tra 33 e 62.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 44


Esempio: esecuzione

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 45


Istruzione do-while!
Sintassi
do!
!istruzione!
while (condizione);!

• condizione è un’espressione che restituisce un


valore vero (≠ 0) o falso (0)
• istruzione è una singola istruzione (detta anche
il corpo del ciclo)

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 46


Semantica
do!
!istruzione!
while (condizione);!
è equivalente a

istruzione ;
while (condizione)!
!istruzione!

Quindi:
• viene prima eseguita istruzione
• poi viene valutata condizione, se è vera, si torna ad eseguire istruzione,
procedendo così fino a quando condizione diventa falsa
• a questo punto, si passa ad eseguire l’istruzione che segue il ciclo do
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 47
Esempio

int i = 0;
do {
printf("*");
i++;
} while (i < 100);

Stampa di 100 asterischi

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 48


Osservazioni sul ciclo do-while!
Ø  Il corpo del ciclo viene eseguito almeno una
volta.

Ø  Non è, in generale, necessario inizializzare le


variabili che compaiono nella condizione prima
di iniziare l'esecuzione del ciclo.
E’ sufficiente che tali variabili vengano
inizializzate nel corpo del ciclo stesso.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 49


Esempio
somma gli interi letti da input fino a quando non viene immesso 0.

#include <stdio.h>

int main() {
int i;
int somma = 0;
do {
printf("inserisci intero (0 per terminare):\n");
scanf("%d", &i);
somma = somma + i;
} while (i != 0);
printf("\nTotale = %d\n", somma);
return 0;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 50
Domanda
Cosa stampa il frammento di codice seguente?

int i;
do {
i = 0;
printf("*");
i++;
} while (i < 100);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 51


Buona norma
La sintassi del ciclo do richiede che ci sia un ";" dopo
while (condizione).
Per aumentare la leggibilità del programma, in particolare
per evitare di confondere la parte while(condizione); di un
ciclo do, con un’istruzione while con corpo vuoto,
conviene in ogni caso racchiudere il corpo del ciclo do in
un blocco, ed indentare il codice come segue:
do {
istruzione
} while (condizione);

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 52


Controllo del flusso
do {
istruzione-1
… istruzione-1

istruzione-n istruzione-n
} while (condizione);
istruzione-n+1
0 ≠0
falso vero
istruzione-n+1 condizione

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 53


Validazione dell’input
Spesso è necessario effettuare una validazione
(convalida, dall’inglese validation) di un dato di
input immesso dall’utente.

Nel caso in cui l’utente abbia immesso un dato


non valido, potrebbe essere necessario ripetere la
richiesta del dato stesso.

La validazione può essere realizzata


intuitivamente utilizzando un ciclo do-while.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 54


Esempio
Scrivere un frammento di programma che legga da input
un intero, ripetendo la lettura fino a quando non venga
immesso un intero positivo, e restituisca l’intero positivo
letto.
...
int i;
do {
printf("inserisci un intero positivo:\n");
scanf("%d", &i);
} while (i <= 0);
// all’uscita dal ciclo i e’ un intero positivo
...

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 55


Esecuzione

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 56


Equivalenza tra ciclo while e ciclo
do-while!
do {
printf("inserisci un intero positivo:\n");
scanf("%d", &i);
} while (i <= 0);
equivale a
printf("inserisci un intero positivo:\n");
scanf("%d", &i);
while (i <= 0) {
printf("inserisci un intero positivo:\n");
scanf("%d", &i);
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 57


Insieme completo di istruzioni di controllo

Due programmi si dicono equivalenti se, sottoposti agli


stessi dati di ingresso,
Ø  entrambi non terminano, oppure
Ø  entrambi terminano producendo gli stessi risultati in
uscita.

Un insieme di istruzioni di controllo del flusso si dice


completo se per ogni programma nel linguaggio ne esiste
uno equivalente scritto solo con le strutture di controllo
contenute nell'insieme.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 58


Teorema di Böhm e Jacopini

La sequenza, l'istruzione if-else e l'istruzione while


formano un insieme di istruzioni completo.

Nota: La sequenza è la normale elencazione di istruzioni


perché vengano eseguite una di seguito all'altra nell'ordine
in cui sono state scritte dal programmatore.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 59


Esempio: calcolo del massimo comune
divisore (MCD)
Specifica
Si vuole realizzare un programma che, dati due interi
positivi x ed y, calcoli e restituisca il massimo comun
divisore mcd(x, y).

Il massimo comun divisore di due interi x ed y è il più


grande intero che divide sia x che y senza resto.
Esempio
mcd(12, 8) = 4
mcd(12, 6) = 6
mcd(12, 7) = 1

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 60


MCD: sfruttando direttamente la
definizione
Ø  Cerchiamo il massimo tra i divisori comuni di x ed y

Ø  Osservazione: 1 ≤ mcd(x, y) ≤ min(x, y)


Quindi, si provano i numeri compresi tra 1 e min(x, y).

Ø  Conviene iniziare da min(x, y) e scendere verso 1.


Appena si è trovato un divisore comune di x ed y,
lo si restituisce.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 61


MCD: primo raffinamento
dell’algoritmo
massimoComunDivisore di int x ed int y {
int mcd;
inizializza mcd al minimo tra x ed y
while ((mcd > 1) && (non si è trovato un divisore comune))
if (mcd divide sia x che y)
si è trovato un divisore comune
else
mcd--;
pseudocodice
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 62


Osservazioni
• Il ciclo termina sempre perché ad ogni iterazione
– o si è trovato un divisore,
– o si decrementa mcd di 1 (al più si arriva ad 1).

• Per verificare se si è trovato il mcd si utilizza una


variabile intera che rappresenta un valore booleano (usata
nella condizione del ciclo).

• Per verificare se x (o y) divide mcd si usa l’operatore "%".

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 63


MCD: problemi legati alla prima
versione dell’algoritmo
Quante volte viene eseguito il ciclo nel precedente
algoritmo?

Ø  caso migliore: 1 volta, quando x divide y o viceversa


senza resto
Es. mcd(500, 1000)

Ø  caso peggiore: min(x,y) volte, quando mcd(x,y) = 1


Es. mcd(500, 1001)

Quindi, il precedente algoritmo si comporta “male” se


x e y sono grandi e mcd(x, y) è piccolo.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 64


MCD usando il metodo di Euclide
Il metodo di Euclide permette di ridurre velocemente il
calcolo a numeri più piccoli, sfruttando la seguente
proprietà:

Esempio
mcd(12, 8) = mcd(12 – 8, 8) = mcd(4, 8 - 4) = 4

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 65


Dimostrazione del metodo di Euclide

La validità di questo metodo si dimostra facilmente,


mostrando che i divisori comuni di x e y sono anche
divisori di x − y (nel caso in cui x > y).

http://it.wikipedia.org/wiki/Algoritmo_di_Euclide

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 66


Codifica del metodo di Euclide per il
calcolo del MCD
#include <stdio.h>

int main ()
{
int x = 210;
int y = 63;
while (x != y) {
if (x > y)
x = x - y;
else // significa che y > x
y = y - x;
}
printf("mcd = %d\n", x);
return 0;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 67
MCD: ammissibilità dei valori degli
argomenti
Se x = y = 0?
Il risultato è 0.

Se x = 0 e y > 0 (o viceversa)?
Il risultato dovrebbe essere y, ma l'algoritmo
entra in un ciclo infinito.

Se x < 0 e y è qualunque (o viceversa)?


L'algoritmo entra in un ciclo infinito.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 68


Codifica rivista del metodo di Euclide
per il calcolo del MCD
#include <stdio.h>

int main ()
{
int x = 210;
int y = 63;
if ((x > 0) && (y > 0)) {
while (x != y)
if (x > y)
x = x - y;
else // significa che y > x
y = y - x;
printf("mcd = %d\n", x);
}
else
printf("dati errati\n");
return 0;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 69
MCD usando il metodo di Euclide con i
resti (1/2)
Cosa succede nel precedente algoritmo se x è molto
maggiore di y (o viceversa)?

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 70


MCD usando il metodo di Euclide con i
resti (2/2)
Per comprimere questa lunga sequenza di sottrazioni è
sufficiente osservare che quello che in fondo si calcola è
il resto della divisione intera.

Metodo di Euclide

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 71


Codifica del metodo di Euclide con I
resti per il calcolo del MCD
int main ()
{
int x = ...;
int y = ...;
while ((x != 0) && (y != 0)) {
if (x > y)
x = x % y;
else
y = y % x;
}
printf("mcd = %d\n", (x != 0)? x : y);
return 0;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 72
Cicli annidati
Il corpo di un ciclo può contenere a sua volta un ciclo,
chiamato ciclo annidato.
E’ possibile annidare un qualunque numero di cicli.

int main () { Stampa della tavola


int const NMAX = 10; pitagorica
int riga, colonna;
for(riga = 1; riga <= NMAX; riga++) {
for(colonna = 1; colonna <= NMAX; colonna++)
if(riga * colonna < 10)
printf(" %d ", riga * colonna);
else
printf("%d ", riga * colonna);
printf("\n");
}
return 0;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 73
Output prodotto

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 74


Esempio di doppio ciclo: stampa di
una piramide di asterischi
il numero di iterazioni di un ciclo più interno può dipendere
dall’iterazione del ciclo più esterno
Esempio
stampa di una piramide di asterischi

Per la stampa della generica riga r:


stampa (altezza − r) blank e (2 ・ r − 1) asterischi.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 75
Codice piramide asterischi
int altezza, riga, i;
printf("Altezza = ");
scanf("%d", &altezza);
printf("\n");
for (riga = 1; riga <= altezza; riga++) {
// 1 iterazione per ogni riga della piramide
for (i = 1; i <= altezza - riga; i++)
printf(" "); // stampa gli spazi bianchi iniziali
for (i = 1; i <= riga * 2 - 1; i++)
printf("*"); // stampa la sequenza di asterischi
printf("\n"); // va a capo: la riga e’ finita
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 76


Esecuzione piramide asterischi

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 77


Esempio: potenza con un doppio ciclo
int main() {
int base = 2;
int esponente= 3;
int risultato = 1;
while (esponente > 0) {
esponente--;
// risultato = risultato * base
int moltiplicando = risultato;
int moltiplicatore = base;
int prodotto = 0;
while (moltiplicatore > 0) {
moltiplicatore--;
prodotto = prodotto + moltiplicando;
}
risultato = prodotto;
}
printf("%d\n", risultato);
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 78
Istruzioni di controllo del flusso
Le istruzioni di controllo del flusso determinano la
successiva istruzione da eseguire.

Le istruzioni if-else, if, switch, while, for, do-while


sono istruzioni di controllo del flusso di esecuzione.

Esse non permettono, però, di stabilire in modo arbitrario


la prossima istruzione da eseguire, ma forniscono una
strutturazione del programma che determina il flusso di
esecuzione.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 79


Istruzioni di salto
Ø  break (salto all'istruzione successiva al ciclo o
allo switch corrente)

Ø  continue (salto alla condizione del ciclo)

Ø  goto (salto all'istruzione etichettata)

Anche l'istruzione return può essere usata per


modificare il flusso di esecuzione, nelle funzioni
definite.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 80


Istruzione break per uscire da un
ciclo (1/2)
break permette di uscire prematuramente da un’istruzione
switch, while, for o do-while.

double a;
int i;
for (i = 0; i < 10; i++) {
printf("Immetti un reale non negativo: ");
scanf("%lf", &a);
if (a >= 0)
printf("%f\n", sqrt(a));
else {
printf("Errore\n");
break;
}
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 81
Istruzione break per uscire da un
ciclo (2/2)

Nota: nel caso di cicli annidati o di switch


annidati dentro un ciclo, l’esecuzione di un break
permette di uscire da un solo livello.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 82


Istruzione break in doppio ciclo
int main() {
int a;
int i, j;
printf("Immetti un intero non negativo: ");
scanf("%d", &a);
for (i = 0; i < 10; i++) {
printf("*");
for (j = 0; j < 10; j++) {
if(a == 2) break;
printf("*");
}
if (a >= 0) printf("%d\n", a);
else {
printf("Errore\n");
break;
}
}
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 83
Esecuzione

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 84


Rimozione del break (1/3)
L’esecuzione di un’istruzione break altera il flusso
di controllo.
Quando viene usata nei cicli:
• si perde la strutturazione del programma
• si guadagna in efficienza rispetto ad
implementare lo stesso comportamento senza
fare uso del break.

In generale, è sempre possibile eliminare


un’istruzione break.
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 85
Rimozione del break (2/3)
while (condizione) {
istruzioni-1
if (condizione-break)
break;
istruzioni-2
}
equivale a
int finito = 0; //condizione finito = false
while (condizione && !finito) {
istruzioni-1
if (condizione-break)
finito = 1; //condizione finito = true
else {
istruzioni-2
}
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 86
Rimozione del break (3/3)
double a;
int errore = 0;
int i;
for (i = 0; (i < 10) && !errore; i++) {
printf("Immetti un reale non negativo: ");
scanf("%lf", &a);
if (a > 0)
printf("%f\n", sqrt(a));
else {
printf("Errore\n");
errore = 1;
}
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 87
Istruzione continue!
L’istruzione continue si applica solo ai cicli e comporta il
passaggio alla successiva iterazione del ciclo, saltando le
eventuali istruzioni che seguono nel corpo del ciclo.

int i;
for (i = 0; i < n; i++) {
if (i % 2 == 0)
continue;
printf("%d\n", i);
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 88


Uso errato di continue!
Nota: Un possibile uso di continue è all’interno di un ciclo di lettura,
nel quale vogliamo effettuare un’elaborazione sui dati letti solo se è
verificata una determinata condizione. Bisogna però assicurarsi che ad
ogni iterazione del ciclo venga in ogni caso letto il prossimo valore.
Altrimenti il ciclo non termina.

Esempio:

leggi il prossimo dato ;


while (condizione) {
if (condizione-sul-dato-corrente )
continue; // ERRORE! viene saltata la lettura del dato
elabora il dato;
leggi il prossimo dato ;
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 89
Esempio su continue!
Cosa stampa questo programma?

#include <stdio.h>

int main() {
int i;
for (i = 0; i < 5; i++) {
if(i == 3) {
continue;
}
printf("i = %d\n", i);
}
return 0;
}

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 90


Istruzione di salto goto!
L’istruzione di salto deriva dal linguaggio macchina dove ha un ruolo
fondamentale per consentire la realizzazione dei cicli.

Il teorema di Böhm e Jacopini ha mostrato che essa non è necessaria


ai fini della completezza del linguaggio.

L’istruzione di salto comporta una interruzione del flusso


dell’esecuzione del programma, che prosegue con l’istruzione
specificata nel goto.

Per consentire il salto, le istruzioni possono avere delle etichette:

etichetta : istruzione-ciclo;

Le etichette devono essere degli identificatori.


Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 91
Sintassi e semantica di goto!
Sintassi
goto etichetta

etichetta è un identificatore che deve individuare


una istruzione del programma.

Semantica
L'esecuzione del programma prosegue con la
istruzione specificata dall'etichetta

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 92


Esempio sul goto!
int i = 0;
int x;
while (i < 100) {
printf("inserisci dato: ");
scanf("%d", &x);
if (x < 0) goto errore;
i++;
}
errore: printf("errore nei dati, programma interrotto\n");

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 93


Esecuzione

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 94


Nota sul goto!

L’uso di etichette e di istruzioni goto


è considerato come cattiva pratica di
programmazione e va riservato a casi
particolari.

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 95


Esempio su break e continue!
int x, i;
for(;;) {
printf("Inserisci un intero non negativo\n");
i = scanf("%d", &x);
printf("valore di ritorno scanf: %d\n", i);
if(x < 0) {
printf("ho detto non negativo\n");
continue;
}
else if(i != 1){
if(i == 0)
printf("formato non corretto. addio\n");
else if(i == EOF)
printf("ciao ciao\n");
break;
}
printf("Ho letto %d\n", x);
}
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 96
Valore di ritorno scanf!
int scanf ( const char * format, ... );

Read formatted data from stdin


Reads data from stdin and stores them according to the
parameter format into the locations pointed by the additional arguments.
The additional arguments should point to already allocated objects of the type
specified by their corresponding format tag within the format string.

Return Value
On success, the function returns the number of items successfully read.
This count can match the expected number of readings or fewer, even zero, if
a matching failure happens.
In the case of an input failure before any data could be successfully
read, EOF is returned.

http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 97
Esercizio su break e continue!
Si chiede di realizzare un programma in grado di leggere
da tastiera dei valori int ed elaborarli in accordo con le
seguenti condizioni:
Se il valore che viene letto è negativo, si vuole stampare un
messaggio di errore e terminare il programma.
Se il valore letto è maggiore di 100, si vuole ignorarlo e
continuare con il successivo valore in input.
Se il valore è 0, si vuole terminare il ciclo con un
messaggio di avvenuta terminazione corretta.
Altrimenti si vuole stampare il doppio dell’intero letto

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 98


Soluzione
/* Viene letto un valore intero ed elaborato purché
sia maggiore di 0 e minore di 100 */
while (scanf("%d", &value) == 1 && value !=0) {
if (value < 0) {
printf("Valore non ammesso\n");
break; /* Abbandona il loop */
}
if (value > 100) {
printf("Valore non ammesso\n");
continue; // Torna nuovamente all'inizio del loop
}
/*Elabora il valore letto*/
/*che e' sicuramente tra 0 e 100 */
printf("%d\n", 2 * value);
}
printf("programma terminato con successo");

Istruzioni di Ciclo - Unità 4 2013/2014 Pagina 99