La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.

Presentazioni simili


Presentazione sul tema: "Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli."— Transcript della presentazione:

1 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli Corso di Laurea in Informatica Università degli Studi La Sapienza (lezioni 12-15) Puntatori e ricorsione

2 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Puntatori I puntatori sono delle variabili che come valore contengono degli indirizzi di memoria int count; count contiene un _valore_ intero count contiene un _valore_ intero int *countPtr; La variabile countPtr contiene lindirizzo di una locazione di memoria che contiene un valore intero. La variabile countPtr contiene lindirizzo di una locazione di memoria che contiene un valore intero countPtr Il nome di una variabile intera (es. count) fa direttamente riferimento ad un valore intero; Una variabile puntatore fa indirettamente riferimento ad un valore intero (deriferimento). Variabili di tipo puntatore devono essere dichiarate e inizializzate Es. int * countPtr; /*dichiarazoine*/ float * fcountPtr; countPtr = &count; /*inizializzazione*/ fcountPtr=NULL; /*NULL è una costante simbolica predefinita In molti file di intestazione incluso stdio.h. Se una variabile puntatore è inizializzata a NULL non punta ad alcuna locazione di memoria*/

3 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Operatore di indirizzo & (operatore unario di indirizzo) restituisce lindirizzo di memoria associato al suo operando; int y=5; int *yPtr; yPtr=&y; 5 y 3200

4 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Operatore di indirizzo & (operatore unario di indirizzo) restituisce lindirizzo di memoria associato al suo operando; int y=5; int *yPtr; yPtr=&y; 5 y 3200 Viene allocata memoria per la variabile puntatore yPtr. Nella locazione di yPtr viene memorizzato lindirizzo di memoria associato alla variabile y yPtr 3200 & deve essere applicato ad una variabile. Non Può essere applicato a costanti, espressioni o a variabili dichiarate con la specifica di classe di memoria register

5 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Operatore di deriferimento Loperatore * (detto operatore di deriferimento o di risoluzione dellindirizzo) consente di accedere al valore contenuto nella locazione di memoria puntata da una variabile puntatore

6 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Operatore di deriferimento Loperatore * (detto operatore di deriferimento o di risoluzione dellindirizzo) consente di accedere al valore contenuto nella locazione di memoria puntata da una variabile puntatore 5 y 3200 yPtr 3200 *yPtr è il valore contenuto nella locazione di memoria il cui indirizzo è memorizzato in yPtr 5

7 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Esempio La specifica di conversione %p di printf consente di stampare in output indirizzi di locazioni di memoria

8 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Esempio

9 Precedenza degli operatori

10 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Chiamata per riferimento delle funzioni Come può essere realizzata in C? Se vogliamo poter modificare il contenuto di una variabile x con cui invochiamo una funzione e far sì che tali modifiche permangano anche alluscita dalla funzione possiamo usare come parametro formale un puntatore (quindi passare lalla funzione lindirizzo di x)… Un esempio..

11 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Esempio /*eleva al cubo una variabile usando una chiamata per valore*/ #include #include int cubeByValue(int); main(){ int number =5; printf(Il valore originale del numero è: %d\n,number); number=cubeByValue(number); printf(il nuovo valore del numero è: %d\n,number); return 0; } int cubeByValue(int n) { return n*n*n; } Il valore originale del numero è: 5 Il nuovo valore del numero è: 125

12 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria…

13 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria…

14 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria…

15 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esempio 2 /*eleva al cubo una variabile usando una chiamata per riferimento*/ #include #include void cubeByReference(int *); main(){ int number =5; printf(Il valore originale del numero è: %d\n,number); cubeByReference(&number); printf(il nuovo valore del numero è: %d\n,number); return 0; } void cubeByReference(int *nPtr) {*nPtr=(*nPtr)*(*nPtr)*(*nPtr);} Il valore originale del numero è: 5 Il nuovo valore del numero è: 125

16 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… int number=5;cubeByReference(&number); 5 number 6200

17 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… int number=5;cubeByReference(&number); 5 number 6200 void cubeByReference(int *nPtr) {*nPtr=(*nPtr)*(*nPtr)*(*nPtr);} Invochiamo la funzione cubeByReference Viene allocata memoria per la variabile puntatore nPtr Viene copiato in nPtr il valore dellargomento con cui è stata invocata la funzione &number OVVERO lindirizzo della locazione di memoria della variabile number OVVERO

18 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… int number=5;cubeByReference(&number); 5 number 6200 void cubeByReference(int *nPtr) {*nPtr=(*nPtr)*(*nPtr)*(*nPtr);} Invochiamo la funzione cubeByReference 6200 Si esegue listruzione*nPtr=(*nPtr)*(*nPtr)*(*nPtr); *nPtr è il valore contenuto nella locazione di memoria puntata da nPtr 5 Listruzione quindi dice di elevare al cubo 5 e di memorizzare il valore risultante nella locazione di memoria puntata da nPtr

19 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… int number=5;cubeByReference(&number); 5 number 6200 void cubeByReference(int *nPtr) {*nPtr=(*nPtr)*(*nPtr)*(*nPtr);} Invochiamo la funzione cubeByReference 6200 Listruzione quindi dice di elevare al cubo 5 e di memorizzare il valore risultante nella locazione di memoria puntata da nPtr Il cubo di 5 è

20 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… int number=5;cubeByReference(&number); printf(il nuovo valore del numero è: %d\n,number); return 0; 5 number 6200 void cubeByReference(int *nPtr) {*nPtr=(*nPtr)*(*nPtr)*(*nPtr);} Si ritorna il controllo al main che esegue la prossima istruzione 6200 Si stampa il valore di number 125 La memoria allocata per nPtr viene rilasciata 125

21 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… Passaggio per valore evita di compromettere i valori delle variabili con cui sono invocate le funzioni (spesso non si vogliono modificare tali valori) Passaggio parametri per riferimento evita di dover allocare, ad ogni invocazione di funzione, memoria per copiare quantità di dati di input grandi che possono dover essere passati alla funzione esempio: se la funzione ha come input un vettore abbiamo bisogno solo di un parametro di tipo puntatore in cui copiare la locazione di memoria associata al primo elemento del vettore

22 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Qualificatore const Consente di specificare che il valore di una particolare variabile NON dovrà essere modificato Il compilatore intercetterà qualsiasi tentativo di modificare una variabile che sia stata dichiarata const e, nel caso in cui tale variabile sia modificata, darà un errore o un warning. serve a proteggere da errori nellimplementazione del codice rendere più facile il debugging serve a proteggere da errori nellimplementazione del codice rendere più facile il debugging

23 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Modi di passare un puntatore a una funzione Puntatore variabile a dati variabili – i dati possono essere modificati attraverso il puntatore –Il valore della variabile puntatore potrà essere modificato in modo che il puntatore possa fare riferimento ad altri dati

24 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Esempio #include #include void convertToUppercase (char *); main(){ char string[ ]=caratteri; printf(la stringa prima della conversione è %s\n,string); convertToUppercase(string); /*converte le lettere minuscole della stringa in maiuscole*/ printf(dopo la conversione la stringa è %s\n,string); return 0; } void convertToUppercase(char *s) { while (*s != \0) { if (*s >= a && *s = a && *s<= z)*s-=32;++s;}} La stringa prima della conversione è:pippo Dopo la conversione la stringa è PIPPO Vengono modificati i caratteri della Stringa. s punta a caratteri diversi della stringa durante lesecuzione della funzione

25 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Altri casi… Puntatore variabile a dati costanti (i dati non possono essere modificati) #include #include void printCharacters (const char *); main(){ char string [ ]=stampa i caratteri; printf (la stringa è:\n); printCharacters (string); putchar(\n); return 0; } void printCharacters(const char *s) { for (;*s!=\0;s++) putchar(*s);} la stringa è: stampa i caratteri

