Capitolo 4 (Deitel)
Le strutture di controllo in C
Indice degli argomenti
4.1 - Introduzione
4.2 - Concetti di base sulle iterazioni
4.3 - Concetti di base sulle iterazioni controllate da contatore
4.4 - La struttura di iterazione for
4.5 - Costrutto for: note ed osservazioni
4.6 - Esempio di utilizzo del costrutto for
4.7 - La struttura di selezione multipla switch
4.8 - La struttura di iterazione do/while
4.9 - Le istruzioni break e continue
4.10 - Gli operatori logici
4.11 - Operatori di uguaglianza e assegnamento
4.12 - Riepilogo sulla programmazione strutturata
 2000 Prentice Hall, Inc. All rights reserved.
4.1 - Introduzione
• Si suppone che chi affronta questo capitolo sia ormai in
grado di scrivere con agio dei semplici programmi in C
• Questo capitolo introduce:
– Una visione più dettagliata delle strutture di controllo
•
•
•
•
Nuovi costrutti iterativi: for e do/while
Il costrutto di scelta multipla: switch
L’uscita rapida da una struttura di controllo: break
Come saltare uno o più giri di un ciclo: continue
– Gli operatori logici per combinare varie condizioni
– I principi fondamentali sulla programmazione strutturata
 2000 Prentice Hall, Inc. All rights reserved.
4.2 - Concetti di base sulle iterazioni
• Ciclo (Loop)
– E’ costituito da un blocco di istruzioni che il computer esegue
ripetutamente finché una certa condizione resta vera
– Esistono principalmente due modi per controllare un ciclo
• Iterazione controllata da un contatore
– Il numero di ripetizioni del ciclo è ben definito e noto a priori
– Sfrutta una variabile di controllo per contare il numero di iterazioni
– Usare il costrutto while è un pò macchinoso
• Serve un’istruzione apposita nel corpo del ciclo per incrementare il contatore
• Il C offre una struttura iterativa più compatta: for
• Iterazione controllate da un valore sentinella (flag)
– Il numero di ripetizioni del ciclo è indefinito e non noto a priori
– Il valore sentinella indica la fine della sequenza di iterazioni
• Generalmente coincide con la fine dell’acquisizione dei dati
– Il costrutto while spesso non è proprio adatto ai problemi normali
• In genere almeno un giro del ciclo va sempre eseguito
• Per fare ciò, il blocco di istruzioni nel ciclo va replicato fuori (prima del ciclo)
• Il C offre una struttura iterativa più adatta allo scopo: do/while
 2000 Prentice Hall, Inc. All rights reserved.
4.3 - Concetti di base sulle
iterazioni controllate da contatore
• L’iterazione controllata da un contatore richiede di:
– Definire una variabile di controllo (contatore del ciclo) e darle un nome
– Specificare il valore iniziale della variabile di controllo (inizializzarla)
– Fornire la condizione che testa il valore della variabile di controllo ad ogni
ripetizione del ciclo, in attesa che essa assuma il valore finale
• Ovvero, quello che determinerà l’uscita dal ciclo
– Stabilire entità dell’incremento (o decremento) con cui la variabile di
controllo sarà modificata ad ogni ripetizione del ciclo
• Esempio:
int counter = 1;
while (counter <= 10){
printf( "%d\n", counter );
++counter;
}
//inizializzazione
//condizione di iterazione
//incremento del contatore
//equivalente a counter++
– L’istruzione int counter = 1;
•
•
•
•
Assegna il nome counter alla variabile di controllo
La dichiara di tipo intero (altri tipi non hanno senso)
Le riserva uno spazio in memoria
La inizializza con valore pari a 1
 2000 Prentice Hall, Inc. All rights reserved.
4.4 - La struttura di iterazione for (1/2)
• E’ un costrutto di iterazione che gestisce autonomamente
tutti i dettagli di un’iterazione controllata da contatore
• Formato di un ciclo for
for ( inizializzazione; condizione di iterazione; incremento)
istruzione
• Esempio:
for( int counter = 1; counter <= 10; counter++ )
printf( "%d\n", counter );
Non usare il
punto e virgola
– Questo ciclo di esempio stampa gli interi da 1 a 10
dopo l’ultima
espressione
– Il valore iniziale del contatore è 1, il valore finale è 10
– for è una parola riservata del linguaggio C, come while
– Nella pratica il ciclo comprende più istruzioni da eseguire
• In tal caso il blocco di istruzioni va incluso tra { }, come per il while
 2000 Prentice Hall, Inc. All rights reserved.
