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
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*/
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
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
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
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
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
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Esempio
Precedenza degli operatori
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..
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
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria…
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria…
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria…
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
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Cosa succede in memoria… int number=5;cubeByReference(&number); 5 number 6200
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
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
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 è
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
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
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
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
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
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
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;
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
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; }
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]);}
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;}
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
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]?
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
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
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
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
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
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
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';}
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); }
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.
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); }
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
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
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
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
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Codice #include<stdio.h>#include<stdlib.h>#include<time.h> void shuffle(int wDeck[ ][13]); void deal(const int wDeck[ ][13], const char *wFace[ ], const char *wsuit[ ]);
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
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; }}
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
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
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?
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
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Bubblesort#include<stdio.h> #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
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<SIZE;counter++){ printf(%d,a[counter]);}if(order==1){bubble(a,SIZE,ascending);}else{bubble(a,SIZE,descending);} for (counter=0,counter<SIZE; counter++){ printf(%d,a[counter]);} return 0; } puntatore a funzione
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<size;pass++){ for (count=0;count<size-1;count++){ if ((*compare)(work[count],work[count+1])){ swap(&work[count],&work[count+1]);}}}} compare è un puntatore ad una funzione che prende due parametri interi e restituisce un intero int (*) (int,int); un puntatore a funzione è dereferenziato per usare la funzione Invoca la funzione puntata da compare con parametri work[count] e work[count+1]
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 b<a; } int descending(int a,int b) { return b>a; } 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<SIZE;counter++){ printf(%d,a[counter]);}if(order==1){bubble(a,SIZE,ascending);}else{bubble(a,SIZE,descending);}
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.
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010Codice#include<stdio.h> 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
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); }
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Argomenti avanzati sulle funzioni… Classi di memoria Regole di scope
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 una variabile 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 alla variabile) 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/PROG2
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 di 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
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;
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)
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à
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
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); }
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
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); }
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); }
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
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
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
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
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
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
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
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.
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
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
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
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
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
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)
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)
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)
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)
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 TUTTAVIA ragionare in modo ricorsivo è molto utile e vedrete di qui a poco (PROG2) 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
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
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
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<b, come posso usarlo per calcolare a+b a+b=(a+b-1)+1 a+b=(a+b-1)+1 Calcolato dallinvocazione della funzione su a e b-1 Caso base: se b==0, a+b=a
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)
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
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
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
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)
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)
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*1=aa*0=0 b volte
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; if (b==1) return a; else return (prodotto(a,b-1)+a); }
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
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); }
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.)
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)
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)
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)
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
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
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
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)
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
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
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
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!
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
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
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
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
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
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
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
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice #include<stdio.h> 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<n;i++) A[i]=i+1;n_A=n; hanoi (n,A,&n_A, B, &n_B, C, &n_C); return 0; } I vettori A, B, C conterranno i dischi (ed il loro ordine) impilati nei pioli A,B, e C Dato un vettore A, n_A indicherà il numero di dischi impilati in A (memorizzati nelle locazioni di memoria 0,…,n_A-1) n_A sarà quindi anche lindice della prossima posizione libera del vettore Numero di dischiVettore che rappresenta il primo piolo Puntatore alla prima locazione libera relativa al primo piolo
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice #include<stdio.h> 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<n;i++) A[i]=i+1;n_A=n; hanoi (n,A,&n_A, B, &n_B, C, &n_C); return 0; } I dischi hanno associato un indice da 1,..,n I dischi più grandi avranno associato un indice più piccolo Se il primo piolo contiene I dischi in figura il corrispettivo vettore A conterrà nelle prime n_A=4 posizioni i valori 1,2,3, A n_A
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Torri di Hanoi-Codice #include<stdio.h> 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<n;i++) A[i]=i+1;n_A=n; hanoi (n,A,&n_A, B, &n_B, C, &n_C); return 0; } Inizializza i vettori A, B e C a zero n_A,n_B,n_C a zero (i vettori non hanno elementi memorizzati) Prende da input un numero valido di dischi n Mette in A i vari dischi dal più grande al più piccolo (situazione quando si comincia a spostare da A a B i dischi). Si aggiorna coerentemente n_A. Si invoca la funzione hanoi il cui Compito sarà spostare n dischi da A a B seguendo le regole per il movimento dei dischi e mantenendo aggiornate le informazioni sul contenuto e num. Di elementi del vettore
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); }}
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
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
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
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
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
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++;
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++;
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
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
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
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
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++;
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++;
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
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
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
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
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++;
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
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
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
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);
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);
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--;
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);
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);
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);
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);
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
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--;
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);
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);
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
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);
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--;
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);
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);
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);
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
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--;
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);
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);
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
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);
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);
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);