26 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Altri casi… Puntatore costante a dati variabili – il puntatore fa sempre riferimento alla stessa locazione di memoria –Tramite il puntatore si può cambiare il valore della locazione di memoria int *const ptr; Puntatore costante a dati costanti –il puntatore fa sempre riferimento alla stessa locazione di memoria –Il valore della locazione di memoria non può essere modificato const int *const ptr;

27 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esempio #include #include main () { int x=5,y; const int *const ptr=&x; *ptr=7; ptr=&y; ptr=&y; return 0; return 0;} Cannot modify a const object

28 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Bubblesort (versione 2) #include #include #define SIZE 10 void bubbleSort(int *,const int); void swap (int *,int*); main(){ int i,a[SIZE]={2,6,4,8,10,12,89,68,45,37}; printf(ordine originale \n); for (i=0;i<=SIZE-1;i++) printf(%d,a[i]); bubbleSort (a,SIZE); printf(dati in ordine crescente \n); for (i=0;i<=SIZE-1;i++) printf(%d,a[i]);printf(\n); return 0; }

29 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Bubblesort void bubbleSort(int *array, const int size) { int pass,j; for (pass=1;pass <=size-1;pass++) for (j=0;j<=size-2;j++) if(array[j]>array[j+1])swap(&array[j],&array[j+1]);}

30 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Swap void swap (int *element1Ptr, int *element2Ptr) { int temp; temp=*element1Ptr;*element1Ptr=*element2Ptr;*element2Ptr=temp;}

31 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Aritmetica dei puntatori I puntatori sono degli operandi validi per le espressioni aritmetiche (insieme limitato di operatori aritmetici possono essere applicati a puntatori), le espressioni di assegnamento e le espressioni di confronto – un puntatore potrà essere incrementato e decrementato con gli operatori ++ o --, ad un puntatore potrà essere sommato o sottratto un intero (operatori +, -,-=, +=). Infine ad un puntatore potrà essere sottratto un secondo puntatore. Devono però essere puntatori allo stesso tipo di dato

32 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Aritmetica dei puntatori per operare sui vettori int i; int v[100]; int * vPtr; for (i=0; i<100;i++) v[i]=i;vPtr=&v[0]; 012…9899 v 3000 vPtr vPtr poteva anche essere inizializzato Scrivendo vPtr=v; In quale locazione di memoria si trova v[1]? Ed il generico elemento v[i]?

33 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Operatore sizeof sizeof(nome_di variabile o tipo di dato o costante) È loperatore che consente di determinare quante celle di memoria sono associate ad un certo tipo di dato printf(sizeof(char)=%d\n sizeof(short)=%d\n sizeof(short)=%d\n sizeof(int)=%d\n sizeof(int)=%d\n sizeof(long)=%d\n sizeof(long)=%d\n sizeof(float)=%d\n sizeof(float)=%d\n sizeof(double)=%d\n sizeof(double)=%d\n sizeof(long double)=%d\n, sizeof(long double)=%d\n, sizeof(char),sizeof(short),sizeof(int),sizeof(long), sizeof(char),sizeof(short),sizeof(int),sizeof(long), sizeof(long),sizeof(float),sizeof(double), sizeof(long),sizeof(float),sizeof(double), sizeof(long double)); sizeof(long double)); sizeof(char)=1 sizeof(short)=2 sizeof(int)=2 sizeof(long)=4 sizeof(float)=4 sizeof(double)=8 sizeof(long double)=10

34 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Aritmetica dei puntatori per operare sui vettori int i; int v[100]; for (i=0; i<100;i++) v[i]=i;vPtr=&v[0]; 012…9899 v 3000 vPtr Supponendo che il numero di celle associate ad un Intero sia 2… vPtr+=2 fa puntare vPtr a v[2] 3004

35 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Aritmetica dei puntatori per operare sui vettori int i; int v[100]; for (i=0; i<100;i++) v[i]=i;vPtr=&v[0]; 012…9899 v vPtr Supponendo che il numero di celle associate ad un Intero sia 2… vPtr-- fa puntare vPtr alla posizione precedente del vettore, v[1] (stessa cosa scrivendo vPtr-=1) Infatti in questo caso la variabile puntatore viene decrementata di una quantità di celle pari a quelle che servono per memorizzare il tipo di dato in modo da far puntare allelemento precedente del vettore 3002

36 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Aritmetica dei puntatori per operare sui vettori int i; int v[100]; int *vPtr; int *vPtr2; for (i=0; i<100;i++) v[i]=i;vPtr=&v[0];vPtr2=&v[99]; 012…9899 v 3000 vPtr Supponendo che il numero di celle associate ad un Intero sia 2… x=vPtr2-vPtr; Assegna ad x il numero di elementi del vettore compresi tra lelemento puntato da vPtr2 e vPtr (infatti il valore delle differenza viene normalizzato al numero di celle necessarie per contenere un intero) in questo caso vPtr2 Laritmetica dei puntatori ha senso con gli elementi di un vettore altrimenti Non si può assumere che variabili dello stesso tipo siano immagazzinate in celle consecutive di memoria Un confronto tra puntatori ha senso solo per puntatori che puntano ad elementi diversi dello stesso vettore e può ad esempio essere usato per controllare quale dei due elementi puntati ha Indice maggiore

37 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Puntatori e vettori 012…9899 v 3000 vPtr v==&v[0] Se vPtr==v v[4] e *(vPtr+4) sono due notazioni equivalenti per far riferimento al valore del quinto elemento del vettore notazione con puntatore e offset Attenzione: il nome del vettore è un puntatore costante punterà sempre alla Prima posizione del vettore, non può essere modificato vPtr[4] e *(vPtr+4) sono anche notazioni equivalenti notazione con puntatore e indice

38 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio #include #include main(){ int i, offset, b[ ]={10,20,30,40}; int *bPtr=b; printf(stampa del vettore con notazione con indici); for (i=0;i<=3;i++) printf(b[%d]=%d\n,i,b[i]); printf(stampa del vettore con notazione con puntatore e offset); for (offset=0;offset<=3;offset++) printf(*(bPtr+%d)=%d\n,offset,*(bPtr+offset)); printf(stampa del vettore con notazione con puntatore e indice); for (i=0;i<=3;i++) printf(bPtr[%d]=%d\n,i,bPtr[i]); return 0; } b[0]=10 b[1]=20 b[2]=30 b[3]=40 *(bPtr+0)=10 *(bPtr+1)= 20 *(bPtr+2)= 30 *(bPtr+3)= 40 bPtr[0]=10 bPtr[1]=20 bPtr[2]=30 bPtr[3]=40

39 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Alcuni esercizi sulle stringhe… Si scriva una funzione che copia la stringa s2 nel vettore s1. /*Pre: dim del vettore s1 sufficienti per contenere s2*/ /*Post: s1 contiene la stringa s2*/ void stringcopy(char *s1, char *s2) { for (;*s2 !='\0';s1++,s2++) *s1=*s2;*s1='\0';}

40 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Alcuni esercizi sulle stringhe… /*Post: confronta s1 e s2. Restituisce -1 se s1 e' minore in ordine lessicografico di s2, 0 se sono uguali,1 se s1 e' maggiore in ordine lessicografico di s2 */ int stringcmp(char *s1, char *s2) { while (*s1==*s2) { if (*s1=='\0') return 0; s1++;s2++;} if (*s1 == '\0') return -1; else if (*s2 == '\0') return 1; else return (((*s1 - *s2)>0)?1:-1); }

41 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Alcuni esercizi sulle stringhe si scriva una funzione che, date due stringhe, restituisce 1 se la prima stringa compare come sottostringa della seconda, 0 altrimenti. Se la prima stringa e' vuota restituisce 1 (una stringa vuota e' sottostringa di q.siasi stringa. Se la seconda stringa e' vuota e la prima no allora restituisce 0.