4.4 - La struttura di iterazione for (2/2)
• Ogni ciclo for solitamente può essere riscritto tramite un
ciclo while equivalente e viceversa:
inizializzazione;
while (condizione di iterazione){
istruzione
incremento;
}
– Tuttavia for è un costrutto più compatto ed elegante di while
– Se la variabile contatore non ha altri usi nel programma è meglio usare for
• Inizializzazione ed incremento
– Possono essere liste di istruzioni separate da virgole
– Esempio:
for (int i = 0, j = 0; j + i <= 10; j++, i++)
printf( "%d\n", j + i );
– Nell’esempio la condizione di iterazione coinvolge due variabili, che sono
inizializzate ed incrementate separatamente
 2000 Prentice Hall, Inc. All rights reserved.
4.5 - Costrutto for: note e osservazioni (1/2)
• Espressioni aritmetiche
– Inizializzazione, condizione di iterazione e incremento possono contenere
espressioni aritmetiche
– Se ad un certo punto di un programma x = 2 e y = 10, allora
for ( j = x; j <= 4 * x * y; j += y / x )
è equivalente a scrivere
for ( j = 2; j <= 80; j += 5 )
• L’incremento può essere negativo (decremento)
• Se la condizione di iterazione è inizialmente falsa
– Il corpo interno alla struttura for non viene eseguito (come col while)
– L’esecuzione procede dalla prima istruzione successiva alla struttura for
• La variabile di controllo spesso viene usata e/o stampata a
video nel corpo del ciclo, ma non è indispensabile
– Il suo valore può anche essere modificato in itinere da altre istruzioni
presenti nel corpo del ciclo
– Meglio evitare l’uso di questo tipo di istruzioni, perché potenzialmente
possono generare errori logici molto difficili poi da trovare
 2000 Prentice Hall, Inc. All rights reserved.
4.5 - Costrutto for: note e osservazioni (2/2)
• L’incremento agisce come se fosse un’istruzione posta in
coda al corpo della for
– Quindi le seguenti espressioni di incremento sono equivalenti
counter = counter +1 | counter += 1 | counter++ | ++counter
• Il diagramma di flusso for e while sono uguali
 2000 Prentice Hall, Inc. All rights reserved.
