Programmazione strutturata
Controllo del flusso 1 Flusso di esecuzione: ordine in cui le istruzioni di un programma sono eseguite Salvo contrordini, è in sequenza Il flusso sequenziale è specificato da un gruppo di istruzioni racchiuse tra { } detto blocco di istruzioni { } Istruzione1; Istruzione2; IstruzioneN;
Controllo del flusso 2 Flusso di esecuzione: ordine in cui le istruzioni di un programma sono eseguite sequenza Due possibili alterazioni: selezione: sceglie un azione da una lista di due o più azioni possibili ripetizione: continua ad eseguire un azione fino a quando non si verifica una condizione di termine
E' stato dimostrato che i programmi esprimibili tramite istruzioni di salto o diagrammi di flusso possono essere riscritti utilizzando le tre strutture di controllo (Teorema Boehm-Jacopini) Programmazione strutturata: I programmi usano soltanto sequenza, selezione, ripetizione
Selezione
Selezione: Permette di scegliere tra alternative da eseguire in base ad una condizione Una condizione è una espressione logica combinazione di operatori logici e relazionali Operatori relazionali: ==,!=, <,>,<=,>=
Operatori relazionali 1 se gli operatori sono uguali/ 0 se diversi <op1> = = <op2> 1 se gli operatori sono diversi/ 0 se uguali <op1>!= <op2> 1 se il 1 O è minore del 2 o operatore/ 0 altrimenti Precedenze: <,<=,>,>= hanno precedenza su = =,!=
Operatori logici Operano su valori logici: VERO 1 FALSO 0 Restituiscono un valore logico (0 o 1) Godono delle proprietà Commutativa Associativa Proposizione = sequenza di valori logici
Operatori logici di base La proposizione è vera se tutti gli operandi sono veri ( && ) La proposizione è vera se almeno uno gli operandi è vero ( ) La proposizione viene negata (! ) a XOR b: ((a &&!b) (!a && b))
Operatori logici e precedenze Operatore Valutazione Precedenza 1, se esp è falsa/0, se vera massima (!espr) Gli operatori logici 1, se binari espr1 hanno e espr2 precedenza sono vere/ inferiore intermedia a tutti gli altri operatori 0, altrimenti binari
Esempi x e y sono maggiori di z x è uguale a 1.0 o a 3.0 x ha un valore all'interno dell'intervallo determinato da z e y, estremi inclusi x ha valori all'esterno dell'intervallo determinato da z e y x>z && y>z x==1.0 x==3.0 z<=x && x<=y!(x>z && x<y) x<z x>y
Esempi Confronto tra caratteri: ch>='a' && ch<='z'
Valutazione a cortocircuito La valutazione di una espressione logica termina non appena il suo valore è determinato es. condizione: num%div==0 /*può causare un run time error*/ div!=0 && (num%div==0)/*corretto*/
Assegnamento logico Il risultato di un'espressione logica può essere assegnato ad una variabile di tipo int (per creare una variabile booleana ) int pari, dispari; pari=(n%2==0); dispari=(n%2!=0);
Istruzione if Selezione semplice: esegue un azione se e solo se una certa condizione è verificata Sintassi: if (Espressione_Booleana) Blocco_1 //esegui solo se vera Prossima_Istruzione; //sempre eseguita Espressione_Booleana true Blocco_1 false Prossima_Istruzione
Istruzioni di selezione - L istruzione if La forma generale di if quando riferita a blocchi di istruzioni è la seguente: if(espressione) Blocco_1 //esegui solo se vera else Blocco_2 //esegui solo se falsa Prossima_Istruzione; //sempre eseguita
Diagramma di flusso Espressione_Booleana true Blocco_1 false Blocco_2 Prossima_Istruzione
Programma #include <stdio.h> main(){ int a,b; /* numeri interi */ int c; /*variabile di appoggio*/ printf( \ninserisci due interi a e b ); scanf( %d%d,&a,&b); c=a-b; if(c>0) /* controllo */ { printf("il max e' a e vale %d\n",a); } else { printf("il max e' b e vale %d\n",b); } }
Esempi (selezione semplice): Dati in ingresso due numeri A e B, dividi A per B (se B diverso da zero) Conversione gradi Fahrenheit in Celsius e viceversa
Programma div.c #include <stdio.h> main(){ int a,b; /* variabili dividendo e divisore */ printf( Inserisci il dividendo ); scanf( %d,&a); printf( Inserisci il divisore ); scanf( %d,&b); if(b) /* controlla se b e zero */ { printf("%d\n",a/b); } else { printf("impossibile dividere per 0\n") } }
Istruzioni if annidate Esempio in pseudo-c if(i) { if(j) istruzione1; if(k) istruzione2; /* questo if e associato*/ else /* a questo else */ istruzione3; } else istruzione 4; /* questo if e associato a if(i) */
Selezione complessa (scelte mutuamente esclusive) Espressione_Booleana_1 true Blocco_1 Espressione_Booleana_2 true Blocco_2 Espressione_Booleana_n true Blocco_n
If-else-if (scelte esclusive) Un costrutto di programmazione a cui si ricorre frequentemente e che si basa sugli if annidati è il seguente if-else-if. if(condizione) istruzione; else if(condizione) istruzione; else if(condizione) istruzione;.. else istruzione; Le espressioni condizionali vengono valutate dall alto verso il basso. Alla prima condizione vera, viene eseguita l istruzione ad essa associata ed il resto della scala if-elseif viene aggirato. Se nessuna delle condizioni è vera allora viene eseguita l istruzione else finale (se è presente).
Istruzione (malsana) switch Istruzione switch: switch (Espressione_Di_Controllo) { case Etichetta_1: Sequenza_Istruzioni_1 case Etichetta_2: Sequenza_Istruzioni_2... case Etichetta_n: Sequenza_Istruzioni_n default: Sequenza_Istruzioni_Default }
Operatore condizionale È un operatore ternario: espr1? espr2 : epr3; if (espr1) else espr2; espr3; Ad esempio: z = (x>y)? x : y; /*assegna a z il max tra x e y */
L operatore, Assegna il valore di b a x, poi incrementa a e poi incrementa b: x = (a++, b++);
Istruzioni di Iterazione Ripetere un passo dell'algoritmo più volte Fanno parte di questa classe di istruzioni i cicli: for while do-while
Il ciclo for Inizializzazione Espressione_Booleana true Blocco false Continuazione Prossima_Istruzione
Il ciclo for (1) Viene utilizzato per ripetere un istruzione un numero specificato di volte. for(inizializzazione;espressione;incremento) istruzione; Per ripetere un blocco di istruzioni la forma generale è: for(inizializzazione;espressione;incremento) { istruzione_1;.. istruzione_n; }
Il ciclo for (2) L inizializzazione: di solito un istruzione di assegnamento che imposta il valore iniziale della variabile di controllo del ciclo, che ha la funzione di contatore. Per espressione si intende un espressione condizionale che determina se il ciclo continuerà (se vera) oppure no (se falsa). L incremento definisce la quantità di cui la variabile di controllo cambierà ogni volta che il ciclo viene iterato. devono essere separate da ; (punto e virgola).
Il ciclo for Esempio: calcolare la somma dei primi N numeri naturali S=0 I=1 I>N si S=S+1 I=I+1 no Scrivi S
Il ciclo for int i,n,s=0; printf("inserisci un intero n:\n"); scanf("%d",&n); for(i=1;i<=n;i++){ } s+=i; printf("la somma dei primi %d numeri e' %d",n,s);
Il ciclo while (1) La sintassi è: while(espressione) istruzione; oppure, while(espressione) { istruzione_1;.. istruzione_n; } L espressione definisce la condizione che controlla il ciclo Viene valutata prima di eseguire il blocco di istruzioni
Istruzione while Espressione_Booleana true Blocco false Prossima_Istruzione
Il ciclo while (2) È essenzialmente equivalente ad un ciclo for senza inizializzazione e l incremento: for ( ; condizione ; ) è equivalente a while (condizione)
Il ciclo while (3) /* programma che stampa i caratteri ASCII corrispondenti a lettere maiuscole (65-90)*/ #include <stdio.h> main() { unsigned char ch='a'; /* inizializzo la variabile al carattere codice ASCII */ while(ch<='z') { printf("[ %c ]\n",ch); /* stampa il singolo carattere ch */ ch++; /* incrementa il valore del carattere */ } }
Il ciclo do-while (1) A differenza dei cicli for e while, nei quali le condizioni sono verificate in testa al ciclo, il ciclo do-while verifica la condizione in fondo al ciclo. Cio significa che un ciclo do-while verrà sempre eseguito almeno una volta. do { istruzioni; } while(espressione); Il ciclo viene eseguito fino a che la condizione in espressione è vera. (se è falsa esce)
Istruzione do-while Blocco true Espressione_Booleana false Prossima_Istruzione
Spesso usato per il controllo dell'input da tastiera Esempio: controllo scelta di conversione da gradi Fahrenheit a Celsius (option 1) o viceversa (option 2)
I tre construtti (for, while, do-while) sono equivalenti si distinguono tra di loro in base al controllo anticipato o posticipato della condizione di controllo o alla conoscenza a priori del numero di iterazioni Scelta idonea per una particolare implementazione
Il ciclo for (3) /* programma che stampa i caratteri ASCII dal 33 al 127 */ #include <stdio.h> main() { unsigned char i; /* definisco la variabile i di iterazione del ciclo */ for(i=33;i<128;i++) /* ciclo for con indice i*/ { printf("[ %c ]\n",i);/* stampa un carattere racchiuso tra parentesi quadre, ad ogni ciclo */ } }
Il ciclo while (3) /* programma che stampa i caratteri ASCII dal 33 al 127 */ #include <stdio.h> main() { unsigned char ch=33; /* inizializzo la variabile al carattere codice ASCII 33*/ */ while(ch<128) { /* ciclo while controllato dall espressione ch<128 printf("[ %c ]\n",ch); /* stampa il singolo carattere ch */ ch++; /* incrementa il valore del carattere */ } }
Il ciclo do-while (2) /* stampa I caratteri ascii dal 33 al 128 */ #include <stdio.h> main() { unsigned char ch=33; /* il ciclo do-while viene sempre eseguito almeno una volta. Se ch=128 il ciclo verrebbe eseguito sempre e comunque una volta soltanto perche la condizione ch<128 viene controllata a fine ciclo */ do{ printf("[ %c ]\n",ch); ch++; }while(ch<128); }
Istruzione di salto break (1) Questa istruzione consente di uscire forzatamente da un ciclo aggirando la verifica condizionale. Quando in un ciclo si incontra l istruzione break, esso termina immediatamente ed il controllo del programma riprende dall istruzione successiva al ciclo
Istruzione di salto continue (1) Serve per ottenere forzatamente l iterazione anticipata di un ciclo aggirando la sua normale struttura di controllo. L uso di continue all interno di un ciclo provoca forzatamente il salto alla successiva iterazione del ciclo stesso saltando il codice che si trova tra il continue e l espressione condizionale che controlla il ciclo.
Istruzione di salto continue (2) /* stampa I numeri pari da 0 a 20 */ #include <stdio.h> main() { unsigned int i; } for(i=0;i<=20;i++) /* iteriamo da 0 a 20 compresi */ { if(i%2) continue; /* se il numero e dispari salta alla successiva iterazione del ciclo */ printf(" %d \n",i); /* stampa i numeri */ }
while( ) { continue; break; }
Cicli infiniti Cause principali: errata espressione Booleana errata (o assente) alterazione delle variabili coinvolte nell espressione Booleana Esempio: int total = 0; int count = 1; while (count!= 10) { total = total + count; count += 2; }
Esempi ed esercizi Calcolo del fattoriale Metodo di bisezione Ricerca di numeri primi Riconoscimento di un pattern
Tracciato (o traccia di esecuzione) È una simulazione su carta dell'algoritmo passo-passo per un valore in input delle variabili Usata per verficare se un algoritmo è corretto
Metodo di bisezione Determinare numericamente le soluzioni di una funzione f f(x)=0, x 1,x 2,...,x n (a i,b i ) intervallo in cui si trova x i, i=1,...,n Condizione: f(a i ) f(b i )<0 a i x i b i
Calcola il punto medio c i =(a i +b i )/2 Calcola il prodotto p=f(a i )f(b i ) Se p<0, l'estremo dx è c i Se p>0, l'estremo sx è c i Se p=0, la soluzione è c i
Quante volte ripetere? Condizione di arresto: a i -b i <ε Realizzazione con f(x)=cos(x) in (0,π) (vedi file: cap04_bisezione.c)
Numeri primi PB: Determinare tutti i numeri primi compresi tra 2 e N Sottoproblema: determinare se un numero i è primo i è primo se non è divisibile per alcun j<i Condizione: i%j Se i%j!=0, i è primo con j Se i%j==0, i non è primo
Quante volte ripetere? Per ogni j<i Miglioramento: per ogni j<jmax (quanto vale jmax?) In realtà: appena trovo j che divide i, esco dal ciclo (vedi file: primo_for.c e primo_while.c)
Problema iniziale: Quante volte ripetere? Al più N volte (vedi file: cap04_primi.c) Discussione: complessità?
Riconoscimento di un pattern PB: cerca una sequenza particolare in un testo (es. p= ciao in ora vado a casa, ciao! ) carattere per carattere Automa a stati finiti: Se sei in s0 e leggi 'c', vai nello stato s1; Se sei in s1 e leggi 'i', vai nello stato s2; Se sei in s2 e leggi 'a', vai nello stato s3; Se sei in s3 e leggi 'o', vai nello stato s4;
Le condizioni sono mutuamente esclusive Attenzione: se nello stato si leggi un carattere diverso da pi, torna nello stato s0 Quante volte ripetere? Finchè non raggiungi lo stato s4 (vedi file: riconoscimento_pattern.c)