42 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Alcuni esercizi sulle stringhe int findstr (char *s1, char *s2) { char *temp_s1; char *temp_s2; while (*s2!='\0'){ temp_s2=s2;temp_s1=s1; while ((*s1 == *s2)&&(*s1!='\0')&&(*s2!='\0')) {s1++;s2++;} if (*s1=='\0') return 1; else if (*s2=='\0') return 0; else{s2=temp_s2+1;s1=temp_s1;}} return ((s1=='\0')?1:0); }

43 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Vettori di puntatori I vettori possono contenere elementi di tipo puntatore Esempio: array di stringhe const char *suit[4]={Cuori,Quadri,Picche,Fiori}; Cuori\0 suitFiori\0 Quadri\0 Picche\0 Gli elementi di suit sono puntatori alla posizione dove è memorizzato il primo carattere di ciascuna stringa ciascuno punta in maniera Stabile ad una determinata stringa La memoria allocata per suit è quella necessaria per contenere 4 puntatori Ciascuna stringa ha poi allocata memoria separatamente per Contenerne i caratteri incluso quello di fine stringa

44 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Vettori di puntatori I vettori possono contenere elementi di tipo puntatore Esempio: array di stringhe const char *suit[4]={Cuori,Quadri,Picche,Fiori}; Cuori\0 suitFiori\0 Quadri\0 Picche\0 Non si poteva usare una matrice di caratteri? Si MA luso di vettori di puntatori a caratteri fa risparmiare memoria Per ogni stringa Si alloca la memoria sufficiente a memorizzare la stringa NON la memoria necessaria a memorizzare la stringa più lunga

45 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio Si scriva un programma che mescoli un mazzo di carte, stampando lordine delle carte ottenuto Cuori Quadri Picche Fiori Asso Due Dieci Fante Donna Re mazzo_carte

46 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Pseudocodice Inizializza la matrice mazzo_carte a 0 Inizializza una variabile contatore k a 1 Fino a quando non è stato assegnato un ordine a ciascuna carta (52 iterazioni) – Scegli la prossima carta Scegli casualmente una riga i Scegli casualmente una riga i Scegli casualmente una colonna j Se mazzo_carte[i][j] è diverso da zero scegli una nuova riga e colonna, ALTRIMENTI mazzo_carte[i][j]=k incrementa k Stampa una a una le carte nellordine selezionato Critico …potrei avere lunghe attese (attesa infinita) prima di trovare una posizione libera. Come potrei risolvere il problema? Posso scegliere casualmente solo tra le posizioni non ancora riempite per esercizio

47 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Codice #include#include#include void shuffle(int wDeck[ ][13]); void deal(const int wDeck[ ][13], const char *wFace[ ], const char *wsuit[ ]);

48 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Codice int main() { const char *suit[4]={Cuori,Quadri,Picche,Fiori}; const char *face[13]={Uno,Due,Tre,Quattro, Cinque,Sei,Sette,Otto,Nove,Dieci,Fante, Donna, Re}; int deck[4][13]={0}; srand(time(0));shuffle(deck);deal(deck,face,suit);} Alloco memoria per una matrice di 52 interi. Inizializzo la matrice a 0

49 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Shuffle void shuffle(int wDeck[ ][13]) { int i,j,k; for (k=1; k<=52; k++) { do{i=rand()%4;j=rand()%13; } while (wDeck[i][j] !=0); wDeck[i][j]=k; }}

50 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Shuffle Cuori Quadri Picche Fiori Asso Due Dieci Fante Donna Re k=1 i 1 j 3 1 k=2 i 3 j 10 2

51 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Shuffle Cuori Quadri Picche Fiori Asso Due Dieci Fante Donna Re SCEGLIAMO UN ALTRO i e j, LA POSIZIONE È GIA OCCUPATA i 1 j 3 1 k=3 i 2 j

52 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Stampa delle carte nellordine selezionato void deal(const int wDeck[][13],const char *wFace[ ], const char *wSuit[ ]) { int i,j,k; for (k=1;k<=52;k++){ for (i=0;i<=3;i++){ for (j=0;j<=12;j++){ if (wDeck[i][j]==k){ printf(%s di %s\n,wFace[j],wSuit[i]); }}}}} Quattro di Quadri Fante di Fiori Re di Picche --- Scandiamo sempre tutta la matrice anche quando abbiamo trovato lelemento che corrisponde alla k-esima carta inefficiente. Qualche idea su come evitare questo problema?

53 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Puntatori a funzioni Un nome di funzione indica lindirizzo di memoria in cui è memorizzata la prima istruzione della funzione Esempio di uso: una versione del bubblesort che consenta di inserire da input se il vettore deve essere ordinato in ordine crescente o decrescente

54 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Bubblesort#include #define SIZE 10 void bubble(int work[ ], const int size, int (*compare)(int a,int b)); int ascending(int a, int b); int descending(int a,int b); Puntatore ad una funzione che prende come parametri due interi e restituisce un intero Compare è un puntatore a funzione

