Parte 4 - PowerPoint PPT Presentation

About This Presentation
Title:

Parte 4

Description:

Title: PowerPoint Presentation Last modified by: stefano berardi Created Date: 1/1/1601 12:00:00 AM Document presentation format: Presentazione su schermo (4:3) – PowerPoint PPT presentation

Number of Views:41
Avg rating:3.0/5.0
Slides: 49
Provided by: unito151
Category:

less

Transcript and Presenter's Notes

Title: Parte 4


1
Informatica A.A. 2009/2010
  • Parte 4
  • Dai diagrammi di flusso alla programmazione
    strutturata
  • le istruzioni if, for, while,

Corso A Prof. Stefano Berardi
http//www.di.unito.it/stefano Corso B Prof.
Ugo de Liguoro http//www.di.unito.it/deligu

2
Corrado Bohm
Milano, 1923. Professore emerito di Teoria e
applicazione delle macchine calcolatrici presso
lUniversità di Roma La Sapienza
3
Indice Parte 4 Diagrammi
  • Il flusso dellesecuzione e i diagrammi di
    flusso.
  • Il salto condizionale listruzione IF.
  • Iterazione le istruzioni WHILE e FOR.
  • La programmazione strutturata e il teorema di
    Bohm-Jacopini.
  • I diagrammi di flusso venivano usati per
    descrivere i programmi nellepoca in cui si
    programmava in Assembly. Oggi sono ancora adatti
    per spiegare programmi molto brevi.

4
1. Il flusso dellesecuzione
  • Lesecuzione dei programmi C, assembly, e in
    generale dei programmi detti imperativi,
    consiste in una successione di trasformazioni
    dello stato (delle memorie della RAM e del
    program counter, lindirizzo della prossima
    istruzione da eseguire)
  • Ogni trasformazione di stato è leffetto
    dellesecuzione di unistruzione. Per es., una
    assegnazione x3 oppure unistruzione JB L1 che
    fa saltare lesecuzione a unistruzione lontana
    di indirizzo L1 se una certa condizione è vera.
  • Il flusso è lordine in cui le istruzioni di un
    programma vengono eseguite.

5
Diagrammi di flusso
  • I diagrammi di flusso sono una rappresentazione
    in forma di grafo del flusso dellesecuzione di
    un programma. Erano un progresso rispetto al
    linguaggio assembly, perché spostavano
    lattenzione dalle istruzioni del programma alla
    loro relazione reciproca.

6
Esempio di diagramma di flusso area di un
rettangolo
Ogni freccia rappresenta la scelta della
prossima istruzione da eseguire.
7
Il programma C corrispondente
int main() double base, altezza, area cout ltlt
"base " cin gtgt base cout ltlt "altezza "
cin gtgt altezza area basealtezza cout ltlt
"area " ltlt area ltlt endl system(pause)
8
Sequenza di diagrammi e Blocchi di istruzioni in
C
C1 C2 Ck
Sequenza di diagrammi
Blocco di istruzioni
Più in generale, rappresentiamo una sequenza di
diagrammi in C scrivendo le istruzioni che li
rappresentano di seguito, quindi racchiudendole
tra graffe, per formare una singola istruzione
detta istruzione composta o blocco.
9
Il flusso dellesecuzione in C
  • Per gestire le variabili il C segue da vicino
    la nozione di indirizzo di macchina di von
    Neumann.
  • Invece per la gestione dei salti da una
    istruzione allaltra il C segue unidea
    completamente diversa, quella della
    programmazione strutturata.
  • Noi spiegheremo la programmazione strutturata
    attraverso i diagrammi di flusso.
  • I diagrammi di flusso spiegano come un programma
    funziona, ma hanno lincoveniente di essere
    leggibili solo per programmi brevissimi.

10
Programmazione strutturata
  • La programmazione strutturata individua i
    diagrammi di flusso piu utili tra quelli con una
    sola entrata ed una sola uscita. Per ciascuno di
    essi viene introdotto una istruzione blocchi,
    IF, WHILE, FOR, del C/C. I programmi in C
    sono costruiti con le istruzioni if, while, for
    cosi introdotte.
  • Oggi usiamo i diagrammi di flusso per introdurre
    le istruzioni IF, WHILE, FOR, e in pochi altri
    casi.
  • Vediamo ora i diagrammi di flusso più importanti
    insieme alla loro traduzione in C.

