Rappresentazione delle informazioni
Rappresentazione delle informazioni
• L’informatica si occupa di rappresentare ed elaborare informazioni
:
•numeri
•caratteri
• audio
• immagini
• video
Rappresentazione dei caratteri
I caratteri
• I
caratteriappartenenti ad un alfabeto vengono
codificati(cioè “rappresentati”) mediante
sequenze di bit: una diversasequenza per ciascun diverso carattere.
• Uno dei codici più noti e usati è il codice ASCII (American Standard Code for Information Interchange):
• usa una sequenza di 7 bit per ciascun carattere: ci sono 128 (=27) sequenze diverse, utilizzate anche per lettere, segni di punteggiatura, cifre decimali, ecc.
(par. 6.9)
I caratteri
• Dato che l’unità elementare di informazione nei calcolatori è il byte (= 8 bit), si è passati ad usare, quasi sempre, il codice ASCII esteso, che usa una sequenza di 8 bit per ciascun carattere degli alfabeti occidentali
:• ci sono 256 (=28) sequenze diverse, utilizzate anche per vocali accentate e altre lettere speciali (es. ß tedesca, ç francese)
• le sequenze con la prima cifra uguale a zero coincidono con il codice ASCII
I caratteri
• I primi 32caratteri del codice ASCII (con codice da 0 a 31) sono caratteri di controllo:
• 9 tabulatore ’\t’
• 10 nuova riga ’\n’
• 13 invio ’\r’
• I caratteri da32 a127sono caratteri stampabili:
• 32 spazio ’ ’
• da 48 a 57 caratteri numerici, le cifre decimali ’0’, ’1’…
• da 65 a 90, da 97 a 122 caratteri alfabetici (maiuscoli e minuscoli)
• da 33 a 47, da 58 a 64, da 91 a 96, da 123 a 127 caratteri di interpunzione.
I caratteri (codice Unicode)
• Per rappresentare i segni grafici utilizzati da tutti gli alfabeti del mondo servono molti più simboli diversi.
• Codifica Unicode
http://www.unicode.org
• usa una sequenza di 16 bit per ciascun segno grafico:
• ci sono 65536 (= 216) sequenze diverse
• le sequenze con le prime otto cifre uguali a zero coincidono con il codice ASCII esteso.
I caratteri (codice Unicode)
Variabili e Tipi base
Variabili e Tipi base
• Nei corsi di matematica quando scriviamo x ∈ ∈ ∈ ∈
e diciamo “ x è una variabile reale” intendiamo dire che x è un nome che indica un elemento generico dell’insieme dei numeri reali.
• Nei corsi di informatica con “x è una variabile reale” intendiamo dire che x è
un nomeche indica una posizione di memoria che conterrà un elemento generico di R (con R ⊂ ⊂ ⊂ ⊂ ).
Variabili e Tipi base
• insieme dei numeri reali (infinito e continuo).
• R insieme dei numeri reali rappresentabili nel calcolatore (finito e discreto).
• La posizione di memoria è caratterizzata dal tipo, che è l’insieme da cui la variabile può estrarre i suoi valori
3 reale èdiversoda 3 intero
Variabili e Tipi base
• Ogni variabile possiede:
• un nome: è una stringa di caratteri che è bene ricordi il significato della variabile,
• un tipo: è l’insieme da cui la variabile può estrarre i valori,
• regole d’uso: rappresentano l’insieme delle operazioni che si possono fare sulla variabile,
• struttura: alla variabile può essere associato un solo valore oppure gruppi di valori dello stesso tipo o di tipo diverso,
• ambito d’uso: è l’ambito di visibilità, indica in quale punto del programma è nota e quindi usabile.
Variabili e Tipi base
•
Tipi base o primitivi o standard nel C++• numeri interi short, int, long
• numeri reali float, double
• caratteri char
Non fanno parte dello standard ma sono implementati
• logici bool
• Definizione di una variabile
• Sintassi
nometipo nomevariabile;
Variabili e Tipi base
• Esempi.
int n, numeroanni;
short dimensione;
double area, saldo;
bool errore;
char lettera;
•
Nonsi possono ridefinire le variabili.
Variabili e Tipi base
• Le operazioni che possiamo fare su una variabile sono:
•
accesso: individuare la posizione di memoria ed estrarre il valore (lettura)
•
assegnamento: individuare la posizione di memoria e introdurre il valore (scrittura)
Variabili e Tipi base
• Nelle istruzioni di un programma, abbiamo:
•
accesso: quando la variabile compare in unaistruzione e se ne utilizza il valore
•
assegnamento: quando il valore le viene attribuito:• dall’esterno: lettura del valore in una acquisizione di dati
• in una istruzione di assegnazione
Assegnazione
Assegnazione
• Sintassi:
nomevariabile = espressione;
• Esempi.
n = 3+5;
area = 25.67;
saldo = 20000;
lettera = 'x';
lettera = x ; //Errore
Assegnazione
• Quando una variabile viene definita le viene associata un’area di memoria del tipo attribuito con la definizione:
int a;
double b;
a b
• Interi e reali vengono rappresentati in binario in modo diverso.
Assegnazione
• Quando si esegue l’assegnazione, il valore viene inserito nell’area corrispondente
a=3;
b=3;
a b
• Le due aree di memoria sono di tipo diverso e la sequenza di bit (per il numero 3) contenuta è diversa, anche con uguale numero di bit (long e float).
3 3
Assegnazione
• Il simbolo per l’istruzione di assegnazione è
=
(C++, Java, Fortran)• NON lo si deve confondere con un simbolo di uguaglianza o di confronto.
• Il suo significato è:
• il valore dell’espressione a destra del simbolo = viene inserito nella locazione corrispondente alla variabile che sta a sinistra.
• Nel Pascal, il simbolo è := proprio per distinguerlo dal simbolo di uguaglianza
Assegnazione
• Si può eseguire una assegnazione anche in fase di definizione:
int k = 25;
• Osserviamo queste assegnazioni e vediamo un diverso significato per a:
a = 5; //assegnamento su a //a è a sinistra k = a; //accesso per a
//a è a destra
Assegnazione
• Osserviamo queste assegnazioni:
a = 5; //assegnamento
a = a + 1; /*sia accesso che assegnamento*/
• Quanto vale a?
a = a + 1;
• In alcuni linguaggi di pseudocodifica, il simbolo per l’assegnazione è
← ← ← ←
5 6
Assegnazione
• Nei primi linguaggi le variabili avevano per il tipo una definizione di default. In C++ una variabile può essere usata solo se è stata precedentemente definita, ossia se è stata dichiarata con il suo tipo.
• Esempio.
int c = 7;
c1 = c;
//Errore: c1 non è definita Il compilatore segnala:error : C1 undeclared
Assegnazione
• Nell’assegnazione si deve rispettare il tipo di dato.
• Esempio.
char m;
double y = 23.75;
m = y;
//NO: m è un carattere Il compilatore segnala:warning: converting to char from double
• Il compilatore C++ non è molto preciso. L’errore si verifica in esecuzione.
Leggere dati in ingresso
Leggere dati in ingresso
• Per dare un valore iniziale ai dati possiamo utilizzare l’istruzione di assegnazione: in tale modo, però, avremo sempre la stessa elaborazione ad ogni esecuzione.
• Se vogliamo eseguire il programma su altri dati, è necessario modificare il codice sorgente e quindi le inizializzazioni delle variabili e compilarlo di nuovo, prima di eseguirlo
.Leggere dati in ingresso
• Per poter scrivere programmi generali, l’utente deve poter inserire dei propri dati: i programmi devono perciò ricevere dati in ingresso, acquisire valori dall’esterno.
• Lo scambio di informazioni tra l’utente e il programma e viceversa è rappresentato da un flusso di dati.
• Quando l’ingresso è rappresentato dalla tastiera si dice che il programma viene eseguito in maniera interattiva: durante l’esecuzione il programma si ferma in “attesa” di ricevere i dati (input).
Leggere dati in ingresso
• Il flusso di dati standard per l’uscita è un file di nome
cout; il flusso di dati standard perl’ingresso è un file di nome cin.
• Ciò che viene inserito da tastiera viene codificato in binario e successivamente ricostruito prima come gruppo di caratteri (stringa) e poi interpretato come valore di una variabile di un certo tipo.
Leggere dati in ingresso
• Esempio.
3 3 intero
7.5 7.5 reale
ciao
0100110…01ciao stringa
true true booleano
Leggere dati in ingresso
• Esempio.
int a; double b;
cin>>a>>b;
• Per acquisire il valore per due variabili si può concatenare l’operatore d’ingresso >> oppure si possono eseguire due istruzioni di lettura:
cin>>a;
cin>>b;
• In entrambi i casi i dati devono essere immessi rispettando l’ordine (un numero intero e un numero reale) ma possono essere scritti sulla stessa riga, separati da spazio oppure su righe diverse.
Progettare
Algoritmi
Progettare Algoritmi
• La progettazione di un algoritmo è una fase che richiede intelligenza e fantasia:
l’informatica è un’arte.
• Per imparare a progettare un algoritmo ci può aiutare la scomposizione del problema in problemi più semplici e la scrittura dell’algoritmo in un linguaggio intermedio (pseudocodifica) nel quale evidenziare i costrutti importanti senza vincoli di sintassi.
Progettare Algoritmi
• Scomporre un problema P in sottoproblemi significa individuare problemi più semplici P1, P2, P3 che risolti nell’ordine costituiscono la soluzione.
• Ciascuno dei sottoproblemi può a sua volta essere scomposto nuovamente.
P1 P2 P3
P
Progettare Algoritmi
• Fino a quando si prosegue con queste successive scomposizioni?
• Si prosegue fino al livello di operazioni elementari (operazioni aritmetiche, confronti, ecc.) o fino ad incontrare problemi già risolti in precedenza da noi (es. algoritmi di somma, ricerca, ordinamenti,…) o da altri (funzioni matematiche sin(x), gestione di array,…).
Progettare Algoritmi
• Nel linguaggi ad alto livello (Pascal, C, Java,..) ci sono degli enunciati che organizzano le istruzioni con precisi significati: strutture di controllo.
• Sono essenzialmente tre: sequenza, scelta (decisioni), ciclo (iterazioni).
• Teorema di Bohm-Jacopini 1966: ogni
algoritmo può essere scritto utilizzando
unicamente queste tre strutture.
Strutture di controllo
Strutture di controllo
• Una struttura di controllo è un blocco di istruzioni caratterizzato da un unico punto di ingresso e un unico punto di uscita e che si può schematizzare nel modo seguente:
(par. 1.5.2)
S S
Strutture di controllo
• In tale modo l’algoritmo si può schematizzare:
prima 2)
successiva 3)
ultima 4)
S
1S
iS
i+1S
nSequenza
• Si chiama sequenza una funzione che ha per dominio un sottoinsieme finito dei e il cui codominio acquisisce l’ordine posizionale degli elementi di .
• Indichiamo con Nk = {1, 2, 3, .., k}
s : Nk→ A
• Il codominio di s = {s(1), s(2), … s(k)}, ma solitamente si scrive:
s1, s2, s3, …. sk
• si+1è il successivo di si, come posizione e non come valore.
Sequenza
• La struttura di controllo sequenza rappresenta un gruppo di istruzioni eseguite secondo l’ordine posizionale (che nei linguaggi è l’ordine di scrittura delle istruzioni):
<istruzione 1>
<istruzione 2>
.………
<istruzione k>
• Cosa può essere <istruzione i> ?
Sequenza
• La generica istruzione può essere:
• assegnazione
• struttura di controllo
• operazione lettura/scrittura
• invocazione di una funzione (sottoprogramma)
Esercizio
• Problema: Si consideri un trapezio T i cui angoli alla base maggiore sono rispettivamente 30° e 45°. Sono note le misure dei lati AB = 60 cm.(base maggiore) e AD = 20 cm. (il lato obliquo che forma 30° con la base). Calcolare il perimetro e l’area del trapezio.
D C
A K H B
Esercizio
• Analisi del problema.
• Vediamo di generalizzare alcuni dati:
possiamo voler risolvere il problema per dei valori generici di AB e AD (purché AB >AD).
• Non possiamo invece considerare un valore
qualunque per gli angoli alla base, perché
forniscono importanti relazioni per individuare
le misure degli altri lati.
Esercizio
• Il problema propone già una scomposizione:
• I scomposizione:
• P si suddivide in
• P1 : calcolare il perimetro
p = AB+AD+DC+CB
• P2: calcolare l’area
area = (AB+DC)*CH /2 Basi di conoscenza: sappiamo le formule
Esercizio
• Il problema P1 non è subito risolubile, ma necessita di una ulteriore scomposizione:
• II scomposizione per P1:
• Ci mancano le misure dei lati DC e CB, quindi la scomposizione sarà
• P1.1 calcolare DC
• P1.2 calcolare CB
• P1.3 calcolare il perimetro p = AB+AD+DC+CB
Esercizio
• Come facciamo a calcolare DC?
• Il problema P1.1 deve essere ulteriormente scomposto:
DC = AB – AK –HB ed è noto solo AB
• P1.1.1 AK = AD * √ 3 /2
• P1.1.2 HB = CH = DK = AD/2
• P1.1.3 DC = AB-AK-HB
Esercizio
• P1.2 calcolare CB:
CB = HB * √2 (HB calcolato)
• P1.3 calcolare il perimetro.
• Sequenza dei sottoproblemi che risolve P1:
(P1.1.1 P1.1.2 P1.1.3) P1.2 P1.3
Esercizio
• Vediamo ora la seconda scomposizione per P2:
• Poiché P2 è il secondo sottoproblema:
• DC è noto
• CH = HB è noto
(noti perché calcolati nella soluzione per P1)
• Area = (AB+DC)*HB/2
Esercizio
• La scomposizione finale è una sequenza:
P1.1.1 AK
P1.1.2 HB = CH
P1.1.3 DC
P1.2 CB
P1.3 perimetro
P2 area
Esercizio per casa
• Esercizio: scrivere in C++ le istruzioni di questo algoritmo (sono tutte assegnazioni, ma bisogna rispettare l’ordine).
• Il valore degli angoli è servito per costruire le relazioni e non è un dato da inserire; calcolare a parte la radice di 2 e di 3.
• Esercizio. Calcolare la misura della diagonale del rombo equivalente agli 8/5 del trapezio essendo note le misure dell’altra diagonale
.Predicati
Predicati
• Un predicato è una funzione a valori nell’insieme B B B B
P: A → B B B B
x ∈ A P(x) può essere vero o falso
• x deve avere un valore, altrimenti il predicato non è valido.
Esempio. A = P(x) : x > 5
P(7) è vero P(3) è falso
Struttura condizionale
Struttura condizionale
• Struttura condizionale o decisione o scelta.
• Sia P un predicato (condizione); P viene valutato e sarà o vero o falso. Si vuole eseguire <istruzione1>
nel caso in cui P sia vero e <istruzione2> nel caso in cui P sia falso.
• Come possiamo esprimere in un costrutto questa scelta?
se P
allora istruzione1 //P vero altrimenti istruzione2 //P falso //fine scelta
Struttura condizionale
• Può anche accadere che non dobbiamo fare nulla nel caso in cui P sia falso; allora possiamo schematizzare questa scelta in modo seguente:
se P
allora istruzione //fine scelta
• L’ingresso alla struttura è la valutazione del predicato P, l’uscita è la fine della scelta (istruzione successiva o fine algoritmo).
Struttura condizionale
• Esempio.
• Dati due numeri reali a e b, determinare il più grande dei due.
• Analisi.
• Tra le operazioni elementari sui numeri non c’è il calcolo del massimo, quindi dobbiamo utilizzare una struttura condizionale: il predicato sarà rappresentato dal confronto tra i due numeri; il confronto è una operazione elementare.
Struttura condizionale
• Progetto.
Algoritmo massimotradue
variabili a, b, max di tipo reale acquisire i dati per a e b e stamparli se a>b
allora max ←←←← a altrimenti max ←←←← b //fine scelta
stampare il valore di max //fine algoritmo
Struttura condizionale
• La struttura if. Sia P un predicato o una espressione; il vero del predicato corrisponde a “diverso da zero”, il falso del predicato corrisponde a “0”(par.13.7.1).
• La sintassi è:
if(P)
istruzione;
if(P){//blocco di istruzioni
………
istruzione;
………
}
se P
allora istruzione //fine scelta
Struttura condizionale
• L’unica istruzione, o il blocco di istruzioni individuato dalla coppia di parentesi graffe, viene eseguita solo nel caso in cui il predicato P risulti vero.
• Esempio.
int a, b;
//assegnare valori ad a e b if(a>b)
cout<<""""a maggiore di b"""" <<endl;
Struttura condizionale
• Sintassi con le due alternative; sia P la condizione:
if (P) istruzione;
else
istruzione;
if(p){//blocco istruzione;
}
else{//blocco istruzione;
}
se P
allora istruzione altrimenti istruzione //fine scelta
Struttura condizionale
• Attenzione al ;
• Dopo la parentesi graffa (prima di else) non ci deve essere il simbolo ;
• Se si mette il ; l’istruzione if termina e il compilatore segnala che c’è una else senza if
if(x>0){
cout<< """" x = """" << x <<endl;
cout<<"""" x positivo \n"""";
};
else ...
il compilatore segnala:
error: parse error before else
Struttura condizionale
• Traduciamo l’algoritmo massimotradue int main () {
double a,b, max;
cin>>a>>b; //acquisire e stampare a e b cout<<"a = "<<a<<" b = "<<b<<endl;
if (a>b)
max = a; //P vero else
max = b; // P falso
cout<< """" il massimo vale: max = """" <<
max<<endl;
return 0;
}//fine main
Struttura condizionale
• Possiamo voler eseguire due istruzioni, quindi usare un blocco:
if (a>b) {
max = a; //P vero cout<<""""a > b"""" <<endl;
}
else {// P falso max = b;
cout<<""""a <= b"""" <<endl;
}//fine if
cout<<" " " " max = """" << max<<endl;
Struttura condizionale
• L’istruzione
cout<<" " max = """" << max<<endl;" "
• viene eseguita con qualunque valore di P (vero, falso) e rappresenta il punto di prosecuzione dell’esecuzione dell’algoritmo.
• Ma se abbiamo più scelte come possiamo scriverle? In sequenza o annidate?
Struttura condizionale
• Scelte multiple. Siano P e Q due predicati:
if (P)
istruzione; //if in sequenza if(Q)
istruzione;
. . .
if(P) //if annidate
istruzione;
else if(Q) // if(Q) si valuta istruzione; //quando P è falso
Struttura condizionale
• Nella sequenza il predicato Q viene valutato in ogni caso: P vero e P falso; nel caso di if annidate, il predicato Q viene valutato solo se P è falso.
• Quale delle due strutture scegliere dipende da ciò che si vuole realizzare nell’algoritmo.
L’ordine con cui si effettuano le scelte può essere fondamentale per l’algoritmo: un ordine diverso può dare un algoritmo errato.
Struttura condizionale
• Esempio. Supponiamo di voler stampare una stringa che esprima la ricchezza o meno di una persona in base al suo saldo bancario
.povero medio ricco straricco
0 1000 50000 200000
• Dopo aver acquisito il valore del saldo (double) eseguiremo i vari confronti con i valori che individuano gli intervalli di minore o maggiore ricchezza stabilendo un valore da stampare (un carattere che esprime la ricchezza: p, m, r, s).
Struttura condizionale
char s; double saldo;
if(saldo >= 200000) s='s';
else if(saldo >= 50000) s='r';
else if(saldo >= 1000) s='m';
else if(saldo >=0) s='p';
else s='N'; //valore non valido cout<<"s = "<<s<<endl;
Struttura condizionale
• Casi di prova.
• Per essere sicuri che la struttura funzioni bene dobbiamo provare tutte le alternative, provando diversi valori per saldo:
-2 900 1000 1200 51000 200000 250000
• In corrispondenza a questi valori ci aspettiamo un valore per s: non valido, povero, medio, medio, ricco, straricco, straricco.
• Se nel predicato si mette > invece di >=
il secondo e il quarto valore di s cambiano.
Struttura condizionale
• Proviamo ad invertire l’ordine delle scelte:
if(saldo >= 1000) s='m';
else if(saldo >= 0) s='p';
else if(saldo >= 50000) s='r';
else if(saldo >= 200000) s='s';
else s='N';
• Per saldo = 1200 si ha s= “m” e le altre scelte non vengono eseguite; ma cosa accade per saldo = 51000?
Struttura condizionale
• Se mettiamo le if in sequenza otteniamo:
if(saldo >= 200000) s='s';
if(saldo >= 50000) s='r';
if(saldo >= 1000) s='m';
if(saldo >=0) s='p';
//else s='N';
cout<<"s = "<<s<<endl;
• Viene, però, sempre stampato l’ultimo valore perché le assegnazioni sono in sequenza .
Struttura condizionale
• Esercizio. Scriviamo delle istruzioni che autorizzano il prelievo da un conto corrente solo se l’ammontare del prelievo è inferiore al saldo:
double saldo = 10000; //saldo iniziale double prelievo = 200;
if (prelievo <= saldo ) saldo = saldo - prelievo;
cout<<""""restano """" << saldo << """" euro \n"""";
Struttura condizionale
• E se il prelievo è superiore? Il programma deve dare una risposta anche nel caso in cui il prelievo sia superiore al saldo e …. impedirlo:
il saldo non può essere negativo.
if (prelievo <= saldo ) saldo = saldo - prelievo;
if (prelievo > saldo)
cout<<"impossibile: conto scoperto\n";
• In questo algoritmo c’è un errore logico.
Struttura condizionale
• Se il prelievo viene eseguito ma supera la metà del saldo la seconda if viene eseguita e stamperà
“impossibile”, perché il saldo è stato modificato.
Pertanto eseguiamo le istruzioni in alternativa:
if (prelievo <= saldo ) saldo = saldo - prelievo;
else
cout<<"impossibile: conto scoperto\n";
Struttura condizionale
• If annidate e il problema dell’else sospeso .
• Siano P e Q due predicati; non essendoci un costrutto “endif” si pone il seguente problema:
if(P)
if(Q)
istruzione1;
else istruzione2;
• La else a quale delle due if si riferisce?
Struttura condizionale
• Esempio .
int a,b,c;
a=9; b=7; c=4;
if (a>b) //vero
if(b<c) //falso
b=b+1;
else b=b-1;
cout<<"""" b = """" << b<<endl;
• Quale valore viene stampato per b? 6 o 7?
• La else si riferisce alla prima if o alla seconda?
Struttura condizionale
• La regola del linguaggio è la seguente:
• La else si riferisce alla if più vicina (interna) quindi b=6.
• Si può alterare la regola inserendo della parentesi graffe:
int a,b,c; a=9; b=7; c=4;
if (a>b){ //vero if(b<c) //falso
b=b+1;}
else b=b-1; //si riferisce alla prima cout<<"""" b = """" << b<<endl; //b=7
Un po’ di stile
• Quando scriviamo una struttura è bene utilizzare una modalità di scrittura che faciliti la lettura dell’algoritmo, rientrando di alcuni spazi a sinistra le istruzioni che si riferiscono al vero e al falso, ed incolonnando le else sotto la parola if.
• Però questo stile non risolve l’attribuzione della else in caso di più strutture condizionali, che si ottiene con l’inserimento (o meno) della coppia di parentesi graffe.
Struttura iterativa
Struttura iterativa
• Consideriamo un predicato P e valutiamo se è vero: nel caso vero vogliamo eseguire ripetutamente un gruppo di istruzioni; questo gruppo di istruzioni, però, non dovrà più essere eseguito nel caso in cui P sia falso. Possiamo rappresentare questo ciclo scrivendo che:
fintantoché P eseguire
<istruzioni> //P vero //fine ciclo
// ora P è falso
Struttura iterativa
• Individuiamo così una struttura con un unico punto di ingresso (la valutazione di P) ed un unico punto di uscita (ciò che segue dopo la fine della struttura).
• Esempio.
• Stampare i primi cinque numeri naturali in ordine decrescente.
• Analisi. Dobbiamo:
1. individuare il predicato P
2. individuare le istruzioni da ripetere.
Struttura iterativa
• Quali sono i numeri da stampare?
• 1, 2, 3, 4, 5 ma nell’ordine inverso:
5, 4, 3, 2, 1
• Possiamo pensare di partire dal più grande (5) e ad ogni iterazione calare di una unità, quindi l’iterazione sarà:
stampa numero esegui numero-1
• Quando ci fermiamo? Lo 0 non è compreso, quindi fintantoché numero è maggiore di zero, ripetiamo le istruzioni.
Struttura iterativa
• Progetto.
algoritmo stamparovescia variabili a intero a ←←←← 5
finché a > 0 eseguire stampa a
a ←←← a-1← //fine struttura
• Questa struttura termina?
Struttura iterativa
• Scriviamo i valori che la variabile a assume durante il funzionamento dell’algoritmo:
valore predicato stampa a > 0
a = 5 V 5
a = 4 V 4
a = 3 V 3
a = 2 V 2
a = 1 V 1
a = 0 F il ciclo termina
Struttura iterativa
• Osserviamo che il ciclo è stato eseguito 5 volte e che il predicato è stato valutato 6 volte:
5 vero + 1 falso
• Qual è il comportamento di un ciclo?
• Un ciclo:
• può non essere mai eseguito
• può essere eseguito una o più volte
• deve terminare.
Struttura iterativa
• Cosa cambia se iniziamo con a = -5 ?
• Il predicato a > 0 è falso e quindi il ciclo non viene mai eseguito. Se quello che volevamo era la stampa dei numeri, questo è un errore logico: il compilatore non segnalerà errore ma il programma non eseguirà le operazioni richieste.
• Cosa cambia se scriviamo a ← a+1?
• I valori da a saranno: 5, 6, 7, … il predicato sarà sempre vero e il ciclo non termina. Questo è un errore logico grave.
• Nell’iterazione ci deve sempre essere una istruzione che modifica il predicato e che può renderlo falso.
Struttura iterativa
• Il ciclo while
(par. 13.7.3).
• Sia P un predicato (espressione), la sintassi è:
while (P)
istruzione;
while (P){//blocco . . . istruzione;
. . . . }//fine while
finché P eseguire iterazione //fine ciclo
Struttura iterativa
• Esempio. Scrivere un algoritmo per stampare i numeri dispari compresi tra 1 e 10.
//inizio algoritmo int i = 1;
while(i <= 10) { cout<<i<<endl;
i = i+2;
}
Verifica: i assume i valori 1, 3, 5, 7, 9, con predicato vero; quando i = 11 il predicato è falso e il ciclo termina.
Struttura iterativa
• Il ciclo precedente è del tipo:
indice = inizio;
while(indice <= fine){
//iterazione;
indice = indice + passo;
}
• Questo ciclo è governato da un’unica variabile (indice) che descrive un intervallo di valori e che è incrementata di una quantità fissa (passo).
Struttura iterativa
• Il ciclo for
(par. 13.7.4) .• La sintassi è:
for (inizializzazione; controllo; modifica) iterazione;
• Oppure:
for (inizializzazione; controllo; modifica){
//blocco di istruzioni }
Struttura iterativa
• Nel caso precedente il ciclo
whilesi trasforma in:
for (indice = inizio; indice <= fine;
indice = indice + passo) iterazione;
• Oppure se ci sono più istruzioni da eseguire:
{//blocco di istruzioni }
Struttura iterativa
• Nella sezione di inizializzazione si può anche inserire la definizione della variabile, che risulta “visibile” solo all’interno della struttura.
int n = 10;
for (int i = 1; i <= n; i = i+2) cout<<i<<endl;
• L’indicazione dell’incremento della variabile i appartiene all’intestazione della struttura e non deve più essere scritta all’interno della iterazione.
Struttura iterativa
• In entrambe queste strutture (while e for) la condizione viene verificata all’inizio: entrambi questi cicli possono non essere mai eseguiti.
• Nel ciclo for l’incremento della variabile i che governa il ciclo viene fatto alla fine della iterazione:
• i=1, verifica condizione (i <= n): è vera, iterazione, incremento di i che diventa 3; verifica condizione: è vera, iterazione, … , incremento di i che diventa 11; verifica condizione: è falsa; il ciclo termina.
Errori di programmazione
Errori di programmazione
• Quando scriviamo un programma possiamo introdurre degli errori.
• Gli errori che possiamo fare sono di due tipi:
• Errori che il compilatore evidenzia, errori di sintassi.
• Errori che si verificano quando il programma
esegue le istruzioni, errori logici ed errori in
esecuzione (il programma viene interrotto).
Errori compilazione
• Abbiamo visto alcuni errori che il compilatore segnala.
• Il compilatore segnala:
• il nome della funzione in cui si verifica l’errore
• il numero della riga in cui tale errore si verifica
• il tipo di errore rilevato.
• Questi errori sono (abbastanza) facili da correggere perché c’è un “suggerimento” da parte del compilatore.
Errori logici
• Consideriamo il seguente codice
#include <iostream>
using namespace std;
int main () {// stampa un saluto cout<<"viao a tutti "<<endl;
return 0;
}
• Questo errore non viene segnalato dal compilatore, che non può sapere che cosa il programmatore abbia intenzione di voler scrivere:
• la compilazione va a buon fine ma il risultato è errato perché viene prodotto un output diverso dal previsto.
Errori logici
• Sono molto più insidiosi degli errori di sintassi:
• il programma viene compilato correttamente, ma non fa quello che dovrebbe fare.
• L’eliminazione degli errori logici richiede molta attenzione:
• si esegue il programma su vari casi e si osservano con attenzione i risultati prodotti; i casi di prova devono essere “certi” ossia si deve conoscere il risultato.