55 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Bubblesort int main() { int order; /* 1 per ordine crescente, 2 per decrescente*/ int counter; int a[SIZE]={2,6,4,8,10,12,89,68,45,37}; printf(si inserisca 1 per ordinare in ordine crescente, 2 per un ordinamento decrescente del vettore \n); scanf(%d, &order); printf(dati nellordine originale \n); for (counter=0;counter

56 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Bubble void bubble(int work[ ],const int size, int (*compare)(int a, int b)) { int pass; int count; void swap(int *element1Ptr,int *element2ptr); for (pass=1;pass

57 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Swap, ascending, descending void swap(int *element1Ptr, int *element2Ptr) { int hold; hold=*element1Ptr;*element1Ptr=*element2Ptr;*element2Ptr=hold;} /*ritorna 1 se non si segue lordinamento crescente*/ int ascending(int a,int b) { return ba; } A seconda che si voglia ordinare in ordine crescente o decrescente occorre testare due condizioni diverse per verificare se due elementi consecutivi sono ordinati correttamente o meno printf(si inserisca 1 per ordinare in ordine crescente, 2 per un ordinamento decrescente del vettore \n); scanf(%d, &order); printf(dati nellordine originale \n); for (counter=0;counter

58 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Puntatori a funzione (secondo esempio) Un utente seleziona unopzione da un menu. Ciascuna opzione è servita da una funzione differente. I diversi puntatori a funzione sono memorizzati in un array di puntatori a funzione. La scelta dellutente fornisce lindice del vettore. Il puntatore a funzione è usato per invocare la funzione opportuna in base alla scelta dellutente.

59 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Codice#include void function1(int a); void function2 (int b); void function3 (int c); int main() { void (*f[3])(int)={function1,function2,function3}; int choice,i; printf(inserisci la scelta della funzione da invocare: 0, 1, 2 a seconda che vogliate moltiplicare per uno, due o tre il valore inserito. Inserire il valore 3 per terminare lesecuzione); scanf(%d,&choice); printf(inserisci intero \n); scanf(%d,&i); while(choice>=0 && choice =0 && choice <3){(*f[choice])(i); printf(inserisci la scelta della funzione da invocare: 0, 1, 2 a seconda che vogliate moltiplicare per uno, due o tre il valore inserito. Inserire il valore 3 per terminare lesecuzione); scanf(%d, &choice); printf(inserisci intero \n); scanf(%d,&i);} return 0; } inizializza un array di tre puntatori a funzione Queste funzioni prendono in input un intero e non restituiscono valori invoca la funzione puntata da f[choice] sul valore intero inserito da input i

60 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Codice delle tre funzioni… void function1(int a) { printf(il valore di a moltiplicato per uno è %d\n,a*1); } void function2(int a) { printf(il valore di a moltiplicato per due è %d\n,a*2); } void function3(int a) { printf(il valore di a moltiplicato per tre è %d\n,a*3); }

61 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010

62 Argomenti avanzati sulle variabili e funzioni… Classi di memoria Regole di scope

63 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Classi di memoria Una variabile ha associato un tipo, un nome, una dimensione ed un valore Altri attributi di un identificatore (e.g. variabile, nome di funzione) usato in un programma sono la sua classe di memoria – auto – register –extern –static il periodo durante il quale lidentificatore ha associata memoria (storage duration) il periodo durante il quale lidentificatore ha associata memoria (storage duration) lo scope (in quali parti del programma si può far riferimento all identificatore) linkage (se il programma è suddiviso in più file se lidentificatore può essere usato solo in questo file oppure in altri file previa opportune dichiarazioni) ARGOMENTO CHE TRATTERETE AD ESERCITAZIONE

64 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Automatic storage duration Classi di memoria auto autoregister Le variabili di tipo auto o register permangono in memoria fino a quando è attivo il blocco di istruzioni allinterno del quale la variabile è definita Le variabili locali alle funzioni sono tipicamente di tipo auto (è la loro classe di memoria di default) Se una variabile è di tipo register si suggerisce che venga memorizzata in un registro I compilatori sanno ottimizzare luso dei registri meglio di un programmatore I compilatori sanno ottimizzare luso dei registri meglio di un programmatore possono decidere di ignorare la richiesta di mettere in un registro una variabile possono decidere di ignorare la richiesta di mettere in un registro una variabile Le variabili viste finora erano implicitamente dichiarate come auto Se dichiarate allinizio del main è loro allocata memoria fino alluscita dal programma se dichiarate allinizio di una funzione la variabile ha allocata memoria fino a quando non si esce dalla funzione register int counter=1; dice che la variabile intera counter dovrebbe essere memorizzata in un registro e inizializzata a 1

65 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Static storage duration Le parole chiave extern extern static static sono usate per identificare variabili e funzioni di tipo static storage Memoria è allocata una volta per tutte e le variabili sono inizializzate allinizio del programma. Tale memoria è disponibile per lintera durata del programma Le variabili globali sono di tipo extern per default. Sono dichiarate fuori da ogni funzione e mantengono memoria a loro allocata durante lintera durata del programma. Possono essere riferite da una qualsiasi funzione che segue la loro dichiarazione. Le variabili di tipo static invece sono note solo allinterno della funzione dove sono definite. Tuttavia quando si esce dalla funzione si continua a memorizzare il loro valore. La prossima volta che si invoca la funzione la variabile locale static avrà come valore quello che aveva alla fine della precedente invocazione. static int count=1;

66 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Regole di scope Lo scope di un identificatore è la porzione del programma allinterno della quale si può fare riferimento allidentificatore – function scope – file scope –block scope –function-prototype scope etichette usate nel costrutto switch possono essere usate solo allinterno della funzione nella quale compaiono (e possono essere riferite in qualsiasi punto della funzione) Un identificatore dichiarato allesterno di ogni funzione ha uno scope di tipo file scope Possono essere riferite in qualsiasi punto allinterno del file a partire dal punto in cui lidentificatore è dichiarato Esempi: variabili globali, definizioni di funzioni, prototipi)

67 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Regole di scope Lo scope di un identificatore è la porzione del programma allinterno della quale si può fare riferimento allidentificatore – function scope – file scope –block scope –function-prototype scope Identificatori block scope possono essere riferiti allinterno del Blocco in cui sono dichiarate Il blocco è delimitato da {} Variabili static hanno uno scope di blocco Variabili locali ad una funzione hanno scope di blocco Gli unici identificatori di tipo function prototype scope sono quelli usati nella lista dei parametri di un prototipo di funzione. Dato che tali nomi, se usati, sono ignorati dal compilatore, hanno valore solo allinterno del prototipo. Gli stessi identificatori possono essere riutilizzati in altre parti del programma senza problemi di ambiguità

68 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } Se lo stesso identificatore è usato in un blocco più interno allinterno del blocco interno vale la definizione e inizializzazione del blocco interno. Il valore di x allinterno dello scope più esterno del main è: 5 Il valore di x allinterno dello scope più interno del main è: 7 Il valore di x allinterno dello scope più esterno del main è: 5

69 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… void useLocal (void) { int x=25; /*è di classe di memoria auto*/ printf() printf(valore di x entrati in useLocal, allinizio della funzione: %d\n,x); x++; printf(valore di x entrati in useLocal, alla fine della funzione: %d\n,x); }

70 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } Il valore di x entrati in UseLocal allinizio della funzione è: 25 Il valore di x entrati in UseLocal alla fine della funzione è: 26

71 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… void useStaticLocal() { static int x=50; /*inizializzata solo la prima volta che si entra nella funzione*/ printf(local static vale %d allinizio della funzione useStaticLocal,x); x++; printf(local static vale %d alla fine della funzione useStaticLocal,x); }

72 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… void useGlobal() { printf(global x vale %d allentrata di useGlobal\n,x); x*=10; printf(global x vale %d alla fine di useGlobal\n,x); }

73 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } local static vale 50 allinizio della funzione useStaticLocal local static vale 51 alla fine della funzione useStaticLocal

74 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } Global x vale 1 allentrata di useGlobal Global x vale 10 alla fine di useGlobal

75 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } Il valore di x entrati in UseLocal allinizio della funzione è: 25 Il valore di x entrati in UseLocal alla fine della funzione è: 26

76 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } local static vale 51 allinizio della funzione useStaticLocal local static vale 52 alla fine della funzione useStaticLocal

77 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… #include #include void useLocal (void); void useStaticLocal (void); void useGlobal (void); int x=1; /*variabile globale*/ int main() { int x=5;/*variabile locale al main*/ printf(il valore di x allinterno dello scope più esterno del main è: %d,x); {/*comincia un nuovo scope*/ int x=7; /*variabile locale al blocco*/ printf(il valore di x allinterno dello scope più interno del main è: %d,x); } printf(il valore di x nello scope più esterno del main è: %d, x); useLocal();useStaticLocal();useGlobal();useLocal();useStaticLocal();useGlobal(); return 0; } Global x vale 10 allentrata di useGlobal Global x vale 100 alla fine di useGlobal

78 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Chiamata a funzione-cosa succede in memoria Il call stack è una struttura dati speciale (stack o pila) usata dal sistema per gestire le informazioni di una funzione attiva (che è stata chiamata e non ha ancora completato la sua esecuzione) Cosa memorizza – indirizzo di ritorno – variabili locali –parametri passati alla funzione

79 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Call stack Funzionamento: ogni volta che si invoca una funzione si inserisce nello stack lindirizzo di ritorno ed i vari parametri del chiamante ogni volta che termina lesecuzione di una funzione questa passa il controllo allindirizzo memorizzato nello stack –In questo modo si sa da dove riprendere lesecuzione

80 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Call stack Un call stack è composto da call frames (uno per ogni funzione) Esempio: se una funzione DrawSquares chiama una funzione DrawLine (che è quella attualmente in esecuzione) il call stack conterrà informazioni di questo tipo

81 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio. Come si implementa una pila con i vettori? Struttura dati in cui memorizzare informazioni. Supponete di saper definire un tipo di dato record che contenga le informazioni di ciascun stack frame e che se x è una variabile di tipo record e y è una variabile di tipo record possiate scrivere istruzioni tipo y=x. –Un nuovo record viene inserito in cima (push) –E possibile rimuovere e leggere solo lelemento in cima (pop)

