2. Le istruzioni
• Istruzioni (statement): sono le azioni
svolte da programma
• Differiscono dalle
– Espressioni: vengono valutate e hanno un
valore
– Dichiarazioni: intruducono nome e tipo
delle variabili (e delle funzioni)
– Definizioni: definiscono il valore iniziale
delle variabili (e il corpo delle funzioni)
2
3. Principali istruzioni del C++
• Semplici
– Istruzione espressione (expression statement)
• Composte
– Blocco
• Condizionali
– if, if-else, switch
• Iterative
– While, for, do while
• Di salto
– Break, continue, goto
3
4. Teorema di Böhm e Jacopini
• Tutti i programmi possono essere scritti in
termini di tre strutture di controllo:
– Sequenza: istruzioni eseguite in ordine
– Selezione: istruzioni che permettono di
prendere strade diverse in base a una condizione
(costrutto di tipo if-then-else)
– Iterazione: istruzioni che permettono di
eseguire ripetutamente un certo insieme di altre
istruzioni (costrutti di tipo while, do e for)
4
5. Sequenza
int main()
{
int integer1, integer2, sum;
// declaration
cout << "Enter first integer" << endl;
cin >> integer1;
cout << "Enter second integer" << endl;
cin>> integer2;
sum = integer1 + integer2;
cout << "Sum is: " << sum;
//
//
//
//
//
//
prompt
read an integer
prompt
read an integer
assignment
print sum
return 0;
// successful end
}
5
6. Istruzione espressione
• <espressione>; è la forma più semplice di
istruzione
– i+2; è un'istruzione legittima, calcola la somma
e ne butta via il valore!
– cin>>i; esempio di istruzione-espressione utile
– ; istruzione nulla (può servire in alcuni casi di
iterazione, ma… va sempre commentata!)
// read input until end-of-file or item found
while (cin >> s && s != sought)
; // null statement, placed on purpose
• Attenzione ai ; dispersi
NB: vale la
regola del corto
circuito
// disaster: extra semicolon: loop body is this null statement
while (i < 10) ; // the while body is the empty statement
++i; // increment is not part of the loop
6
7. Istruzioni condizionali (if-then-else)
• Costrutto if:
if ( espressione )
istruzione
int main()
{
int n;
cout << "Inserisci un numero" << endl;
cin >> n;
if ( n > 0 )
cout << "Numero positivo ! " << endl;
cout << "Fine del programma" << endl;
return 0;
}
ramo
then
8. Istruzioni condizionali complesse
• Costrutto if-else:
if ( espressione )
istruzione1
else
istruzione2
int main()
{
int n;
cout << "Inserisci un numero" << endl;
cin >> n;
if ( n > 0 )
cout << "Numero positivo ! " << endl;
else
cout << "Numero negativo o nullo ! " << endl;
cout << "Fine del programma" << endl;
return 0;
}
ramo
then
ramo
else
8
9. Formattazione
if (numero < 0) valass = -x; else valass = x;
•Per maggior leggibilità, è bene usare
regole di incolonnamento (indentazione)
10. Istruzioni condizionali
(selezione singola)
#include <iostream>
// Calcolo del valore assoluto
int main ( ) {
// programma principale
int numero, valass; // dichiarazione delle variabili
cout << "Calcolo Valore Assoluto" << endl <<
"Inserisci Numero Intero: ";
cin >> numero;
// acquisizione valore
if (numero < 0)
condizione
valass = -numero;
ramo
if (numero >= 0)
then
valass = numero;
cout << "Numero: " << numero <<
// output
"Valore assoluto: " << valass;
// output
return 0;
}
10
11. Istruzioni condizionali
(con selezione doppia)
#include <iostream>
using namespace std;
int main() {
int numero, valass; // dichiarazione delle variabili
cout << "Calcolo del Valore Assoluto " << "Inserisci Numero Intero: "
<< endl;
cin >> numero;
// acquisizione valore
if (numero < 0)
valass = -numero;
else
valass = numero;
cout << "Numero: " << numero <<
// output
" Valore assoluto: " << valass <<endl;
// output
return 0;
}
11
12. Uso degli operatori relazionali
#include <iostream>
using namespace std;
int main() {
int num1, num2;
cout << "Enter two integers, and I will tell you" <<
"the relationship they satisfy" << endl;
cin >> num1 >> num2;
if (num1 == num2)
cout << num1 << " Is equal to " << num2 << endl;
if (num1 != num2)
cout << num1 << " Is not equal to " << num2 << endl;
if (num1 < num2)
cout << num1 << " Is less than " << num2 << endl;
if (num1 > num2)
cout << num1 << " Is greater than " << num2 << endl;
if (num1 <= num2)
cout << num1 << " Is less or equal to " << num2 << endl;
if (num1 >= num2)
cout << num1 << " Is greater or equal to " << num2 << endl;
return 0;
}
12
13. Output
>
>
>
>
>
Enter two integers, and I will tell you
the relationships they satisfy: 3 7
3 is not equal to 7
3 is less than 7
3 is less than or equal to 7
>
>
>
>
>
Enter two integers, and I will tell you
the relationships they satisfy: 22 12
22 is not equal to 12
22 is greater than 12
22 is greater than or equal to 12
13
14. Ulteriori forme di selezione
• I rami di un if o if-else possono
contenere istruzioni composte:
if ( espressione )
{seq.1 di istruzioni}
else
{seq.2 di istruzioni }
• Gli if possono essere annidati per
esprimere decisioni articolate
14
15. if-then-else annidati
if (i < 100)
if (i > 0)
cout << "Minore di 100 e maggiore di 0" << endl;
else
if (i == 0)
cout << "Uguale a zero"<< endl;
else
cout << "Minore di zero"<< endl;
else
if (i == 100)
cout << "Uguale a 100"<< endl;
else
cout << "Maggiore di 100"<< endl;
15
16. La lettura di if annidati
• In presenza di if annidati è bene imparare a valutare
rapidamente quali valori delle variabili menzionate nelle
condizioni producono l'ingresso in ciascun sotto-ramo
if (i < 100)
if (i > 0)
...; // quanto vale i??
else if (i == 0)
...; // quanto vale i??
else
...; // quanto vale i??
else if (i == 100)
...; // quanto vale i??
else
...; // quanto vale i??
16
17. Ramo else pendente (dangling)
• Potenziale ambiguità insorge
quando ci sono più if che else:
– if (n > 0) if (a>b) z = a; else z = b;
• Ogni else si associa
all’if più vicino
– l'indentazione lo rende evidente
– se incerti, usare le parentesi
– if (n > 0) {if (a>b) z = a;} else z = b;
if (n > 0)
if (a>b)
z = a;
else
z = b;
if (n > 0) {
if (a>b)
z = a;
}
else
z = b;
18. Sequenze di if
• Spesso accade di voler scrivere molti
if annidati (alternative multiple):
if (...)
fai qualcosa1;
else
if (…)
fai qualcosa2;
else
if(…)
18
19. Esempio
/* Se un numero n ha divisori primi <15, stampa il minimo,
altrimenti stampa un messaggio che lo segnala
*/
if (n % 2 == 0)
cout << n " è pari" << endl;
else
if (n % 3 == 0)
cout << n " è multiplo di 3" << endl;
else
if (n % 5 == 0)
cout << n " è multiplo di 5" << endl;
else
if (n % 7 == 0)
cout << n " è multiplo di 7" << endl;
else
if (n % 11 == 0)
cout << n " è multiplo di 11" << endl;
else
if (n % 13 == 0)
cout << n " è multiplo di 13" << endl;
else
cout << n << " non ha divisori primi< 15" << endl;
20. Una rappresentazione più leggibile
/* Se un numero n ha divisori primi <15, stampa il minimo,
altrimenti stampa un messaggio che lo segnala
*/
20
21. Iterazione a condizione iniziale
• Ciclo while
while (condizione)
Istruzione
• Si esegue istruzione fintantoché la condizione è vera
• E' detto anche ciclo a condizione iniziale
–Se alla prima valutazione la condizione è falsa, non si esegue
mai Istruzione
• Istruzione di solito contiene un'espressione che
cambia il valore di una variabile usata in condizione
• Condizione è condizione di permanenza nel ciclo
• Si usa
–Quando si deve iterare in modo indefinito, per esempio
sull'input dell'utente
–Quando si vuole ispezionare il valore delle variabili di governo
della condizione anche dopo la terminazione del ciclo
21
22. Esempio di ciclo while
variabile
di
governo
int main()
condizion
{
e
int n = 9;
cout << " PRONTI... " << endl;
while ( n > 0 ) {
cout << " ...meno " << n << endl;
n = n-1;
}
cout << " ...VIA!!! " << endl;
return 0;
}
Corpo del ciclo:
blocco di
istruzioni
22
23. Ciclo while: errori tipici
int main()
{
int n = 9;
cout << " PRONTI... " << endl;
while ( n > 0 )
cout << " ...meno " << n << endl;
n = n-1;
cout << " ...VIA!!! " << endl;
return 0;
}
ERRATO!!
Che fa?
24. Ciclo while: errori tipici
int main()
{
int n = 9;
cout << " PRONTI... " << endl;
while ( n > 0 ); {
cout << " ...meno " << n << endl;
n = n-1;
}
cout << " ...VIA!!! " << endl;
return 0;
}
ERRATO!!
Che fa?
25. Sequenze di input di lunghezza ignota
• Iterazione controllata da una "sentinella", cioè
un valore che denota la fine della sequenza
• L’iterazione avviene un numero di volte non
determinata a priori
• Procede fintantoché resta vera una
condizione
– L’inserimento, da parte dell’utente, della sentinella
al posto del valore da elaborare
• NB: si sceglie come sentinella un valore che
non appartiene all'insieme dei valori da
elaborare!
25
26. Schema tipico
cout << "fornisci valore da elaborare;
se hai finito, fornisci …" << sentinella;
cin >> valore;
while (valore != sentinella) {
elabora valore;
cout << "fornisci valore da elaborare;
se hai finito, fornisci …" << sentinella;
cin >> valore;
}
26
27. Errore tipico
while (valore != sentinella) {
cout << "fornisci valore da elaborare;
se hai finito, fornisci …" << sentinella;
cin >> valore;
elabora valore;
}
27
28. Esempio di ciclo con sentinella
• Calcolare la media di una serie di
numeri interi positivi inseriti dall’utente
• Il valore –1 indica la fine del flusso
• Applicazione
– Calcolo della media dei voti della classe
con un numero arbitrario di voti
28
29. Pseudocodice
• Inizializzazione delle variabili:
• Inizializza il totale a zero
• Inizializza il contatore a zero
• Lettura, addizione e conteggio dei voti:
• Leggi da terminale il prossimo voto (potrebbe essere la
sentinella)
WHILE l’utente non ha ancora immesso la sentinella
– Aggiungi il voto al totale
– Aggiungi uno al contatore
– Leggi il prossimo voto (potrebbe essere la sentinella)
• Calcolo e scrittura della media:
– IF il contatore è diverso da zero
• Calcola la media (uguale a totale / contatore)
Stampa a terminale la media
– ELSE
Stampa a terminale “Non è stato immesso alcun voto”
30. Programma media di una sequenza
int main() {
int valore, sum = 0, num = 0, media; // la media verrà troncata
const int sentinella = -1;
cout << "Fornisci valore..." << endl;
cout << "Per finire fornisci " << sentinella << endl;
cin >> valore;
while (valore != sentinella) {
sum += valore;
++num;
cout << endl << "Fornisci valore..." << endl;
cout << "Per finire fornisci" << sentinella << endl;
cin >> valore;
}
if (num > 0) {
media = sum / num; // di che tipo è media??
cout << "La media dei valori è " << media;
}
else
cout << "Nessun valore immesso" << endl;
return 0;
}
31. Versione con condizione nell'input
#include <iostream>
using namespace std;
Si usa ctrl-z come sentinella, che
termina del tutto l'input, oppure un
carattere non numerico
int main() {
int contatore = 0, voto = 0;
float media = 0.0, totale = 0.0;
cout << "Inserisci serie di numeri; ctl-z per terminare" << endl;
cout << "Prox voto: " << endl;
while (cin >> voto) {
totale += voto;
++contatore;
cout << "Prossimo voto: " << endl;
}
if (contatore > 0) {
media = totale / contatore;
cout << endl << "Numero voti inseriti: " << contatore
<< " Somma numeri inseriti: " << totale << " Media dei voti: "
<< media << endl;
} else
cout << "Serie vuota" << endl;
return 0;
}
31
32. Gli operatori ++ e -• Attenzione all'uso degli operatori incremento e decremento (++
e --)
• ++i è un'espressione che prima incrementa i e poi ne fornisce il
valore (pre-incremento)
• i++ è un'espressione che prima fornisce il valore di i e poi la
incrementa (post-incremento)
– Esempio: sia la dichiarazione int c = 5;
cout << ++c;
stampa 6
cout << c++;
stampa 5
in entrambi i casi al termine dell'istruzione c ha valore 6
• Il post-incremento è più costoso, perché deve salvare il valore
precedente all'incremento
• All’interno di una espressione, però, è determinante la regola
del pre- e del post– Quindi if ( i++ > 0 )… è diverso da if ( ++i > 0 )…
• Usare sempre la forma prefissa, a meno che non sia necessario
preservare il valore precedente all'incremento
32
33. Lo stato di cin
• cin è un oggetto di tipo istream
• Rappresenta una sequenza di caratteri letta dal
programma
• Internamente l'oggetto mantiene lo stato
dell'ultima operazione di lettura
• (cin>>voto) viene convertito in un valore di tipo
bool, secondo la seguente logica
– true se la lettura è andata a buon fine
– false se si è incontrato il carattere end-of-file
(ctrl-z) o si è letto un dato di tipo non conforme
alla variabile a destra dell'operatore >>
• Nell'esempio anche una lettera al posto di un numero
33
34. M.C.D. di due interi positivi
1.
2.
3.
4.
Acquisisci i valori di A e B
Calcola MIN, il minimo tra A e B
Parti con X=1 ed assumi che MCD sia 1
Fintantoché X < MIN
1. incrementa X di 1
2. se X divide sia A sia B, assumi che MCD sia X
5. Mostra come risultato MCD
34
35. Esempio: MCD v1
int main() {
int x = 1;
int mcd = 1;
int a, b, min;
cout << "Inserisci due numeri: ";
cin >> a >> b;
if (a < b)
// Trovo il più piccolo tra a e b
min = a;
else
min = b;
while (x < min) { // Verifico tutti i numeri tra 2 e min
++x;
// Prima incremento poi verifico
if ((a % x)==0 && (b % x)==0 )
mcd = x;
}
cout << "Il MCD tra " << a << " e " << b << " è: "<< mcd;
return 0;
}
35
36. Esempio: MCD v2
int main() { // Scansione numeri da 2 a min: ultimo trovato è MCD
int x = 1;
int mcd = 1;
int a, b, min;
cout << "Inserisci due numeri maggiori di zero: ";
cin >> a >> b;
if (a < b)
// Trovo il più piccolo tra a e b
min = a;
else
min = b;
while (x <= min) {
// Verifico tutti i numeri tra 1 e min
if ((a % x) == 0 && (b % x) == 0) // Prima verifico
mcd = x;
++x;
// Poi incremento
}
cout << "Il MCD tra " << a << " e " << b << " è: " << mcd;
return 0;
}
36
37. Esempio: MCD v3
int main() { // Si scandiscono i naturali diminuendo
// a partire dal minimo tra a e b.
// Il primo divisore comune trovato è il MCD
int mcd = 1;
int a, b, x;
cout << "Inserisci due numeri maggiori di zero: ";
cin >> a >> b;
if (a < b)
// Trovo il più piccolo tra a e b
x = a;
else
x = b;
// e lo metto in x
while (!((a%x) == 0 && (b%x) == 0)) { // Verifico numeri tra min e 1
--x;
// Poi decremento
}
// all'uscita vale (a%x) == 0 && (b%x) == 0)
mcd = x;
// Il primo che trovo è MCD
cout << "Il MCD tra " << a << " e " << b << " è: " << mcd;
return 0;
}
Si tratta della negazione della condizione precedente
37
38. Esempio: MCD v4
int main() { // Si scandiscono i naturali diminuendo
// a partire dal minimo tra a e b.
// Il primo divisore comune trovato è il MCD
int mcd = 1;
int a, b, x;
cout << "Inserisci due numeri maggiori di zero: ";
cin >> a >> b;
if (a < b)
// Trovo il più piccolo tra a e b
x = a;
else
x = b;
// e lo metto in x
while ((a%x) != 0 || (b%x) != 0) { // Verifico numeri tra min e 1
--x;
// Poi decremento
}
mcd = x;
// Il primo che trovo è MCD
cout << "Il MCD tra " << a << " e " << b << " è: " << mcd;
return 0;
}
Equivalente al precedente: per la legge di De
Morgan
38
39. Esempio: MCD v. Euclide
int main() {
int mcd;
int a, b;
cout << "VERSIONE ALGORITMO DI EUCLIDE" <<
" Inserisci due numeri maggiori di zero: " << endl;
cin >> a >> b;
while (a != b) {
Scegliere a o b come MCD è indifferente:
if (a > b)
al momento dell’uscita dal ciclo while,
a = a-b;
infatti, a e b sono certamente uguali.
else
b = b-a;
}
mcd = a;
// All'uscita dal ciclo a e b sono uguali
cout << "Il MCD è: " << mcd << endl;
return 0;
}
39
40. Analisi critica
Siamo sicuri che il ciclo termini sempre?
– È cruciale l'ipotesi che a e b siano strettamente
positivi
• Un programmatore scrupoloso effettuerebbe un
opportuno controllo sui dati in ingresso
– Sotto questa ipotesi, ad ogni passo o a o b
decresce, ma resta positivo
– Non esiste una sequenza di coppie (a, b) che
rispetti queste proprietà e che non sia finita
Riconosciamo nel corpo del ciclo una sezione che garantisce un
progressivo avvicinamento alla condizione di uscita (terminazione)
40
41. Cosa domandarsi mentre si scrive un ciclo
• Quali sono le variabili su cui il ciclo
agisce?
• Quali sono i valori prima di entrare nel
corpo del ciclo?
• Come agisce il corpo del ciclo sui valori
delle variabili?
• Ci si avvicina SEMPRE alla condizione di
uscita? Ci sono casi in cui ci si allontana o
si resta fermi?
• Quali sono i valori dopo la terminazione
del ciclo?
42. Stampa dei numeri pari minori di N
int main() {
// Stampa dei numeri pari minori di N
int n, pari = 0; // considera lo 0 pari
cout << "Dammi un intero positivo : " << endl;
cin >> n;
while ( pari != n ) {
pari += 2;
}
return 0;
}
errore!!!
42
43. Conteggio con ciclo while
• Il ciclo while si può usare anche nel
caso in cui il numero di iterazioni sia
predeterminato (ad esempio N)
int contatore = 1;
while (contatore <= N) {
• …;
++contatore;
}
int contatore = 0;
while (contatore < N) {
…;
++contatore;
}
44. Calcolo del fattoriale
Definito solo su interi non negativi
n * (n-1) * ... * 2 * 1 se n > 1
n! =
1
se n = 0, 1
indefinito
altrimenti
44
45. Calcolo del fattoriale
int main() {
int n, cont, fatt = 1;
cout << "Fattoriale con while: inserisci n: " << endl;
cin >> n;
if (n < 0) /* verifica dati d’ingresso */
cout << "Numero negativo, fattoriale indefinito" <<
endl;
else {
cont = n;
while (cont > 1) {
fatt *= cont;
Quante volte viene eseguito il ciclo?
--cont;
}
cout << "Fattoriale di " << n << " vale " << fatt <<
endl;
}
return 0;
}
45
46. Tutto si può fare in molti modi
• In teoria
– sequenze, if-else e while sono complete
– bastano per codificare qualsiasi algoritmo
eseguibile da un computer
• Teorema di Boehm e Jacopini
• In pratica
– per rendere più semplice la scrittura dei
programmi i linguaggi introducono altre
istruzioni di controllo
46
47. Il ciclo do-while
do {
istruz.1
...
istruz.N
} while ( cond );
ATTENZIONE
Istruz.1
...
Istruz.N
while ( cond ) {
istruz.1
...
istruz.N
}
48. La "trasformazione inversa"
while ( cond ) {
istruz.1
...
istruz.N
}
do {
if ( cond ) {
istruz.1
...
istruz.N
}
} while ( cond );
Con ciclo while si ripeteva il codice sul primo
elemento di una sequenza, con ciclo dowhile si ripete la condizione
50. Do-while per interazione ripetitiva
int main() {
char rsp; // used in the condition;
// can't be defined inside the do
do {
cout << "enter two values: " << endl;
int val1 = 0, val2 = 0;
cin >> val1 >> val2;
cout << endl << "The sum of " << val1
<< " and " << val2 << " = " << val1 + val2
<< "nn" << "More? Enter y or n: " << endl;
cin >> rsp;
} while (rsp != 'n');
cout << "Thank you for playing!!" << endl;
return 0;
}
50
51. I caratteri speciali
• n: carattere "a capo"
– A differenza di endl non produce lo
svuotamento del buffer
• Sono usati come un carattere singolo
51
52. Il ciclo for
for ( exp.Iniz; cond; exp.Incr ) {
ist.1;
...
ist.N;
}
52
exp.Iniz;
while ( cond ) {
ist.1;
...
ist.N;
exp.Incr;
}
53. cont = 0;
while (cont < N) {
…;
…;
cont++;
}
Ciclo a
contatore
for (cont = 0; cont < N; ++cont) {
…;
…;
}
53
54. Somma dei primi N numeri naturali
INIZIO
LEGGI N
istruzione di inizializzazione
S=0
istruzione di inizializzazione
I=1
istruzione di assegnamento
S=S+I
istruzione di assegnamento
I=I+1
istruzione di I/O
(scrittura)
sì
ciclo
no
I>N
istruzione di test
SCRIVI:LA
SOMMA E’ S
FINE
54
istruzione di I/O
(lettura)
55. Ciclo a condizione iniziale - while
#include <iostream>
/* Somma dei primi N naturali */
int main() {
int n;
cout << "Versione con ciclo a condizione iniziale"
condizione di
<< "nInserisci n: " << endl;
permanenza nel ciclo
cin >> n;
if (n >= 0) {
int somma = 0, i = 1; // dichiarazione vicino all'uso
while (i <= n) {
corpo
somma += i;
del ciclo
++i;
}
cout << "La somma vale: " << somma << endl;
}
return 0;
56. Ciclo a condizione finale - do
#include <iostream>
/* Somma dei primi N numeri naturali */
int main ( ) {
int n;
cout << "Versione con ciclo a condizione finale"
<< "nInserisci n: " << endl;
cin >> n;
if (n > 0) {
int somma = 0, i = 1;
do {
// ciclo a condizione finale
somma += i;
corpo
++i;
del ciclo
condizione di
} while (i <= n);
permanenza nel ciclo
cout << "La somma vale: " << somma << endl;
}
return 0;
}
57. Ciclo a conteggio - for
#include <iostream>
/* Somma dei primi N numeri naturali */
int main() {
int n, somma=0;
cout << "Versione con ciclo a conteggio"
intestazione
<< "nInserisci n: " << endl;
del ciclo
cin >> n;
if (n >= 0) {
somma = 0;
for (int i = 1; i <= n; ++i) { // ciclo a conteggio
somma += i;
}
corpo
cout << "La somma vale: " << somma << endl;
del ciclo
}
return 0;
}
57
58. Visibilità della variabile di controllo
for (int i = 1; i <= n; ++i) { blocco}
– Se la variabile di controllo (i) è dichiarata
all'interno del ciclo for si può usare solo nel
blocco del ciclo
int i;
for (i = 1; i <= n; ++i) { blocco}
– Se la variabile di controllo (i) è usata
all'interno del ciclo for ma dichiarata prima,
si può usare sia nel blocco del ciclo sia
fuori
58
59. Altra formulazione del fattoriale
#include <stdio.h>
/* Calcolo del fattoriale */
int main() {
int n, fatt = 1;
cout << "Fattoriale con for: inserisci n: " << endl;
cin >> n;
if (n < 0) /* verifica dati d’ingresso */
cout << "Numero negativo, fattoriale indefinito" << endl;
else {
intestazione
del ciclo
for (int cont = n; cont > 1; --cont)
corpo del
fatt *= cont;
ciclo
cout << "Fattoriale di " << n << " vale " << fatt <<
endl;
}
return 0;
}
60. Istruzione condizionale a scelta multipla:
switch
switch ( var ) {
case v1: ist.1; break;
case ...: ist.2; break;
case vi:
case vj: ist.ij; break;
case ...: ist.3; break;
case vN: ist.N;
break;
default: ist.U;
break;
}
•
Consente la scelta tra numerose
opzioni prefissate
–
–
•
•
•
L' espressioni tra parentesi (di tipo
integral) è confrontata con il valore
di ogni caso (case label)
I valori delle case label (v) devono
essere di tipo integral
Se il valore concorda si esegue
la prima istruzione successiva al
case
L'istruzione break interrompe lo
switch e l'esecuzione procede
dall'istruzione ad esso seguente
Se nessun valore concorda,
l'esecuzione procede dalla
prima istruzione che segue lo
switch
61. Conteggio delle vocali
int main() {
// initialize counters for each vowel
unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
char ch;
while (cin >> ch) {
// if ch is a vowel, increment the appropriate counter
switch (ch) {
case 'a':
++aCnt;
break;
case 'e':
++eCnt;
break;
case 'i':
++iCnt;
break;
case 'o':
++oCnt;
break;
case 'u':
++uCnt;
break;
}
}
// print results
cout << "Number of vowel a: t" << aCnt << 'n' << "Number of vowel e: t"
<< eCnt << 'n' << "Number of vowel i: t" << iCnt << 'n'
<< "Number of vowel o: t" << oCnt << 'n'
<< "Number of vowel u: t" << uCnt << endl;
return 0;
}
62. Switch e case label
•
I valori delle case label (v) devono essere di tipo integral
int ival =
switch(ch)
case 3.14:
case ival:
•
•
•
•
42;
{
// error: noninteger as case label
// error: nonconstant as case label
Normalmente dopo le istruzion di un caso o gruppo di casi si inserisce
break;
Omettere break è un errore comune, se non serve meglio aggiungere
un commento che spieghi perché
La label default, se presente, concorda con qualsiasi valore
dell'espressione di controllo
E' buona prassi mettere un caso default anche se non si devono
eseguire istruzioni, per segnalare che si è considerato il caso
–
In questo caso va messo un blocco vuoto {} o l'istruzione nulla ;
63. #include <iostream>
int main() {
char c;
int n_cifre = 0, n_separatori = 0, n_altri = 0;
do {
cout << "dammi un carattere; ! per terminare " << endl;
cin >> c;
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
++n_cifre;
break;
case '.':
case ';':
case ':':
case ',':
++n_separatori;
break;
default: // considera anche ! tra gli altri caratteri
++n_altri;
}
} while (c != '!');
cout << "cifre: " << n_cifre << " separatori: " << n_separatori
<< " altri: " << n_altri << endl;
return 0;
}
64. Switch e inizializzazione di variabili
•
Bypass illegale
case true:
int ival = 0;
int jval;
break;
case false:
jval = 3;
if (ival > 0)
•
// illegal bypass
// error: control bypasses explicitly initialization
// ok: jval not initialized
//
//
//
//
ok
ok: assign a value to jval
ko, file_name in scope
but not initialized
Uso di un blocco per limitare la visibilità della variabile all'esterno del
case
case true:
{
// ok: declaration statement within a statement block
int ival = 22;
// ...
}
64
65. Istruzioni break e continue
• break fa uscire da corpo di un ciclo o da
switch
• continue interrompe iterazione corrente
di un ciclo (do, while o for) e dà inizio
alla iterazione successiva
66. Esempio
/* ciclo con elaborazioni su una serie di valori (al più N),
assunti successivamente dalla variabile intera x
saltando i valori negativi e interrompendo
l'elaborazione al primo zero incontrato */
int main() {
// somma solo i numeri positivi immessi
int x, somma = 0, n = 10;
for (int i = 0; i < n; ++i) {
cout << "passo " << i << " immettere un intero: " << endl;
cin >> x;
if (x < 0)
// salta il valore
continue;
if (x == 0)
// termina il ciclo
break;
somma += x; // elabora se positivo
}
cout << "La somma dei numeri positivi vale:" << somma << endl;
return 0;
}
67. Istruzione goto
• Trasferimento esplicito e incondizionato del
flusso di esecuzione
• Quasi sempre da evitare! (spaghetti programs)
int main() {
// somma solo i numeri positivi immessi
i, x, somma = 0, n = 10;
for (int i = 0; i < n; ++i) {
cout << "passo " << i+1 << " immettere un intero: " << endl;
cin >> x;
if (x < 0)
continue;
if (x == 0)
goto finito;
somma += x;
}
finito: cout << "La somma dei positivi vale:" << somma << endl;
return 0;
}
68. Consigli
• Fare in modo che il flusso di controllo sia poco
intricato (evitare goto)
• Usare cicli for quando il numero di iterazioni è noto
a priori
• Usare cicli a condizione finale quando si è certi di
dover iterare almeno una volta, quelli a condizione
iniziale quando può succedere di non dover estrare
nel ciclo
• Attenzione a non dimenticare i break in uno switch
• Mettere il caso di default in uno switch anche se non
si deve fare nulla
• Usare MOLTO parsimoniosamente break e
continue nei cicli
68
69. Un altro esempio di
costruzione incrementale dei programmi
(approccio top down)
• Si leggono sequenze di gruppi di numeri
naturali; i gruppi sono separati dal valore 0
• L’ultimo gruppo è terminato dal valore -1
• Si stampi in output una sequenza di
naturali corrispondenti alle somme dei
valori contenuti nei singoli gruppi
70. Passo 1
Inizio
Che cosa serve
• Una variabile per il
numero letto
• Una variabile per la
somma di gruppo
Comincia a leggere input
no
C'è un gruppo?
si
Calcola somma gruppo
Stampa somma gruppo
Fine
71. Passo 2
Inizio
int i; cin >> i;
no
while (i != -1)
si
Calcola somma gruppo
Stampa somma gruppo
Fine
71
72. Passo 3
Inizio
int i, sum; cin >> i;
no
while (i != -1)
si
sum=0;
accumula somma
cout << sum;
72
Fine
73. Passo 4
Inizio
int i, sum; cin >> i;
while (i != -1)
no
si
sum=0;
no
gruppo
prosegue?
si
sum = sum + 1; cin >> i;
// Fine gruppo
cout << sum; cin>>i;
Fine
73
74. Passo 5
Inizio
int i, sum; cin >> i;
while (i != -1)
no
si
sum=0;
no
i!=-1 && i!
=0
si
sum = sum + 1; if (i!=-1) cin >> i;
cout << sum; cin >> i;
Fine
74
75. Codice C++
int main() {
int num, sum = 0;
cout << "Inserire un numero, -1 termina, 0 termina gruppo: " << endl;
cin >> num;
while (num != -1) { // finché ci sono gruppi
sum = 0;
while (num != -1 && num != 0) { // finché ci sono numeri nel gruppo
sum += num;
cout << "inserire un numero, -1 termina, 0 termina gruppo: "
<< endl;
cin >> num;
}
cout << "Somma: " << sum << endl; // stampa somma gruppo appena terminato
if (num != -1) {
cout << "Inserire un numero, -1 termina, 0 termina gruppo: "
<< endl;
cin >> num;
}
}
cout << "Grazie e alla prossima!!" << endl;
return 0;
}
75
76. Che cosa abbiamo fatto
• Il programma è ottenuto per passi successivi
di raffinamento
• È scritto ad ogni passo in un misto di C e di
linguaggio naturale (pseudo-codice)
• Alla fine del processo di raffinamento risulta
scritto in C ed è eseguibile
• I passi scritti in linguaggio naturale e raffinati
al passo successivo possono diventare
commenti
76
77. Esercizio (filtro a memoria finita)
• L’utente immette una sequenza (di lunghezza libera) di
caratteri alfabetici terminata dal carattere ‘.’
• Il programma deve rifiutare e ignorare ogni carattere non
alfabetico diverso da ‘.’
– Va bene accettare solo caratteri alfabetici minuscoli
• Al termine dell’elaborazione il programma segnala
– la vocale inserita il maggior numero di volte [indicando anche
quante volte]
• In caso di “equinumerosità” tra più vocali, va bene una qualsiasi
– il numero totale di consonanti
• Aggiunte per renderlo più “difficile”:
– Considerare i caratteri case-insensitive (cioè d è uguale a D)
– Indicare tutte le vocali, in caso di “equinumerosità”
– Segnalare anche la lunghezza della massima sequenza di
caratteri consecutivi uguali, considerando che comunque i caratteri
non alfabetici interrompono il conteggio di tali sequenze
[a_bB@bbì^+pcDdg+pPPba°pabP*Pab. ⇒ 3]