4.6 - Esempio di utilizzo del costrutto for
1 /* Fig. 4.5: fig04_05.c
2
Somma con for */
3 #include <stdio.h>
Programma
per sommare
4
i numeri pari
5 int main()
da 2 a 100
6 {
7
int somma = 0, numero;
8
9
10
for ( numero = 2; numero <= 100; numero += 2 )
somma += numero;
11
12
printf( “La somma è %d\n", somma );
13
14
return 0;
15 }
La somma è 2550
Output del
programma
 2000 Prentice Hall, Inc. All rights reserved.
4.7 - La struttura di selezione
multipla switch (1/5)
• switch
– Torna utile quando una variabile o espressione deve essere confrontata
con molteplici (o tutti i) possibili valori che può assumere
– A seconda del valore assunto, vengono intraprese azioni differenti
• Formato di una selezione switch
switch ( value ){
case 1:
istruzioni
case 2:
istruzioni
default:
istruzioni
}
–
–
–
–
La variabile o espressione da testare sta tra le ( ) che seguono switch
Prevede una sequenza di etichette case più una di default (opzionale)
Ogni “case” può contenere una o più azioni, ma le { } non sono necessarie
L’uso di istruzioni break; nel blocco di codice relativo ad una opzione
consente l’uscita immediata dalla struttura di controllo
• Vanno messe in coda ad ogni blocco per evitare di eseguire anche gli altri
– default serve ad indicare cosa fare se nessun altro case va a buon fine
 2000 Prentice Hall, Inc. All rights reserved.
4.7 - La struttura di selezione
multipla switch (2/5)
• Nota:
– Switch può solo testare una variabile o espressione che assume valori
interi (es. 1, senza apici) o costanti di carattere (es. ‘A’, tra apici)
• Diagramma di flusso di switch
caso a
vero
azione del caso a
break
azione del caso b
break
azione del caso z
break
falso
caso b
vero
falso
. . . . .
caso z
vero
falso
azione di default
 2000 Prentice Hall, Inc. All rights reserved.
4.7 - La struttura di selezione
multipla switch (3/5)
1 /* Programma che conta i voti espressi tramite lettere */
2 #include <stdio.h>
3
4 int main(){
5
int grade;
6
int aCount = 0, bCount = 0, cCount = 0, dCount = 0, fCount = 0;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
printf(
printf(
“Inserisci la lettera del voto.\n" );
“Digita il carattere di EOF per finire l’input.\n"
while ( ( grade = getchar() )
switch ( grade ){
/*
case 'A': case 'a': /*
++aCount;
/*
break;
case 'B': case 'b': /*
++bCount;
/*
break;
case 'C': case 'c': /*
++cCount;
/*
break;
case 'D': case 'd':
++dCount;
break;
 2000 Prentice Hall, Inc. All rights reserved.
!= EOF ){
switch nidificato nel while */
il voto è una A maiuscola */
o una a minuscola */
il voto è una B maiuscola */
o una b minuscola */
il voto è una C maiuscola */
o una c minuscola */
/* il voto è una D maiuscola */
/* o una d minuscola */
);
1. Inizializza
le variabili
2. Invita l’utente
a inserire i dati
3. Usa una switch
per aggiornare
il contatore
opportuno ad
ogni giro del
ciclo while
4.7 - La struttura di selezione
multipla switch (4/5)
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 }
case 'F': case 'f': /* il voto era una F maiuscola */
++fCount;
/* o una f minuscola */
break;
case '\n': case' ': /* ignora i caratteri vuoti */
break;
default:
/* respinge tutti gli altri caratteri */
printf( “Hai inserito una lettera non corretta." );
printf( " Inserisci un’altra lettera.\n" );
break;
}
}
printf(
printf(
printf(
printf(
printf(
printf(
"\nI totali per ogni voto in lettera sono:\n" );
"A: %d\n", aCount );
"B: %d\n", bCount );
"C: %d\n", cCount );
"D: %d\n", dCount );
"F: %d\n", fCount );
return 0;
 2000 Prentice Hall, Inc. All rights reserved.
4. Output dei
risultati
4.7 - La struttura di selezione
multipla switch (5/5)
Inserisci la lettera del voto.
Digita il carattere di EOF per finire l’input.
A
B
C
C
A
D
F
C
E
Visualizzazione
del programma
Hai inserito una lettera non corretta. Inserisci un’altra lettera.
D
A
B
I totali per ogni voto in lettera sono:
A:
B:
C:
D:
F:
3
2
3
2
1
–getchar è la funzione C usata per acquisire in input un singolo carattere per volta e
restituisce l’intero (convertito) corrispondente a quel carattere.
–Tale intero può essere confrontato con interi o caratteri equivalenti (messi tra apici)
–Il carattere EOF di fine acquisizione dati è CTRL-Z in windows e CTRL-D in linux
–Per eseguire le stesse azioni per vari case, si scrivono una volta sola (riunendo i case)
 2000 Prentice Hall, Inc. All rights reserved.
4.8 - La struttura di iterazione do/while (1/3)
• Il costrutto di iterazione do/while
– E’ molto simile alla struttura while
– Nel while, la condizione di iterazione viene controlla all’inizio del ciclo,
cioè prima che siano eseguite le istruzioni che compongono il ciclo
• Se la condizione è inizialmente falsa, le azioni non sono mai eseguite
– Nel do/while, la condizione di iterazione viene controllata a fine ciclo,
cioè dopo aver eseguito le istruzioni che compongono il ciclo
• Tutte le azioni sono eseguite comunque almeno una volta
• Formato di do/while:
do{
istruzione
} while ( condizione );
– È buona norma mettere sempre le { } anche quando il corpo del ciclo è
composto da una sola istruzione (non sono realmente necessarie)
 2000 Prentice Hall, Inc. All rights reserved.
4.8 - La struttura di iterazione do/while (2/3)
• Esempio (supponendo che counter = 1)
do {
printf( "%d ", counter );
} while (++counter <= 10);
– Stampa gli interi da 1 a 10
• Diagramma di flusso
- Nel while il rombo anticipava il rettangolo
Azione/i
- Nel do/while il rettangolo anticipa il rombo
vera
condizione
falsa
 2000 Prentice Hall, Inc. All rights reserved.
4.8 - La struttura di iterazione do/while (3/3)
1
/* Fig. 4.9: fig04_09.c
2
3
Usare la struttura di iterazione do/while */
#include <stdio.h>
4
5
int main(){
6
7
1. Inizializza
il contatore
int counter = 1;
8
9
do {
10
2. Ciclo di stampa
printf( "%d
11
", counter );
} while ( ++counter <= 10 );
12
13
return 0;
14 }
1
2
3
4
5
6
7
8
9
10
 2000 Prentice Hall, Inc. All rights reserved.
Attenzione che
counter++ <=10
avrebbe stampato
anche 11 !!!
Output del
programma
4.9 - Le istruzioni break e continue (1/2)
• break
– Causa l’uscita immediata dalle strutture while, for, do/while o switch
– L’esecuzione del programma prosegue a partire dalla prima istruzione che
segue sequenzialmente la fine della struttura di controllo
– Usi più comuni dell’istruzione break:
• Anticipare l’uscita da un ciclo (uscita rapida)
• Saltare tutti gli altri case una switch
• continue
– Salta le tutte le rimanenti istruzioni del corpo di una struttura iterativa
• Si usa con while, for o do/while
• Procede con l’esecuzione dell’iterazione successiva del medesimo ciclo
– Nel caso di cicli while o do/while
• La condizione di iterazione per la ripetizione del ciclo viene valutata
immediatamente dopo che l’istruzione continue è stata eseguita
– Nel caso di cicli for
• Prima si esegue l’incremento del contatore, poi viene valutata la condizione di
iterazione per la ripetizione del ciclo
 2000 Prentice Hall, Inc. All rights reserved.
4.9 - Le istruzioni break e continue (2/2)
1
/* Fig. 4.12: fig04_12.c
2
3
Uso dell’istruzione continue in una struttura */
#include <stdio.h>
4
5 int main(){
6
1. Definisce il
contatore
int x;
7
8
for ( x = 1; x <= 10; x++ ) {
9
10
if ( x == 5 )
11
continue;
/* salta la printf per l’iterazione */
2. Ciclo di
stampa
/* corrente se x == 5 */
12
13
14
printf( "%d ", x );
}
15
16
printf( "\nSi usa continue per saltare la stampa del 5\n" );
17
return 0;
18 }
1 2 3 4 6 7 8 9 10
Si usa continue per saltare la stampa del 5
 2000 Prentice Hall, Inc. All rights reserved.
Esecuzione
del programma
4.10 - Gli operatori logici
• Sono usati per costruire condizioni complesse combinando
espressioni semplici
• && (AND logico)
– Restituisce vero solo se entrambe le condizioni sono vere
– Ha priorità d’esecuzione maggiore rispetto all’operatore OR
• || (OR logico)
– Restituisce vero se almeno una delle sue condizioni è vera
• ! (NOT logico, negazione logica)
– Inverte la veridicità/falsità della condizione a cui è applicato
– E’ un operatore unario, cioè ammette un solo operando
• Sono molto utili per esprimere le condizioni di iterazione
Espressione1
Espressione2
vero
&&
falso
vero
||
falso
!falso
 2000 Prentice Hall, Inc. All rights reserved.
Risultato
falso
vero
vero
4.11 - Operatori di uguaglianza
e assegnamento (1/2)
• Uguaglianza (==) e assegnamento (=)
– Confondere i due operatori può causare gravi errori
– Anche se solitamente confonderli non causa errori di sintassi, ma logici
– Ogni espressione che restituisce un valore può essere utilizzata come
condizione in una struttura di controllo
• Se assume valori diversi allora la condizione è vera, altrimenti è falsa
• Esempio di scambio tra i due operatori:
if( payCode == 4 )
printf(“Hai un bonus!\n");
if( payCode = 4 )
printf(“Hai un bonus!\n");
Controlla il valore di payCode
Assegna a payCode il valore 4
Se vale 4, stampa “Hai un bonus”
Dato che 4 è un valore non nullo,
stampa comunque “Hai un bonus”
perché l’espressione vale VERO
L’errore è logico, non di sintassi
Il programma funziona male ma va
 2000 Prentice Hall, Inc. All rights reserved.
4.11 - Operatori di uguaglianza
e assegnamento (2/2)
• In C gli assegnamenti producono sempre un valore
– Tale valore viene assegnato alla variabile a sinistra dell’operatore (=)
• lvalues
– Sono le espressioni che possono apparire a sinistra dell’operatore di
assegnamento
– Il loro valore può cambiare durante l’esecuzione del programma
– Generalmente sono nomi di variabili
• x = 4;
• rvalues
– Sono le espressioni che possono apparire a destra dell’operatore di
assegnamento
– Possono essere anche delle costanti, cioè numeri
• Ma assolutamente non si può scrivere 4 = x;
– Gli lvalues possono essere usati come rvalues, ma mai viceversa
• y = x;
 2000 Prentice Hall, Inc. All rights reserved.
4.12 - Riepilogo sulla
programmazione strutturata (1/6)
• Programmazione strutturata
– Rende più semplice capire, testare, debuggare e modificare i
programmi rispetto alla programmazione non strutturata
• Regole della programmazione strutturata
– Sono state sviluppate dalla comunità dei programmatori
– Fanno uso solo di strutture di controllo del tipo single-entry/single-exit
– Regole:
1) Iniziare con il “diagramma di flusso elementare”, il più semplice (del top)
2) Ogni rettangolo (azione) può essere sostituito da due rettangoli in sequenza
3) Ogni rettangolo (azione) può essere sostituito da una qualsiasi struttura di
controllo (sequenza, if, if/else, switch, while, do/while o for)
4) Le regole 2 e 3 possono essere applicate in qualunque ordine e più volte
 2000 Prentice Hall, Inc. All rights reserved.
4.12 - Riepilogo sulla
programmazione strutturata (2/6)
Regola 1 – Iniziare con il più
semplice diagramma di flusso
Regola 2
Regola 2 – Qualsiasi rettangolo può
essere sostituito da 2 rettangoli in
sequenza
Regola 2
Regola 2
.
.
.
 2000 Prentice Hall, Inc. All rights reserved.
4.12 - Riepilogo sulla
programmazione strutturata (3/6)
Regola 3 – Qualsiasi rettangolo può essere sostituito con
una qualsiasi struttura di controllo
Regola 3
Regola 3
 2000 Prentice Hall, Inc. All rights reserved.
Regola 3
4.12 - Riepilogo sulla
programmazione strutturata (4/6)
• Tutti i programmi possono essere scomposti in 3 parti:
Sequenza - banale perchè attuata automaticamente dal compilatore
Selezione - if, if/else, o switch
Ripetizione - while, do/while, o for
– Ogni selezione può essere riscritta con il costrutto if e ogni iterazione
può essere riscritta con il costrutto while
• Quindi tutti i programmi si possono ridurre a:
– Sequenze
– Strutture if (selezione)
– Strutture while (ripetizione)
– Queste strutture di controllo possono essere combinate solo in due modi,
annidandole (regola 3) e mettendole in sequenza (regola 2)
– Tutto ciò promuove la semplicità della programmazione strutturata
 2000 Prentice Hall, Inc. All rights reserved.
4.12 - Riepilogo sulla
programmazione strutturata (5/6)
Vero
Falso
SELEZIONE IF
Falso
SEQUENZA
 2000 Prentice Hall, Inc. All rights reserved.
Vero
SELEZIONE IF/ELSE
4.12 - Riepilogo sulla
programmazione strutturata (6/6)
break
Vero
Vero
Falso
Falso
ITERAZIONE WHILE o FOR
break
Vero
Falso
break
Vero
Falso
Vero
SELEZIONE SWITCH
 2000 Prentice Hall, Inc. All rights reserved.
Falso
ITERAZIONE DO/WHILE
Scarica

Cap. 4 Deitel