82 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Gestione a pila Come realizzereste la pila usando i vettori? record Pila[MAX_DIM]; record Pila[MAX_DIM]; int top_Stack; int top_Stack; Assumete di avere a disposizione due funzioni isempty (record P[ ], int N, int topstack) e isfull (record P[ ], int N, int topstack) in grado di dirvi se lo stack è vuoto o è pieno (e quindi non possono essere inseriti altri record) come potete realizzare la funzioni pop e push?

83 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Funzioni isempty e isfull int isempty (record P[ ], int N, int topstack) { return (topstack==0); } int isfull (record P[ ], int N, int topstack) { return (topstack==N); }

84 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Funzioni pop e push /* pre: la funzione viene invocata solo su pile non vuote*/ record pop(record P[ ], int N, int* top_stack) { record temp_r; temp_r= P[*top_stack]; *top_stack=*top_stack-1; return temp_r; void push (record P[ ], int N, int* top_stack, record R) { if (! isfull(P,N,top_stack)) {P[*top_stack]=R;*top_stack+=1;}}

85 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Ricorsione Abbiamo visto come un problema complesso possa essere scomposto in task, ciascuno realizzato tramite una funzione Una funzione può invocare altre funzioni E possibile anche invocare la STESSA funzione, su un input diverso – Un task complesso può essere risolto invocando la funzione che realizza il task su dei sottoproblemi, usando la capacità di svolgere il task su sottoproblemi per riuscire a svolgere il task sullintero problema ricorsione ricorsione

86 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Ricorsione…un esempio Vogliamo scrivere una funzione che consenta di calcolare il fattoriale n! n!= n*(n-1)*(n-2)*(n-3)*…*2*1 Approccio ricorsivo: – – Supponiamo di poter invocare ricorsivamente la funzione su interi n < n e di poter usare tale invocazione per calcolare il fattoriale di n – – Possiamo sfruttare il fatto che n!=n*(n-1)! – –Per calcolare il fattoriale di n invoco la funzione fatt su n-1 e moltiplico il risultato per n Abbiamo ridotto la complessità del problema esprimendo la soluzione in funzione della risoluzione di problemi meno complessi sfruttando il fatto che tramite chiamata ricorsiva riusciamo a risolvere su problemi più piccoli per trovare la soluzione del problema più complesso VERSIONE ITERATIVA int fattoriale_iter(int number) { int counter; int factorial=1; for (counter=number; counter>=1; counter--) factorial*=counter; return factorial; }

87 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Ricorsione…un esempio Vogliamo scrivere una funzione che consenta di calcolare il fattoriale n! n!= n*(n-1)*(n-2)*(n-3)*…*2*1 Approccio ricorsivo: – – Supponiamo di poter invocare ricorsivamente la funzione su interi n < n e di poter usare tale invocazione per calcolare il fattoriale di n – – Possiamo sfruttare il fatto che n!=n*(n-1)! – –Per calcolare il fattoriale di n invoco la funzione fatt su n-1 e moltiplico il risultato per n Abbiamo ridotto la complessità del problema esprimendo la soluzione in funzione della risoluzione di problemi meno complessi sfruttando il fatto che tramite chiamata ricorsiva riusciamo a risolvere su problemi più piccoli per trovare la soluzione del problema più complesso

88 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Fattoriale (versione ricorsiva) int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } Caso base. Occorre saper risolvere direttamente i casi base.

89 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata x=fatt(5); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } PRIMA INVOCAZIONE DI FATT fatt(5) Allentrata della funzione si alloca memoria per la var. locale n Si copia in tale locazione il valore 5 n 5Si invoca fatt(4) 3200

90 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(4); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } SECONDA INVOCAZIONE DI FATT fatt(4) Allentrata della funzione si alloca memoria per la var. locale n, relativa A QUESTA INVOCAZIONE DI FUNZIONE Si copia in tale locazione il valore 4 n 4Si invoca fatt(3) 5200

91 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(3); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } TERZA INVOCAZIONE DI FATT fatt(3) Allentrata della funzione si alloca memoria per la var. locale n, relativa A QUESTA INVOCAZIONE DI FUNZIONE Si copia in tale locazione il valore 3 n 3Si invoca fatt(2) 7800

92 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(2); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } QUARTA INVOCAZIONE DI FATT fatt(2) Allentrata della funzione si alloca memoria per la var. locale n, relativa A QUESTA INVOCAZIONE DI FUNZIONE Si copia in tale locazione il valore 2 n 2Si invoca fatt(1) 9800

93 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(1); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } QUINTA INVOCAZIONE DI FATT fatt(1) Allentrata della funzione si alloca memoria per la var. locale n, relativa A QUESTA INVOCAZIONE DI FUNZIONE Si copia in tale locazione il valore 1 n 1 Si restituisce il controllo alla funzione chiamante fatt(2), restituendo fatt(5) fatt(4) fatt(2) fatt(3) fatt(1) Fondamentale che La sequenza di Invocazioni termini SEMPRE con linvocazione della funzione su un caso che sappiamo risolvere direttamente (caso base) La memoria allocata per n viene rilasciata

94 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(2); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } QUARTA INVOCAZIONE DI FATT fatt(2) Allentrata della funzione si alloca memoria per la var. locale n, relativa A QUESTA INVOCAZIONE DI FUNZIONE Si copia in tale locazione il valore 2 n restituisce 1 Viene calcolato fatt(2) 2*1=2 e viene restituito tale valore alla funzione chiamante fatt(3) fatt(5) fatt(4) fatt(2) fatt(3) fatt(1)

95 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(3); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } TERZA INVOCAZIONE DI FATT fatt(3) n restituisce 2 Viene calcolato fatt(3) 3*2=6 e viene restituito tale valore alla funzione chiamante fatt(4) fatt(5) fatt(4) fatt(2) fatt(3) fatt(1)

96 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata fatt(4); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } SECONDA INVOCAZIONE DI FATT fatt(4) n restituisce 6 Viene calcolato fatt(4) 4*6=24 e viene restituito tale valore alla funzione chiamante fatt(5) fatt(4) fatt(2) fatt(3) fatt(1)

97 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 5! Viene invocata x=fatt(5); int fatt (int n) { if (n==1) return 1; else return (fatt(n-1)*n); } PRIMA INVOCAZIONE DI FATT fatt(5) n restituisce 24 Viene calcolato fatt(5) 5*24=120 e viene restituito tale valore alla funzione chiamante main() fatt(5) fatt(4) fatt(2) fatt(3) fatt(1)

98 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Alcuni commenti… Approccio ricorsivo – richiede linvocazione di molte chiamate a funzione, di allocare ogni volta memoria per i parametri e le variabili locali può essere inefficiente può essere inefficiente ogni problema che ammette una soluzione ricorsiva ammette anche una soluzione iterativa ogni problema che ammette una soluzione ricorsiva ammette anche una soluzione iterativa TUTTAVIA ragionare in modo ricorsivo è molto utile e vedrete di qui a poco (corso del secondo semestre/algoritmi) che esistono strutture dati molto importanti quali gli alberi sui quali si riesce a ragionare efficamente solo in modo ricorsivo RAGIONARE IN MODO RICORSIVO E COMPLESSO MA E Q.SA DI FONDAMENTALE PER UN INFORMATICO!! Abbiamo visto cosa succede in memoria quando invochiamo una sequenza di chiamate ricorsive…è importante capire come si ragiona ricorsivamente

99 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Come si ragiona ricorsivamente INPUT OUTPUT funzione Se siamo in grado di descrivere correttamente cosa fa la funzione (postcondizione) Dobbiamo chiederci se possiamo usare il fatto che la funzione possa essere applicata su input più piccoli per risolvere il caso generale Se gli output della invocazioni su casi più piccoli possono essere elaborati ed usati per trovare la soluzione al problema (OUTPUT) per il caso più grande AVER DETERMINATO IL MODO DI FARE CIO CI DARA IL NOSTRO CODICE RICORSIVO output1output2