11
2. Il diagramma di selezione (IF)
Listruzione IF rappresenta in C e in quasi
tutti i linguaggi il seguente diagramma di
selezione a due vie LIF fa saltare
lesecuzione allindirizzo di C se lespressione
B vale vero, e allindirizzo dellistruzione D se
B vale falso.
if (B) C else D
12
Listruzione IF in C
LIF viene tradotto nei compilatori nel
linguaggio Assembly con un salto condizionato,
che fa eseguire come prossima istruzione C oppure
D a seconda se B è vero oppure falso. Noi
utilizzeremo lIF solo come istruzione primitiva,
con la seguente sintassi Al posto di
istruzione1 e istruzione2 possiamo scrivere una
qualunque istruzione o blocco di istruzioni del
C, compresi altri IF in questo caso si parla
di IF annidati. Il C consente un secondo tipo
di IF, lIF tronco.
if (ltespr.booleanagt) ltistruzione1gt else
ltistruzione2gt
13
IF tronco (senza ELSE)
if (B) C
if (ltespr. booleanagt) ltistruzionegt
LIF tronco rappresenta la selezione a due vie
con una sola azione C. Se lespressione booleana
B è falsa saltiamo allistruzione successiva
senza far nulla Vediamo ora alcuni esempi di uso
di IF, IF tronco e IF annidato
14
Primo esempio di IF equazione di 1 grado axb
Discussione se a 0 eq. indeterminata o
impossibile, altrimenti x b/a.
15
Il programma per lequazione di 1 grado
int main() double a, b cout ltlt "a "
cin gtgt a cout ltlt "b " cin gtgt b if
(a ! 0) cout ltlt "x " ltlt b/a ltlt endl else
cout ltlt Indet. o impossibile" ltlt endl
system(pause)
16
Secondo esempio di IF equazione di 2 grado, IF
annidati
Sia
  • ? gt 0 due soluzioni reali
  • ? 0 una soluzione reale
  • ? lt 0 non ci sono soluzioni reali.
  • Per scrivere questo programma dovremo utilizzare
    IF scritti dentro altri IF (IFannidati), per
    distinguere il secondo caso dal terzo.

17
Esempio di IF diagramma equazione di 2 grado
leggi a, b, c
inizio
Deltabb4ac
Questa viene detta una decisione annidata
true
false
Deltagt0
Delta0
rad?Delta
false
true
Stampa ( b ? rad)/(2a)
Stampab/(2a)
Stampa no sol. reali
fine
18
Soluzione eq. di 2 grado in C
  • main() double a, b, c cin gtgt a cin gtgt b cin
    gtgt c
  • double Delta bb - 4ac
  • if (Delta gt 0)double rad sqrt(Delta)
  • cout ltlt "prima sol. reale "
  • ltlt (-b rad)/2a ltlt endl
  • cout ltlt "seconda sol. reale "ltlt (-b -
    rad)/2altltendl
  • else if (Delta 0)
  • cout ltlt "Unica sol. reale " ltlt -b/(2a) ltlt
    endl
  • else cout ltlt "Nessuna soluzione reale" ltlt endl
  • system("pause")

sqrt radice quadrata (funzione della libreria
cmath)
Questo è un if annidato
Questo else si riferisce al secondo if Ma come
facciamo a stabilirlo?
19
Quando ci sono IF annidati come accoppiamo un
if con un else?
Per definizione, la clausola else si riferisce
allultimo if non accoppiato con un else
precedente
if (B) if (B) C else C else D
Il secondo else viene accoppiato con il primo
IF. In questo caso, listruzione D verrà eseguita
se B è falso listruzione C verrà eseguita se B
è vero, ma B è falso.
20
If annidati un altro esempio ambiguita
Dato che la clausola else si riferisce allultimo
if non accoppiato con un else precedente, se
manca un solo else (se un IF è tronco) tutto
cambia
if (B) if (B) C else D
Questa volta else viene accoppiato con il
secondo IF. Dunque listruzione D verrà eseguita
se B è vero e B è falso, non se B è falso.
21
If annidati come eliminare le ambiguita
Avvolgendo ogni sottoistruzione in parentesi
graffa ogni ambiguitá scompare
Queste parentesi sono necessarie se vogliamo
accoppiare il primo IF con lelse
if (B) if (B) C else D
Listruzione D verrà eseguita se B è falso. Le
parentesi non sono sempre necessarie come in
questo caso, peró sono sempre utili per
aggiungere chiarezza.
Esempio es. 3.14 Hubbard indovina il numero
22
Come rappresentare una scelta tra n1 blocchi
È sufficiente annidare n comandi IF, ciascuno
dopo lelse dellIF precedente. Il risultato è
unistruzione composta che esegue il primo blocco
se la prima espressione booleana è vera, il
secondo blocco se la prima è falsa e la seconda è
vera, eccetera, lultimo blocco se tutte le
espressioni booleane sono false.
if (B1) ltblocco_1gt //se B1 vera else if (B2)
ltblocco_2gt //se B1 falsa e B2 vera else if (B3)
ltblocco_3gt //se B1,B2 false e B3
vera else ltblocco_(n1)gt//se B1,,Bn
false
23
Un IF con più di due scelte listruzione
SWITCH(sconsigliata)
  • Un tempo per rappresentare la scelta tra più di
    due alternative veniva usata una istruzione
    chiamata SWITCH.
  • Per completezza nel prossimo lucido spieghiamo
    il funzionamento dello SWITCH. Tuttavia ne
    sconsigliamo luso, sia per ragioni semplicità
    di scrittura, sia perché è facile sbagliarsi a
    usarlo.
  • Al posto dello SWITCH, usate un IF annidato come
    spiegato nel lucido precedente.

