05 3 istruzioni-selezione-iterazione-condizioni
-
Upload
piero-fraternali -
Category
Technology
-
view
387 -
download
0
description
Transcript of 05 3 istruzioni-selezione-iterazione-condizioni
Introduzione al C++
istruzioni: sequenza, selezione, iterazione, condizioni
1
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
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)
5
Sequenzaint main(){ int integer1, integer2, sum; // declaration
cout << "Enter first integer" << endl; // prompt cin >> integer1; // read an integer cout << "Enter second integer" << endl; // prompt cin>> integer2; // read an integer sum = integer1 + integer2; // assignment cout << "Sum is: " << sum; // print sum
return 0; // successful end}
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 foundwhile (cin >> s && s != sought); // null statement, placed on purpose
• Attenzione ai ; dispersi// disaster: extra semicolon: loop body is this null statementwhile (i < 10) ; // the while body is the empty statement++i; // increment is not part of the loop
6
NB: vale la regola del corto circuito
• 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;
}
Istruzioni condizionali (if-then-else)
ramothen
8
• Costrutto if-else:if ( espressione )
istruzione1else
istruzione2int 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;
}
ramothen
ramoelse
Istruzioni condizionali complesse
Formattazione
if (numero < 0) valass = -x; else valass = x;
•Per maggior leggibilità, è bene usare regole di incolonnamento (indentazione)
10
#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)
valass = -numero;
if (numero >= 0)
valass = numero;
cout << "Numero: " << numero << // output
"Valore assoluto: " << valass; // output
return 0;
}
ramothen
condizione
Istruzioni condizionali(selezione singola)
11
#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;
}
Istruzioni condizionali(con selezione doppia)
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
Output
13
> 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
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 (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;
if-then-else annidati
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
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
• Spesso accade di voler scrivere molti if annidati (alternative multiple):
if (...)fai qualcosa1;
elseif (…)
fai qualcosa2;else
if(…)
Sequenze di if
Esempio
if (n % 2 == 0)cout << n " è pari" << endl;
elseif (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;
/* Se un numero n ha divisori primi <15, stampa il minimo, altrimenti stampa un messaggio che lo segnala */
20
/* Se un numero n ha divisori primi <15, stampa il minimo, altrimenti stampa un messaggio che lo segnala */
Una rappresentazione più leggibile
Iterazione a condizione iniziale
• Ciclo whilewhile (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
int main(){ int n = 9;
cout << " PRONTI... " << endl; while ( n > 0 ) {
cout << " ...meno " << n << endl; n = n-1; } cout << " ...VIA!!! " << endl; return 0;
}
condizione
Corpo del ciclo: blocco di istruzioni
variabile di
governo
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?
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!
Schema tipico
26
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;}
Errore tipico
27
while (valore != sentinella) {cout << "fornisci valore da elaborare;se hai finito, fornisci …" << sentinella;
cin >> valore; elabora valore;}
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
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
– ELSEStampa a terminale “Non è stato immesso
alcun voto”
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;}
Versione con condizione nell'input
#include <iostream>
using namespace std;
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
Si usa ctrl-z come sentinella, che termina del tutto l'input, oppure un carattere non numerico
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
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
1. Acquisisci i valori di A e B2. Calcola MIN, il minimo tra A e B3. Parti con X=1 ed assumi che MCD sia 14. Fintantoché X < MIN
1. incrementa X di 12. se X divide sia A sia B, assumi che MCD sia X
5. Mostra come risultato MCD
M.C.D. di due interi positivi
35
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 verificoif ((a % x)==0 && (b % x)==0 )
mcd = x;}cout << "Il MCD tra " << a << " e " << b << " è: "<< mcd;
return 0;}
Esempio: MCD v1
36
int main() { // Scansione numeri da 2 a min: ultimo trovato è MCDint 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 verificomcd = x;
++x; // Poi incremento}cout << "Il MCD tra " << a << " e " << b << " è: " << mcd;
return 0;}
Esempio: MCD v2
37
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 xwhile (!((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 è MCDcout << "Il MCD tra " << a << " e " << b << " è: " << mcd;return 0;
}
Si tratta della negazione della condizione precedente
Esempio: MCD v3
38
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 xwhile ((a%x) != 0 || (b%x) != 0) { // Verifico numeri tra min e 1
--x; // Poi decremento}mcd = x; // Il primo che trovo è MCDcout << "Il MCD tra " << a << " e " << b << " è: " << mcd;return 0;
}
Esempio: MCD v4
Equivalente al precedente: per la legge di De Morgan
!( C && D ) !C || !D
39
Esempio: MCD v. Euclideint main() {
int mcd;
int a, b;
cout << "VERSIONE ALGORITMO DI EUCLIDE" <<
" Inserisci due numeri maggiori di zero: " << endl;
cin >> a >> b;
while (a != b) {
if (a > b)
a = a-b;
else
b = b-a;
}
mcd = a; // All'uscita dal ciclo a e b sono uguali
cout << "Il MCD è: " << mcd << endl;
return 0;
}
Scegliere a o b come MCD è indifferente: al momento dell’uscita dal ciclo while, infatti, a e b sono certamente uguali.
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)
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!!!
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
Definito solo su interi non negativi
n * (n-1) * ... * 2 * 1 se n > 1
n! = 1 se n = 0, 1
indefinito altrimenti
Calcolo del fattoriale
45
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;--cont;
}cout << "Fattoriale di " << n << " vale " << fatt <<
endl;}
return 0;}
Calcolo del fattoriale
Quante volte viene eseguito il ciclo?
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
ATTENZIONE
Il ciclo do-while
do {
istruz.1
...
istruz.N
} while ( cond );
Istruz.1
...
Istruz.N
while ( cond ) {
istruz.1
...
istruz.N
}
Con ciclo while si ripeteva il codice sul primo elemento di una sequenza, con ciclo do-while si ripete la condizione
La "trasformazione inversa"
while ( cond ) {
istruz.1
...
istruz.N
}
do {
if ( cond ) {
istruz.1
...
istruz.N
}
} while ( cond );
49
Sentinellacout << "prompt"; cin >> valore;
while (valore != sentinella) {elabora valore;
cout << "prompt"; cin >> valore;
}do {
cout << "prompt"; cin >> valore;
if (valore != sentinella) {
elabora valore;}
} while (valore != sentinella);
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 << "\n\n" << "More? Enter y or n: " << endl;
cin >> rsp;} while (rsp != 'n');
cout << "Thank you for playing!!" << endl; return 0;}
50
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;
}
exp.Iniz;
while ( cond ) {
ist.1;
...
ist.N;
exp.Incr;
}
53
cont = 0;while (cont < N)
{…;…;
cont++;}
for (cont = 0; cont < N; ++cont) {
…;…;
}
Ciclo a contatore
54
INIZIO
FINE
S = 0
LEGGI N
I > N
SCRIVI:LASOMMA E’ S
sìno
S = S + I
I = 1
I = I + 1
ciclo
istruzione di test
istruzione di inizializzazione
istruzione di inizializzazione
istruzione di assegnamento
istruzione di assegnamento
istruzione di I/O(lettura)
istruzione di I/O(scrittura)
Somma dei primi N numeri naturali
#include <iostream>
/* Somma dei primi N naturali */
int main() {
int n;
cout << "Versione con ciclo a condizione iniziale"
<< "\nInserisci n: " << endl;
cin >> n;
if (n >= 0) {
int somma = 0, i = 1; // dichiarazione vicino all'uso
while (i <= n) {
somma += i;
++i;
}
cout << "La somma vale: " << somma << endl;
}
return 0;
corpo del ciclo
condizione di permanenza nel ciclo
Ciclo a condizione iniziale - while
#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;++i;
} while (i <= n);
cout << "La somma vale: " << somma << endl;}return 0;
}
corpo del ciclo condizione di
permanenza nel ciclo
Ciclo a condizione finale - do
57
#include <iostream>/* Somma dei primi N numeri naturali */int main() {
int n, somma=0;cout << "Versione con ciclo a conteggio" << "\nInserisci n: " << endl;cin >> n;if (n >= 0) {
somma = 0;for (int i = 1; i <= n; ++i) { // ciclo a
conteggiosomma += i;
}cout << "La somma vale: " << somma << endl;
}return 0;
}
corpo del ciclo
intestazionedel ciclo
Ciclo a conteggio - for
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
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 {
for (int cont = n; cont > 1; --cont)
fatt *= cont;
cout << "Fattoriale di " << n << " vale " << fatt << endl;
}
return 0;
}
intestazionedel ciclo
corpo del ciclo
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
Conteggio delle vocaliint main() {
// initialize counters for each vowelunsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;char ch;while (cin >> ch) {
// if ch is a vowel, increment the appropriate counterswitch (ch) {case 'a':
++aCnt;break;
case 'e':++eCnt;break;
case 'i':++iCnt;break;
case 'o':++oCnt;break;
case 'u':++uCnt;break;
}}// print resultscout << "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;}
Switch e case label
• I valori delle case label (v) devono essere di tipo integral
int ival = 42;
switch(ch) {
case 3.14: // error: noninteger as case label
case ival: // 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 ;
#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;
}
Switch e inizializzazione di variabili
• Bypass illegale
case true: // illegal bypass
int ival = 0; // error: control bypasses explicitly initialization
int jval; // ok: jval not initialized
break;
case false: // ok
jval = 3; // ok: assign a value to jval
if (ival > 0) // 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
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
/* 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;}
Esempio
• Trasferimento esplicito e incondizionato del flusso di esecuzione
• Quasi sempre da evitare! (spaghetti programs)
int main() { // somma solo i numeri positivi immessii, 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;
}
Istruzione goto
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
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
Passo 1
Che cosa serve
• Una variabile per il numero letto
• Una variabile per la somma di gruppo
Inizio
Fine
C'è un gruppo?
Calcola somma gruppo
no
si
Comincia a leggere input
Stampa somma gruppo
Passo 2
71
Inizio
Fine
while (i != -1)
Calcola somma gruppo
no
si
int i; cin >> i;
Stampa somma gruppo
Passo 3
72
Inizio
Fine
while (i != -1)
sum=0;
no
si
int i, sum; cin >> i;
cout << sum;
accumula somma
Passo 4
73
Inizio
Fine
while (i != -1)
sum=0;
no
si
int i, sum; cin >> i;
cout << sum; cin>>i;
sum = sum + 1; cin >> i;
gruppo prosegue?
si
no
// Fine gruppo
Passo 5
74
Inizio
Fine
while (i != -1)
sum=0;
no
si
int i, sum; cin >> i;
cout << sum; cin >> i;
sum = sum + 1; if (i!=-1) cin >> i;
i!=-1 && i!=0
si
no
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
• 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]
Esercizio (filtro a memoria finita)