100 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Come si ragiona ricorsivamente INPUT OUTPUT funzione Se siamo in grado di descrivere correttamente cosa fa la funzione (postcondizione) Dobbiamo chiederci se possiamo usare il fatto che la funzione possa essere applicata su input più piccoli per risolvere il caso generale Se gli output della invocazioni su casi più piccoli possono essere elaborati ed usati per trovare la soluzione al problema (OUTPUT) per il caso più grande AVER DETERMINATO IL MODO DI FARE CIO CI DARA IL NOSTRO CODICE RICORSIVO output1output2 Sarà poi fondamentale individuare i casi base e assicurarci che tutte le sequenze di chiamate ricorsive terminino sempre con linvocazione di un caso base

101 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… SI scriva una funzione ricorsiva che dati due numeri interi a e b calcoli a+b Se so calcolare x+y, x<=a, y

102 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio… SI scriva una funzione ricorsiva che dati due numeri interi a e b calcoli a+b Se so calcolare x+y, x<=a, y

103 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Soluzione int somma (int a, int b) { if (b==0) return a; else return (somma(a,b-1)+1); } Vediamo cosa succede invocando somma (3,2)

104 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 3+2 Viene invocata x=somma(3,2); int somma (int a, int b) { if (b==0) return a; else return (somma(a,b-1)+1); } PRIMA INVOCAZIONE DI SOMMA Allentrata della funzione si alloca memoria per le var. locale a e b Si copia in tali locazioni i valori 3 e 2 a 3 Si invoca somma(3,1) 3200 b

105 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 3+2 Viene invocata somma(3,1); int somma (int a, int b) { if (b==0) return a; else return (somma(a,b-1)+1); } SECONDA INVOCAZIONE DI SOMMA Allentrata della funzione si alloca memoria per le var. locale a e b RELATIVE A QUESTA INVOCAZIONE Si copia in tali locazioni i valori 3 e 1 a 3 Si invoca somma(3,0) 5700 b

106 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 3+2 Viene invocata somma(3,0); int somma (int a, int b) { if (b==0) return a; else return (somma(a,b-1)+1); } TERZA INVOCAZIONE DI SOMMA Allentrata della funzione si alloca memoria per le var. locale a e b RELATIVE A QUESTA INVOCAZIONE Si copia in tali locazioni i valori 3 e 0 a 3 Si ritorna il controllo restituendo b somma(3,2) somma(3,1) somma(3,0) La memoria allocata viene rilasciata

107 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 3+2 Viene invocata somma(3,1); int somma (int a, int b) { if (b==0) return a; else return (somma(a,b-1)+1); } SECONDA INVOCAZIONE DI SOMMA Allentrata della funzione si alloca memoria per le var. locale a e b RELATIVE A QUESTA INVOCAZIONE Si copia in tali locazioni i valori 3 e 1 a 3 Si ritorna il controllo restituendo 4 a somma (3,2) 5700 b La memoria allocata viene rilasciata Ha restituito 3 somma(3,2) somma(3,1) somma(3,0)

108 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di 3+2 Viene invocata somma(3,2); int somma (int a, int b) { if (b==0) return a; else return (somma(a,b-1)+1); } PRIMA INVOCAZIONE DI SOMMA Allentrata della funzione si alloca memoria per le var. locale a e b RELATIVE A QUESTA INVOCAZIONE Si copia in tali locazioni i valori 3 e 2 a 3 Si ritorna il controllo restituendo 5 a main() 3200 b La memoria allocata viene rilasciata Ha restituito 4 somma(3,2) somma(3,1) somma(3,0)

109 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un terzo esempio Calcolo di a*b

110 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un terzo esempio Calcolo di a*b a*b= a+a+… …+a a*b=(a*(b-1))+a Caso base a*0=0 b volte

111 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Moltiplicazione tra due interi int prodotto (int a,int b) { if (b==0) return 0; else return (prodotto(a,b-1)+a); }

112 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un quarto esempio Precondizione: a>=1 Calcolo di a b a b = a*a*… …*a a b =(a b-1 )*a Caso base a 0 =1 b volte

113 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Moltiplicazione tra due interi int potenza (int a,int b) { if (b==0) return 1; else return (potenza(a,b-1)*a); }

114 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Numeri di Fibonacci La serie di Fibonacci 0,1,1,2,3,5,8,13,21,.. Comincia con i numero 0 e 1 ed ha la proprietà che se si conoscono F(i) e F(i+1) allora F(i+2)=F(i+1)+F(i) E una serie che occorre in natura. Il rapporto tra due numeri consecutivi della serie di Fibonacci converge al numero che è chiamata sezione aurea Usare come rapporto tra dimensioni la sezione aurea è esteticamente piacevole usato sin dallantichità in architettura (esempio rapporto tra le dimensioni di una finestra, le dimensioni relative dei lati di una cartolina etc.)

115 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Codice long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+Fibonacci(n-2)); } Calcola F(n)

116 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata x=Fibonacci(3); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} PRIMA INVOCAZIONE DI FIBONACCI Allentrata della funzione si alloca memoria per le var. n Si copia in tale locazione il valore 3 n 3 Si invoca Fibonacci(2) E Fibonacci(1) 3200 Attenzione: non si può sapere se verrà valutata prima la chiamata Fibonacci(2) O Fibonacci(1)

117 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata Fibonacci(2); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} SECONDA INVOCAZIONE DI FIBONACCI Allentrata della funzione si alloca memoria per le var. n RELATIVA A QUESTA INVOCAZIONE Si copia in tale locazione il valore 2 n 2 Si invoca Fibonacci(1) E Fibonacci(0) 4000 Attenzione: non si può sapere se verrà valutata prima la chiamata Fibonacci(1) O Fibonacci(0) F(3) F(1)F(2) F(0)F(1)

118 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata Fibonacci(1); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} TERZA INVOCAZIONE DI FIBONACCI Allentrata della funzione si alloca memoria per le var. n RELATIVA A QUESTA INVOCAZIONE Si copia in tale locazione il valore 1 n 1 Si restituisce al chiamante Fibonacci(2) il valore F(3) F(1)F(2) F(0)F(1) 1

119 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata Fibonacci(0); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} QUARTA INVOCAZIONE DI FIBONACCI Allentrata della funzione si alloca memoria per le var. n RELATIVA A QUESTA INVOCAZIONE Si copia in tale locazione il valore 0 n 0 Si restituisce al chiamante Fibonacci(2) il valore F(3) F(1)F(2) F(0)F(1) 1 0

120 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata Fibonacci(1); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} QUINTA INVOCAZIONE DI FIBONACCI Allentrata della funzione si alloca memoria per le var. n RELATIVA A QUESTA INVOCAZIONE Si copia in tale locazione il valore 1 n 1 Si restituisce al chiamante Fibonacci(3) il valore F(3) F(1)F(2) F(0)F(1) 1 0 1

121 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata Fibonacci(2); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} Allentrata della funzione si alloca memoria per le var. n RELATIVA A QUESTA INVOCAZIONE Si copia in tale locazione il valore 2 n 2 Si restituisce al chiamante Fibonacci(3) il valore F(3) F(1)F(2) F(0)F(1)

122 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio.. Calcolo di Fibonacci(3) Viene invocata Fibonacci(3); long Fibonacci (long n) { if ((n==0)||(n==1)) return n; else return (Fibonacci(n-1)+ Fibonacci(n-2));} Allentrata della funzione si alloca memoria per le var. n RELATIVA A QUESTA INVOCAZIONE Si copia in tale locazione il valore 3 n 2 Si restituisce al chiamante main il valore F(3) F(1)F(2) F(0)F(1) Numero di chiamate necessarie Per calcolare F(n) dellordine di 2 n complessità esponenziale