24
Esecuzione dello SWITCH
switch (ltespressionegt) case ltcostante_1gt
ltistruzioni_1gt break ... case ltcostante_kgt
ltistruzioni_kgt break default ltistruzionigt
Esecuzione dello SWITCH. Confrontiamo il valore
dellespressione con le costanti. Trovata la
prima che coincide col valore eseguiamo le
istruzioni relative. Arrivati al break usciamo
dal blocco (le parentesi ). Quando non
troviamo una costante uguale al valore, eseguiamo
le istruzioni che seguono il default.
25
3. Literazione il ciclo while
  • Literazione è lesecuzione ripetuta di una o più
    istruzioni (dette corpo delliterazione). Un
    diagramma iterativo viene detto un ciclo.
  • Un ciclo è controllata dal valore di verità di un
    certo test. Viene tradotto dal compilatore in
    linguaggio Assembly mediante un salto
    condizionato JB (ovvero mediante una assegnazione
    del program counter) che va allindietro, verso
    una istruzione già eseguita in precedenza.
  • Come primo e fondamentale esempio di ciclo
    vediamo il ciclo while.

26
Il diagramma di flusso del ciclo while
Un ciclo while rappresenta il seguente diagramma
di flusso
while (B) C
Il corpo puo essere un qualunque blocco di
istruzioni C. Finché B è vero, il while esegue
il corpo C e poi di nuovo B. La prima volta che B
è falso il while termina dunque se B è sempre
vero il while non termina mai. La sintassi del
while è while (ltespr. booleanagt) ltcorpogt
27
Un programma che richiede il while la somma dei
reciproci
  • Problema dato un intero n calcolare e stampare
  • Soluzione utilizziamo il seguente algoritmo.
    Partiamo con s0, i1. Finché iltn, eseguiamo
    ss1.0/i, ii1. In questo modo, s prende i
    valori 1, 11/2, 11/21/3, , mentre i prende i
    valori 1, 2, 3, . Quando igtn, terminiamo e
    stampiamo s, che a questo punto vale (11/21/3
    1/n).
  • Vediamo ora come tradurre tutto con un while.

28
Somma dei reciproci calcolata con un while
int main() int n cout ltlt "n " cin
gtgt n double s 0.0 int i 1
while (i lt n) s s 1.0/i i
cout ltlt "La somma dei primi " ltlt n ltlt "
reciproci " ltlt s ltlt endl
system("pause")
Scrivendo invece s s 1/i la divisione 1/i è
intera, dunque viente arrotondata per es. 1/2
diventa 0
i è detto incremento. Cosa succede se lo
eliminiamo ???
29
Il ruolo di i nella somma dei reciproci
Lincremento i modifica il valore di verità del
test,lazione svolta dal corpo, ed è cruciale per
il buon funzionamento del ciclo. Se lo eliminiamo
e lasciamo while (i lt n) s s
1.0/i allora, mentre ripetiamo il corpo s s
1.0/i del ciclo while, il valore di i non
cambia. Resta il valore iniziale i1. Dunque
continuiamo a eseguire ss1.0/i con i1 quindi
continuiamo a eseguire s s 1 ne segue che s
assume i valori 0,1,2,3,4, , anziche 1,11/2,
come dovrebbe. Inoltre il test (i lt n) resta
uguale a (1 lt n) e quindi vale sempre true, il
ciclo continua per sempre.
30
Un altro esempio di iterazione il ciclo for
for (ltinizializzazionegt lttestgt ltstepgt)
ltcorpogt
  • Le inizializzazioni sono definizioni di
    variabili o assegnazioni di valori a variabili
    precedentemente dichiarate se più duna, sono
    separate da virgole (e non da punti e virgole
    come al solito)
  • Lo step o incremento di solito è lincremento di
    una o più variabili se più duna, sono separate
    da virgole. Lincremento serve a modificare il
    valore di verità del test e, a volte, lazione
    svolta dal corpo.
  • Nota. A differenza di quanto avviene per il for
    nel Pascal, il test è unespressione booleana
    arbitraria.