123 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Fibonacci Valore di nF(n)Numero di chiamate di funzione F(n) … … La ricorsione in molti casi è utile però può ridurre lefficienza. Numero di chiamate elevato significa che paghiamo un overhead elevato (tempo e spazio) per invocare le funzioni, allocare memoria per le variabili locali

124 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. A B C

125 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. A B C Ogni mossa poteva portare allo spostamento di un unico disco E in ogni momento i dischi dovevano essere posizionati in ordine decrescente su ciascuno dei paletti La leggenda narra che il mondo finirà prima che i monaci siano riusciti a completare questo compito!

126 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi…un esempio La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. A B C Ad esempio il disco viola può essere spostato in una mossa da A a B

127 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi…un esempio La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. A B C Nella mossa successiva il disco azzurro può essere spostato da A a C Il disco azzurro NON poteva essere spostato da A a B perché tale spostamento non avrebbe soddisfatto il vincolo di ordinamento decrescente dei dischi in B

128 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi…un esempio La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto dappoggio C. A B C Nella mossa successiva non possiamo direttamente spostare il disco verde Possiamo ad esempio prima spostare il disco viola in C e poi il disco verde in B

129 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi Problema di difficile risoluzione iterativa se abbiamo molti dischi (e dobbiamo trovare un algoritmo che valga sempre, per qualsiasi numero di dischi) Ragionare in modo ricorsivo aiuta a trovare una soluzione A B

130 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi Cosa vogliamo fare? – Muovere n dischi dal paletto A al paletto B usando C come appoggio Come lo possiamo fare? – Muovere n-1 dischi dal paletto A al paletto C usando B come appoggio A B

131 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi Cosa vogliamo fare? – Muovere n dischi dal paletto A al paletto B usando C come appoggio Come lo possiamo fare? – Muovere n-1 dischi dal paletto A al paletto C usando B come appoggio –Spostare il disco più grande da A in B A B

132 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi Cosa vogliamo fare? – Muovere n dischi dal paletto A al paletto B usando C come appoggio Come lo possiamo fare? – Muovere n-1 dischi dal paletto A al paletto C usando B come appoggio –Spostare il disco più grande da A in B –Muovere n-1 dischi da C a B usando A come appoggio A B Chiamate ricorsive

133 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice #include void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *); main(){ int i,n,n_A,n_B,n_C; int A[100]={0}; int B[100]={0}; int C[100]={0}; n_A=n_B=n_C=0; printf(inserisci un numero di dischi tra 1 e 100 \n); scanf(%d, &n); while ((n>100)||(n 100)||(n<1)){ printf(inserisci un numero di dischi tra 1 e 100 \n); printf(inserisci un numero di dischi tra 1 e 100 \n); scanf(%d, &n); } for (i=0;i

134 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice #include void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *); main(){ int i,n,n_A,n_B,n_C; int A[100]={0}; int B[100]={0}; int C[100]={0}; n_A=n_B=n_C=0; printf(inserisci un numero di dischi tra 1 e 100 \n); scanf(%d, &n); while ((n>100)||(n 100)||(n<1)){ printf(inserisci un numero di dischi tra 1 e 100 \n); printf(inserisci un numero di dischi tra 1 e 100 \n); scanf(%d, &n); } for (i=0;i

135 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice #include void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *); main(){ int i,n,n_A,n_B,n_C; int A[100]={0}; int B[100]={0}; int C[100]={0}; n_A=n_B=n_C=0; printf(inserisci un numero di dischi tra 1 e 100 \n); scanf(%d, &n); while ((n>100)||(n 100)||(n<1)){ printf(inserisci un numero di dischi tra 1 e 100 \n); printf(inserisci un numero di dischi tra 1 e 100 \n); scanf(%d, &n); } for (i=0;i

136 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice /*pre: num >=1*/ void hanoi(int num, int a[ ], int *N_a, int b[ ], int *N_b, int c[ ], int *N_c) { if (num==1) {b[(*N_b)]=a[(*N_a)-1];(*N_b)=(*N_b)+1;(*N_a)=(*N_a)-1;}else{hanoi(num-1,a,N_a,c,N_c,b,N_b);b[(*N_b)]=a[(*N_a)-1];(*N_b)=(*N_b)+1;(*N_a)=(*N_a)-1; hanoi (num-1,c,N_c,b,N_b,a,N_a); }}

137 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(4,A,&n_A,B,&n_B,C, &n_C); n_A 0 n_B 0 n_C A B through C hanoi (3, A, N_a, C, N_c, B, N_b); A C through B

138 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(3,A,N_a,C,N_c,B, N_b); A C through B hanoi (2, A, N_a, B, N_b, C, N_c); A B through C n_An_Bn_C

139 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,A,N_a,B,N_b,C, N_c); A B through C hanoi (1, A, N_a, C, N_c, B, N_b); A C through B n_An_Bn_C

140 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,A,N_a,C,N_c,B, N_b); A C through B c[n_C]=a[n_A-1]; n_A--; n_C++; n_An_Bn_C

141 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,A,N_a,C,N_c,B, N_b); A C through B c[n_C]=a[n_A-1]; n_A--; n_C++; n_An_Bn_C Viene restituito il controllo

142 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,A,N_a,B,N_b,C, N_c); A B through C Viene restituito il controllo a questa chiamata n_An_Bn_C b[n_B]=a[n_A-1]; n_A--; n_B++;

143 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,A,N_a,B,N_b,C, N_c); A B through C Si invoca: hanoi (1, C, N_c, B, N_b, A, N_a); C B through A n_An_Bn_C b[n_B]=a[n_A-1]; n_A--; n_B++;

144 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,C,N_c,B,N_b,A, N_a); C B through A n_An_Bn_C

145 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,C,N_c,B,N_b,A, N_a); C B through A n_An_Bn_C Si restituisce il controllo al chiamante

146 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,A,N_a,B,N_b,C, N_c); A B through C n_An_Bn_C hanoi (2, ) ha terminato le istruzioni da eseguire. Restituisce il controllo al chiamante

147 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(3,A,N_a,C,N_c,B, N_b); A C through B Aveva invocato: hanoi (2, A, N_a, B, N_b, C, N_c); A B through C Questa invocazione ha ora ritornato Il controllo n_An_Bn_C

148 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(3,A,N_a,C,N_c,B, N_b); A C through B n_An_Bn_C Si esegue: c[n_C]=a[n_A-1]; n_A--; n_C++;

149 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(3,A,N_a,C,N_c,B, N_b); A C through B n_An_Bn_C Si esegue: c[n_C]=a[n_A-1]; n_A--; n_C++;

150 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(3,A,N_a,C,N_c,B, N_b); A C through B n_An_Bn_C Si esegue: c[n_C]=a[n_A-1]; n_A--; n_C++; Si invoca: hanoi (2, B, N_b, C, N_c, A, N_a); B C through A

151 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,B,N_b,C,N_c,A, N_a); B C through A n_An_Bn_C Si invoca: hanoi (1, B, N_b, A, N_a, C, N_c); B A through C

152 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,B,N_b,A,N_a,C, N_C); B A through C n_An_Bn_C

153 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,B,N_b,A,N_a,C, N_C); B A through C n_An_Bn_C Si restituisce il controllo al chiamante

154 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,B,N_b,C,N_c,A, N_a); B C through A Aveva invocato: hanoi (1, B, N_b, A, N_a, C, N_c); B A through C Tale invocazione ha terminato restituendo il controllo n_An_Bn_C Si esegue: c[n_C]=b[n_A-1]; n_B--; n_C++;

155 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(2,B,N_b,C,N_c,A, N_a); B C through A n_An_Bn_C Si esegue: c[n_C]=b[n_B-1]; n_B--; n_C++; Si invoca: hanoi (1, A, N_a, C, N_c, B, N_b); A C through B