31
Il diagramma di flusso per il ciclo for
Linizializza-zione I viene eseguita una sola
volta prima di entrare nel ciclo
for (I B S) C
I
false
B
true
Al termine di S avviene sempre un salto
allindietro, verso listruzione che prima
calcola B, poi a seconda del valore di B sceglie
se ripetere il corpo del for o saltare alla prima
istruzione dopo il for
C
Lo step S viene eseguito al termine di ogni
esecuzione del corpo C
S
32
La relazione tra while e for
  • A differenza di quanto succede in altri
    linguaggi, in C il ciclo while ed il ciclo for
    sono interdefinibili, usando le seguenti
    equazioni
  • for(IBS) C I while(B)CS
  • while(B) C for(B) C
  • Ne segue che la differenza tra i due cicli è solo
    di stile di solito il for è più chiaro, perché
    mette in evidenza la parte di inizializzazione e
    incremento.
  • Come capita per il while, il for non termina mai
    se il test B resta sempre vero.
  • Vediamo ora come usare il for per ripetere n
    volte la stessa azione.

33
Il for consente di ripetere n volte una certa
azione
Inizialmente i vale 0
for(i0,n100iltni) cout ltlt CIAO
i 0 n 100
true
false
Al termine di ogni iterazione i viene
incrementato di 1
iltn
Scrivi CIAO
Quando i vale 100 il ciclo termina
i
Il ciclo viene eseguito 100 volte, mentre i
cresce da 0 a 99. Ogni volta stampiamo un CIAO.
34
Un diagramma per il calcolo della media
aritmetica m (a0 an-1)/ n
inizio
i lt n
false
leggi n
true
stampa m s/n
a i-esimo addendo ai
i 0
leggi a
s 0
fine
s s a
A partire da questo diagramma di flusso si puó
scrivere un programma in C usando un ciclo FOR
i i 1
35
Il diagramma di flusso per la media (definito da
un for)
Eseguito una sola volta prima di entrare nel ciclo
for (I B S) C
i 0 s 0
true
false
iltn
Leggi a s s a
Eseguito al termine di ogni iterazione
i
36
Un programma C per la media aritmetica
i è detto incremento. Se lo eliminiamo cosa
succede ???
int main()int n int i, a, s cout ltlt "Media di
n valori. n" cin gtgt n for (i 0, s 0 i lt
n i) cout ltlt "inserisci un valore"
cin gtgt a s s a cout ltlt "Media " ltlt
(double) s / (double) n ltlt endl
system("pause")
Casting necessario per avere la divisione senza
troncamento
37
Il ruolo di i nella media aritmetica
Lincremento i serve a modificare il valore di
verità del test, ed è cruciale per il buon
funzionamento del ciclo. Se lo eliminiamo e
lasciamo for (i 0, s 0 i lt n ) cout ltlt
"inserisci un valore" cin gtgt a s s
a allora mentre il corpo del ciclo for viene
ripetuto il valore di i non cambia, resta il
valore iniziale i0. Dunque il test (i lt n)
resta uguale (0 lt n) e quindi vale true. Il ciclo
for continua per sempre. In generale, se
dimentico di inserire gli incrementi il ciclo
(for o while) non termina.
38
Un ciclo meno usato listruzione dowhile
La differenza con il while è che il corpo del do
while viene eseguito almeno una volta
do ltcomandogt while (ltespr. booleanagt)
do C while (B)
Vi chiediamo di saper riconoscere questa
istruzione, ma vi consigliamo di usare solo while
e for. Il Pascal ha una istruzione simile do
until, che esce però quando il test è vero.
39
Esempio stampa dei fattoriali inferiori a un
certo limite
int main() long limite cout ltlt "Inserire una
limitazione superiore " cin gtgt limite cout ltlt
"Elenco fattoriali minori di " ltlt limite ltlt
endl long f 1, i 0 / f10!i! Faremo sì
che la condizione fi! resti vera durante tutta
lesecuzione del ciclo (continua nel prossimo
lucido) /
40
Esempio stampa dei fattoriali inferiori a un
certo limite
/ (continua dal lucido precedente) / do cout
ltlt i ltlt"! " ltlt f ltlt endl //stampo i! f f
f (i1) //ora f vale f(i1)i!(i1)(i1)!
i /aggiorno i ad (i1), di modo che per
la nuova i (uguale alla vecchia i1) valga la
condizione fi!./ while (f lt
limite) system("pause")
i è detto incremento. Provate a eliminarlo e
vedrete che, anche in questo caso, il ciclo
continua per sempre
41
4. Programmazione strutturata
  • Unistruzione di jump (salto) è ad esempio
  • JB ltetichettagt
  • dove letichetta indica il punto del programma
    a cui saltare. JB è unistruzione tipica del
    linguaggio Assembly, come abbiamo visto parlando
    della macchina di Von Neumann. In C
    listruzione JB esiste e si scrive goto.
  • La programmazione strutturata, tuttavia,
    proibisce luso delle istruzioni di salto anche
    se disponibili, e si basa soltanto su sequenza
    (blocchi), selezione (IF) ed iterazione (WHILE,
    FOR, ecc.) per controllare il flusso del
    programma.

42
Programmazione strutturata
  • Lesperienza mostra che si parte da un diagramma
    non strutturato (cioè non combinazione di
    diagrammi per if e while) è difficile
    trasformarlo in un programma strutturato
    equivalente.
  • Ma almeno in linea di principio, è sempre
    possibile trasformare un diagramma qualunque in
    uno equivalente, che pero corrisponda a un
    programma strutturato, cioè scritto con solo if e
    while? La risposta è
  • si per il Teorema di Böhm-Jacopini del 1966
  • In altre parole if e while sono in linea di
    principio sufficienti a scrivere qualunque
    programma.

43
Teorema di Böhm-Jacopini
Ogni funzione Turing calcolabile è definibile in
un linguaggio di programmazione con i comandi
di Blocco di istruzioni, IF e WHILE
44
Cenno di prova partiamo da un diagramma
qualunque
e ad ogni nodo del grafo associamo un numero

-
B1
C1
C2


-
-
C3
B3
B2
C5
C4
45
Dopo aver numerato i nodi
usiamo una variabile contatore cp per sapere
in quale nodo ci troviamo e per decidere verso
quale nodo proseguire. A questo punto

-
B1
C1
C2


-
-
C3
B3
B2
C5
C4
46
traduciamo il nostro diagramma con un ciclo
while e tanti if
main()int cp 1//cpnodo del diagramma in cui
ci troviamo while (cp lt 10) if (cp 1) cp
2 else if (cp 2) if (B1) cp 3 else
cp 4 else if (cp 3) C1 cp 5
else if (cp 4) C2 cp 6 else if (cp
5) if (B2) cp 8 else cp 4 else if
(cp 6) if (B3) cp 9 else cp 7
else if (cp 7) C3 cp 2 else if (cp
8) C4 cp 3 else if (cp 9) C5 cp
10

-
B1
C1
C2


-
-
C3
B3
B2
C5
C4
47
Conclusioni
  • In base al Teorema di Böhm-Jacopini, per il
    controllo del flusso sono sufficienti i costrutti
    programmativi della programmazione strutturata
    (blocchi, if, while, senza listruzione goto).
  • Attenzione però la dimostrazione del teorema di
    Böhm-Jacopini non ci dà alcuna informazione su
    come trasformare un diagramma caotico in un
    programma strutturato leggibile.
  • Per questo motivo non useremo i diagrammi di
    flusso, ma scriveremo direttamente il codice in
    forma strutturata, con if, while, for, .

48
Istruzioni di cui sconsigliamo luso
  • Il C/C comprende, oltre al goto, altre
    istruzioni di salto che erano tipiche dei più
    antichi linguaggi Assembly. Noi però non ne
    faremo uso, perche i salti producono
    facilmente errori e programmi poco leggibili.
    Solo per completezza, elenchiamo qui le
    istruzioni di salto del C
  • goto
  • break
  • continue
  • exit.
  • Unaltra istruzione che sconsigliamo è lo SWITCH.

Vedi esempi 4.16 e 4.19 dellHubbard
Write a Comment
User Comments (0)
About PowerShow.com