156 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,A,N_a,C,N_c,B, N_c); A C through B n_An_Bn_C

157 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio hanoi(1,A,N_a,C,N_c,B, N_c); A C through B n_An_Bn_C Si restituisce il controllo al chiamante

158 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio B C through A n_An_Bn_C Si restituisce il controllo al chiamante hanoi(2,B,N_b,C,N_c,A, N_a);

159 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio A C through B n_An_Bn_C Si restituisce il controllo al chiamante hanoi(3,A,N_a,C,N_c,B, N_b);

160 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio A B through C n_An_Bn_C hanoi(4,A,&n_A,B,&n_B,C, &n_C); Si esegue: b[n_B]=a[n_A-1]; n_B++; n_A--;

161 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio A B through C n_An_Bn_C hanoi(4,A,&n_A,B,&n_B,C, &n_C); Si esegue: b[n_B]=a[n_A-1]; n_B++; n_A--; Si invoca hanoi(3,C,N_c,B,N_b,A,N_a);

162 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C B through A n_An_Bn_C hanoi(3,C,N_c,B,N_b,A,N_a); Si invoca hanoi(2,C,N_c,A,N_a,B,N_b);

163 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C A through B n_An_Bn_C hanoi(2,C,N_c,A,N_a,B,N_b); Si invoca hanoi(1,C,N_c,B,N_b,A,N_a);

164 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C B through A n_An_Bn_C hanoi(1,C,N_c,B,N_b,A,N_a);

165 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C B through A n_An_Bn_C hanoi(1,C,N_c,B,N_b,A,N_a); Si restituisce il controllo al chiamante

166 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C A through B n_An_Bn_C hanoi(2,C,N_c,A,N_a,B,N_b); Si esegue: a[n_A]=c[n_C-1]; n_A++; n_C--;

167 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C A through B n_An_Bn_C hanoi(2,C,N_c,A,N_a,B,N_b); Si esegue: a[n_A]=c[n_C-1]; n_A++; n_C--; Si invoca hanoi(1,B,N_b,A,N_a,C,N_c);

168 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio B A through C n_An_Bn_C hanoi(1,B,N_b,A,N_a,C,N_c);

169 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio B A through C n_An_Bn_C hanoi(1,B,N_b,A,N_a,C,N_c); Si restituisce il controllo al chiamante

170 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio C A through B n_An_Bn_C Si restituisce il controllo al chiamante hanoi(2,C,N_c,A,N_a,B,N_b);

171 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C C B through A hanoi(3,C,N_c,B,N_b,A,N_a); Si esegue: b[n_C]=c[n_C-1]; n_B++; n_C--;

172 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C C B through A hanoi(3,C,N_c,B,N_b,A,N_a); Si esegue: b[n_C]=c[n_C-1]; n_B++; n_C--; Si invoca hanoi(2,A,N_a,B,N_b,C,N_c);

173 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C A B through C hanoi(2,A,N_a,B,N_b,C,N_c); Si invoca hanoi(1,A,N_a,C,N_c,B,N_b);

174 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C A C through B hanoi(1,A,N_a,C,N_c,B,N_b);

175 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C A C through B hanoi(1,A,N_a,C,N_c,B,N_b); Si restituisce il controllo al chiamante

176 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C A B through C hanoi(2,A,N_a,B,N_b,C,N_c); Si esegue: b[n_C]=a[n_C-1]; n_B++; n_A--;

177 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C A B through C hanoi(2,A,N_a,B,N_b,C,N_c); Si esegue: b[n_C]=a[n_C-1]; n_B++; n_A--; Si invoca: hanoi(1,C,N_c,B,N_b,A,N_a);

178 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C C B through A hanoi(1,C,N_c,B,N_b,A,N_a);

179 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C C B through A hanoi(1,C,N_c,B,N_b,A,N_a); Si restituisce il controllo al chiamante

180 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C Si restituisce il controllo al chiamante A B through C hanoi(2,A,N_a,B,N_b,C,N_c);

181 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C Si restituisce il controllo al chiamante C B through A hanoi(3,C,N_c,B,N_b,A,N_a);

182 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Un esempio n_An_Bn_C Si restituisce il controllo al main Abbiamo correttamente spostato i dischi dal primo al secondo piolo A B through C hanoi(4,A,&n_A,B,&n_B,C, &n_C);

183 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizi di consolidamento delle conoscenze Cicli e costrutti annidati Lettura e scrittura da I/O e da file Vettori MatriciPuntatoriStringhe FunzioniRicorsioneStrutture e liste

184 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Calcolo del minimo comun divisore di due numeri Il massimo comune divisore (M.C.D.) di due numeri interi, che non siano entrambi uguali a zero, è il numero naturale più grande per il quale possono entrambi essere divisi. Algoritmo di Euclide: Dati due numeri naturali a e b, si controlla se b è zero. Se lo è, a è il MCD. Se non lo è, si divide a / b e si assegna ad r il resto della divisione (r=a%b). Se r = 0 allora si può terminare affermando che b è il MCD cercato altrimenti occorre assegnare a = b e b = r e si ripete nuovamente la divisione.

185 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Funzione ricorsiva per il calcolo di MCD int mcd(int a, int b) { if (b == 0) return a; else return mcd(b, a % b); }

186 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 1 Si scriva una funzione che dati due vettori ordinati di interi t1 e t2 e date le loro dimensioni d1 e d2 calcoli la loro intersezione (memorizzandola in un terzo vettore t3 dato in input). La funzione restituira la cardinalita dellinsieme intersezione.

187 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 1 int intersezione(int *t1, int d1, int *t2, int d2, int *t3) { int i,j,cnt; i=j=cnt=0; /* inzializzo i contatori */ while((i

188 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 2 Si scriva una funzione che dato un vettore ed una sua dimensione, inverta il vettore Si scriva una funzione che dato un vettore ed una sua dimensione, inverta il vettore

189 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 2 Versione iterativa esercizio 2

190 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 3 Si scriva una funzione ricorsiva che dato un vettore ed un intervallo di indici degli elementi del vettore [min,max] inverta la parte del vettore con indici in questo intervallo Si scriva una funzione ricorsiva che dato un vettore ed un intervallo di indici degli elementi del vettore [min,max] inverta la parte del vettore con indici in questo intervallo

191 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione ricorsiva esercizio 3

192 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 4 Si scriva una funzione ricorsiva che calcoli il massimo di un vettore

193 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 4

194 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 5 Si scriva una funzione ricorsiva che dato un vettore calcoli la somma dei suoi elementi

195 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 5

196 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizi di consolidamento delle conoscenze Cicli e costrutti annidati Lettura e scrittura da I/O e da file Vettori MatriciPuntatoriStringhe FunzioniRicorsioneStrutture e liste

197 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 1 Si scriva una funzione ricorsiva che data una stringa la stampi

198 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 1

199 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 2 Si scriva una funzione ricorsiva che data una stringa ne stampi i caratteri dallultimo al primo

200 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 2

201 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 3 Si scriva una funzione ricorsiva che data una stringa calcoli il numero dei suoi elementi (notazione vettore e indice)

202 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 3

203 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 5 Si scriva una funzione ricorsiva che data una stringa ed un carattere restituisce il puntatore alla prima occorrenza del carattere nella stringa, NULL se tale carattere non compare nella stringa

204 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 5

205 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 6 Si scriva una funzione ricorsiva che data una stringa ed un carattere restituisca il puntatore allultima occorrenza del carattere nella stringa

206 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 6

207 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Esercizio 4 Si scriva una funzione ricorsiva che calcoli il numero di caratteri di una stringa a partire da un determinato carattere della stringa (il puntatore a tale carattere iniziale viene fornito in input)

208 Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Soluzione esercizio 4


Scaricare ppt "Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli."

Presentazioni simili


Annunci Google