Prof.ssa Chiara Petrioli -- Prof.ssa Chiara Petrioli -- corso di programmazione 1, corso di programmazione 1, a.a. 2006/2007 a.a. 2006/2007 Corso di Corso di Programmazione 1 Programmazione 1 a.a.2007/2008 a.a.2007/2008 Prof.ssa Chiara Petrioli Prof.ssa Chiara Petrioli Corso di Laurea in Corso di Laurea in Informatica Informatica Università degli Studi “La Università degli Studi “La Sapienza” Sapienza” (lezioni 12-15) (lezioni 12-15) Puntatori e ricorsione
192
Embed
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2007/2008 Prof.ssa Chiara Petrioli Corso di Laurea.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Corso di Programmazione 1Corso di Programmazione 1a.a.2007/2008a.a.2007/2008Prof.ssa Chiara PetrioliProf.ssa Chiara Petrioli
Corso di Laurea in InformaticaCorso di Laurea in InformaticaUniversità degli Studi “La Sapienza”Università degli Studi “La Sapienza”
(lezioni 12-15)(lezioni 12-15)Puntatori e ricorsione
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Aritmetica dei puntatoriAritmetica dei puntatori
I puntatori sono degli operandi validi per le I puntatori sono degli operandi validi per le espressioni aritmetiche (insieme limitato di espressioni aritmetiche (insieme limitato di operatori aritmetici possono essere applicati a operatori aritmetici possono essere applicati a puntatori), le espressioni di assegnamento e le puntatori), le espressioni di assegnamento e le espressioni di confronto espressioni di confronto – un puntatore potrà essere incrementato e un puntatore potrà essere incrementato e
decrementato con gli operatori ++ o --, ad un decrementato con gli operatori ++ o --, ad un puntatore potrà essere sommato o sottratto un intero puntatore potrà essere sommato o sottratto un intero (operatori +, -,-=, +=). Infine ad un puntatore potrà (operatori +, -,-=, +=). Infine ad un puntatore potrà essere sottratto un secondo puntatore.essere sottratto un secondo puntatore.
Devono però essere puntatori allo stesso tipo di dato
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Aritmetica dei puntatori per operare Aritmetica dei puntatori per operare sui vettorisui vettori
int i;int i;
int v[100];int v[100];
int * vPtr;int * vPtr;
for (i=0; i<100;i++)for (i=0; i<100;i++)
v[i]=i;v[i]=i;
vPtr=&v[0];vPtr=&v[0];
00 11 22 …… 9898 9999 v
3000
3000 vPtr
vPtr poteva anche essere inizializzatoScrivendo vPtr=v;
In quale locazione di memoria si trova v[1]? Ed il generico elemento v[i]?
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Operatore sizeofOperatore sizeofsizeof(nome_di variabile o sizeof(nome_di variabile o tipo di datotipo di dato o costante) o costante)È l’operatore che consente di determinare quante celle di È l’operatore che consente di determinare quante celle di
memoria sono associate ad un certo tipo di dato memoria sono associate ad un certo tipo di dato printf(“sizeof(char)=%d\n”printf(“sizeof(char)=%d\n”
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Aritmetica dei puntatori per operare Aritmetica dei puntatori per operare sui vettorisui vettori
int i;int i;
int v[100];int v[100];
for (i=0; i<100;i++)for (i=0; i<100;i++)
v[i]=i;v[i]=i;
vPtr=&v[0];vPtr=&v[0];
00 11 22 …… 9898 9999 v
3000
3000 vPtr
Supponendo che il numero di celle associate ad unIntero sia 2…
vPtr+=2 fa puntare vPtr a v[2]
3004
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Aritmetica dei puntatori per operare Aritmetica dei puntatori per operare sui vettorisui vettori
int i;int i;
int v[100];int v[100];
for (i=0; i<100;i++)for (i=0; i<100;i++)
v[i]=i;v[i]=i;
vPtr=&v[0];vPtr=&v[0];
00 11 22 …… 9898 9999 v
3000
3004 vPtr
Supponendo che il numero di celle associate ad unIntero 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 decrementatadi una quantità di celle pari a quelle che servono per memorizzareil tipo di dato in modo da far puntare all’elemento precedentedel vettore
3002
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Aritmetica dei puntatori per operare Aritmetica dei puntatori per operare sui vettorisui vettoriint i;int i;
int v[100];int v[100];
int *vPtr;int *vPtr;
int *vPtr2;int *vPtr2;
for (i=0; i<100;i++)for (i=0; i<100;i++)
v[i]=i;v[i]=i;
vPtr=&v[0];vPtr=&v[0];
vPtr2=&v[99];vPtr2=&v[99];
00 11 22 …… 9898 9999 v
3000
3000 vPtr
Supponendo che il numero di celle associate ad unIntero sia 2…
x=vPtr2-vPtr;Assegna ad x il numero di elementi del vettore compresitra l’elemento puntato da vPtr2 e vPtr (infatti il valore delle differenza viene normalizzato al numero di celle necessarieper contenere un intero)in questo caso 99
3198 vPtr2
L’aritmetica dei puntatori ha senso con gli elementi di un vettore altrimentiNon si può assumere che variabili dello stesso tipo siano immagazzinate incelle consecutive di memoria
Un confronto tra puntatoriha senso solo per puntatoriche puntano ad elementidiversi dello stesso vettoree può ad esempio essereusato per controllare qualedei due elementi puntati haIndice maggiore
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Puntatori e vettoriPuntatori e vettori
00 11 22 …… 9898 9999 v
3000
3000 vPtr
v==&v[0]Se vPtr==vv[4] e *(vPtr+4) sono due notazioni equivalenti per far riferimento al valore del quinto elemento del vettore
notazione conpuntatore e offset
Attenzione: il nome del vettore è un puntatore costante punterà sempre allaPrima posizione del vettore, non può essere modificato
vPtr[4] e *(vPtr+4)sono anche notazioniequivalenti
notazione con puntatore e indice
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempioUn esempio#include <stdio.h>#include <stdio.h>main()main(){{
int i, offset, b[ ]={10,20,30,40};int i, offset, b[ ]={10,20,30,40};int *bPtr=b;int *bPtr=b;printf(“stampa del vettore con notazione con indici”);printf(“stampa del vettore con notazione con indici”);for (i=0;i<=3;i++)for (i=0;i<=3;i++)
printf(“b[%d]=%d\n”,i,b[i]);printf(“b[%d]=%d\n”,i,b[i]);printf(“stampa del vettore con notazione con puntatore e printf(“stampa del vettore con notazione con puntatore e offset”);offset”);for (offset=0;offset<=3;offset++)for (offset=0;offset<=3;offset++)
printf(“*(bPtr+%d)=%d\n”,offset,*(bPtr+offset));printf(“*(bPtr+%d)=%d\n”,offset,*(bPtr+offset));printf(“stampa del vettore con notazione con puntatore e printf(“stampa del vettore con notazione con puntatore e indice”);indice”);for (i=0;i<=3;i++)for (i=0;i<=3;i++)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Alcuni esercizi sulle stringhe…Alcuni esercizi sulle stringhe…
Si scriva una funzione che copia la stringa s2 nel vettore Si scriva una funzione che copia la stringa s2 nel vettore s1. s1.
/*Pre: dim del vettore s1 sufficienti per contenere s2*//*Pre: dim del vettore s1 sufficienti per contenere s2*//*Post: s1 contiene la stringa s2*//*Post: s1 contiene la stringa s2*/void stringcopy(char *s1, char *s2)void stringcopy(char *s1, char *s2){{
for (;*s2 !='\0';s1++,s2++)for (;*s2 !='\0';s1++,s2++)*s1=*s2;*s1=*s2;
*s1='\0';*s1='\0';}}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Alcuni esercizi sulle stringhe…Alcuni esercizi sulle stringhe…/*Post: confronta s1 e s2. Restituisce -1 se s1 e' minore in ordine /*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 lessicografico di s2, 0 se sono uguali ,1 se s1 e' maggiore in ordine lessicografico di s2 */ordine lessicografico di s2 */
int stringcmp(char *s1, char *s2)int stringcmp(char *s1, char *s2){{
while (*s1==*s2)while (*s1==*s2){{
if (*s1=='\0')if (*s1=='\0')return 0;return 0;
s1++;s1++;s2++;s2++;
}}if (*s1 == '\0')if (*s1 == '\0')
return -1;return -1;else if (*s2 == '\0')else if (*s2 == '\0')
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1, Compito BEsercizio 1, Compito B
Si scriva una funzione che dato un vettore Si scriva una funzione che dato un vettore di interi ORDINATO calcoli il numero di di interi ORDINATO calcoli il numero di valori che compaiono ripetuti almeno una valori che compaiono ripetuti almeno una volta nel vettore volta nel vettore
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Soluzioni compito BSoluzioni compito B/* conta il numero di elementi del vettore che vengono ripetuti *//* conta il numero di elementi del vettore che vengono ripetuti */int numRipetizioni (int vett[ ], int n) { int numRipetizioni (int vett[ ], int n) {
int check;int check;int done = 0;int done = 0;int count = 0;int count = 0;int i = 0;int i = 0;check = vett[0];check = vett[0];for (i = 1; i < n; i++) {for (i = 1; i < n; i++) {
if (check == vett[i]) { if (check == vett[i]) { if(done == 0) {if(done == 0) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 2, compito DEsercizio 2, compito D
Denominiamo un elemento di una matrice Denominiamo un elemento di una matrice di interi n*m un minimo diagonale se è di interi n*m un minimo diagonale se è l’elemento con il valore (strettamente) l’elemento con il valore (strettamente) minore tra quelli delle (due) diagonali a cui minore tra quelli delle (due) diagonali a cui appartiene. appartiene. Si scriva una funzione che data una Si scriva una funzione che data una matrice di interi ed un intero h calcoli il matrice di interi ed un intero h calcoli il numero dei suoi minimi diagonali con numero dei suoi minimi diagonali con valore > h valore > h
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Soluzione esercizioSoluzione esercizioint minimoDiagonale2(int righe, int colonne, int matrix[][colonne], int h) {int minimoDiagonale2(int righe, int colonne, int matrix[][colonne], int h) {
int k, i ,j ;int k, i ,j ;int count = 0;int count = 0;for (i = 0; i < righe; i++) {for (i = 0; i < righe; i++) {
for (j = 0; j < righe; j++) {for (j = 0; j < righe; j++) {if (matrix[i][j] > h) {if (matrix[i][j] > h) { if (controlloDiagonale1(colonne, i, j, matrix) && if (controlloDiagonale1(colonne, i, j, matrix) && controlloDiagonale2(colonne, i, j, matrix) &&controlloDiagonale2(colonne, i, j, matrix) && controlloDiagonale3(righe, colonne, i, j, matrix) &&controlloDiagonale3(righe, colonne, i, j, matrix) && controlloDiagonale4(righe, colonne, i, j, matrix)) {controlloDiagonale4(righe, colonne, i, j, matrix)) {
count++;count++;}}
}}}}
}}return count;return count;
}}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Sol esercizio 2 compito DSol esercizio 2 compito Dint controlloDiagonale1(int num_colonne, int indice_riga, int int controlloDiagonale1(int num_colonne, int indice_riga, int
indice_colonna, int matrix[][num_colonne]) {indice_colonna, int matrix[][num_colonne]) {int valore = matrix[indice_riga][indice_colonna];int valore = matrix[indice_riga][indice_colonna];indice_riga--;indice_riga--;indice_colonna++;indice_colonna++;while (indice_riga >= 0 && indice_colonna < num_colonne) {while (indice_riga >= 0 && indice_colonna < num_colonne) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Sol esercizio 2 compito DSol esercizio 2 compito Dint controlloDiagonale2(int num_colonne, int indice_riga, int int controlloDiagonale2(int num_colonne, int indice_riga, int
indice_colonna, int matrix[][num_colonne]) {indice_colonna, int matrix[][num_colonne]) {int valore = matrix[indice_riga][indice_colonna];int valore = matrix[indice_riga][indice_colonna];indice_riga--;indice_riga--;indice_colonna--;indice_colonna--;while (indice_riga >= 0 && indice_colonna >= 0) {while (indice_riga >= 0 && indice_colonna >= 0) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Sol esercizio 2 compito DSol esercizio 2 compito Dint controlloDiagonale3(int num_righe, int num_colonne, int indice_riga, int controlloDiagonale3(int num_righe, int num_colonne, int indice_riga,
int indice_colonna, int matrix[][num_colonne]) {int indice_colonna, int matrix[][num_colonne]) {int valore = matrix[indice_riga][indice_colonna];int valore = matrix[indice_riga][indice_colonna];indice_riga++;indice_riga++;indice_colonna--;indice_colonna--;while (indice_riga < num_righe && indice_colonna >= 0) {while (indice_riga < num_righe && indice_colonna >= 0) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Sol esonero 2 compito DSol esonero 2 compito D
int controlloDiagonale4(int num_righe, int num_colonne, int indice_riga, int int controlloDiagonale4(int num_righe, int num_colonne, int indice_riga, int indice_colonna, int matrix[][num_colonne]) {indice_colonna, int matrix[][num_colonne]) {int valore = matrix[indice_riga][indice_colonna];int valore = matrix[indice_riga][indice_colonna];indice_riga++;indice_riga++;indice_colonna++;indice_colonna++;while (indice_riga < num_righe && indice_colonna < num_colonne) {while (indice_riga < num_righe && indice_colonna < num_colonne) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 2 compito BEsercizio 2 compito B
Denominiamo un elemento di una matrice Denominiamo un elemento di una matrice di interi n*m un massimo diagonale se è di interi n*m un massimo diagonale se è l’elemento con il valore (strettamente) l’elemento con il valore (strettamente) maggiore tra quelli delle (due) diagonali a maggiore tra quelli delle (due) diagonali a cui appartiene. cui appartiene.
Si scriva una funzione che data una Si scriva una funzione che data una matrice di interi calcoli il numero dei suoi matrice di interi calcoli il numero dei suoi massimi diagonali. massimi diagonali.
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
EsempioEsempio
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Compito B, secondo esercizioCompito B, secondo esercizioint massimoDiagonale(int righe, int colonne, int matrix[][colonne]) {int massimoDiagonale(int righe, int colonne, int matrix[][colonne]) {
int k, i ,j ;int k, i ,j ;int count = 0;int count = 0;/*scorre le diagonali che partono da (i, 0) con "i" indice di riga e controlla/*scorre le diagonali che partono da (i, 0) con "i" indice di riga e controllase tale diagonale contiene un massimo diagonale. In caso affermativo se tale diagonale contiene un massimo diagonale. In caso affermativo aumenta il contatore*/aumenta il contatore*/for (k = 0; k < righe; k++) {for (k = 0; k < righe; k++) {
count += esisteMassimoDiagonale(righe, colonne, k, 0, matrix);count += esisteMassimoDiagonale(righe, colonne, k, 0, matrix);}}/*scorre le diagonali che partono da (0, j) con "j" indice di colonna /*scorre le diagonali che partono da (0, j) con "j" indice di colonna (j > 0 perché tale caso è già stato controllato nel for precedente) e (j > 0 perché tale caso è già stato controllato nel for precedente) e controlla se tale diagonale contiene un massimo diagonale. In caso controlla se tale diagonale contiene un massimo diagonale. In caso affermativo affermativo aumenta il contatore*/aumenta il contatore*/for (k = 1; k < colonne; k++) {for (k = 1; k < colonne; k++) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Compito B, secondo esercizioCompito B, secondo esercizioint esisteMassimoDiagonale(int num_righe, int num_colonne, int indice_riga, int indice_colonna, int esisteMassimoDiagonale(int num_righe, int num_colonne, int indice_riga, int indice_colonna,
int matrix[ ][num_colonne])int matrix[ ][num_colonne]){{
Prende da input un testo e lo memorizza in unastringa
Calcola la lunghezza della stringa Contenente il testo
Stampa in ordine invertito le paroleche sono di al massimo k caratteriA mano a mano che legge una parolaLa mette in un vettore di appoggio parola
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Soluzioni compito DSoluzioni compito D
Esercizio 1, compito DEsercizio 1, compito D
Si scriva una funzione che dato un vettore Si scriva una funzione che dato un vettore di interi verifichi se è vero che ogni di interi verifichi se è vero che ogni elemento del vettore contenente un valore elemento del vettore contenente un valore dispari abbia un valore maggiore alla dispari abbia un valore maggiore alla somma degli elementi successivi.somma degli elementi successivi.
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1, compito DEsercizio 1, compito D
int dispariMaggiore (int vett[], int n) {int dispariMaggiore (int vett[], int n) {int somma = vett[n-1]; int somma = vett[n-1]; int i;int i;for (i = n-2; i >= 0; i--) {for (i = n-2; i >= 0; i--) {
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 3, compito DEsercizio 3, compito D
Si scriva una funzione che prenda da input Si scriva una funzione che prenda da input una stringa di testo composto da una stringa di testo composto da sequenze di caratteri divise da spazi e sequenze di caratteri divise da spazi e ritorni a capo. La funzione stampa i ritorni a capo. La funzione stampa i caratteri del testo in ordine invertito dopo caratteri del testo in ordine invertito dopo aver cancellato le sequenze di caratteri del aver cancellato le sequenze di caratteri del testo che contengono cifre.testo che contengono cifre.Vediamo la variante in cui invece il testo Vediamo la variante in cui invece il testo sia dato in una stringasia dato in una stringa
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
/*Pre: stringa di testo contenente soloCaratteri alfanumerici, spazi e newline*/
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Alcuni esercizi sulle stringheAlcuni esercizi sulle stringhesi scriva una funzione che, date due stringhe, si scriva una funzione che, date due stringhe,
restituisce 1 se la prima stringa compare restituisce 1 se la prima stringa compare come sottostringa della seconda, 0 altrimenti. come sottostringa della seconda, 0 altrimenti. Se la prima stringa e' vuota restituisce 1 (una Se la prima stringa e' vuota restituisce 1 (una stringa vuota e' sottostringa di q.siasi stringa. stringa vuota e' sottostringa di q.siasi stringa. Se la seconda stringa e' vuota e la prima no Se la seconda stringa e' vuota e la prima no allora restituisce 0.allora restituisce 0.
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Alcuni esercizi sulle stringheAlcuni esercizi sulle stringheint findstr (char *s1, char *s2)int findstr (char *s1, char *s2){{
Gli elementi di suit sonopuntatori allaposizione dove è memorizzatoil primo carattere di ciascunastringaciascuno punta in manieraStabile ad una determinata stringa
La memoria allocata per suit è quella necessaria per contenere4 puntatoriCiascuna stringa ha poi allocata memoria separatamente perContenerne i caratteri incluso quello di fine stringa
6200
3100
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Vettori di puntatoriVettori di puntatoriI vettori possono contenere elementi di tipo puntatoreI vettori possono contenere elementi di tipo puntatore
Esempio: array di stringheEsempio: array di stringhe
Non si poteva usare una matrice di caratteri?Si MA l’uso di vettori di puntatori a caratteri fa risparmiare memoriaPer ogni stringaSi alloca la memoria sufficiente a memorizzare la stringaNON la memoria necessaria a memorizzare la stringa più lunga
6200
3100
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempioUn esempio
Si scriva un programma che mescoli un mazzo di Si scriva un programma che mescoli un mazzo di carte, stampando l’ordine delle carte ottenutocarte, stampando l’ordine delle carte ottenuto
Cuori
Quadri
Picche
Fiori
0
1
2
3
0 1 10 11 129
Ass
o
Du
e
Die
ci
Fan
te
Do
nn
a
Re
mazzo_carte
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
PseudocodicePseudocodiceInizializza la matrice mazzo_carte a 0Inizializza la matrice mazzo_carte a 0Inizializza una variabile contatore k a 1Inizializza una variabile contatore k a 1Fino a quando non è stato assegnato un Fino a quando non è stato assegnato un ordine a ciascuna carta (52 iterazioni)ordine a ciascuna carta (52 iterazioni)– Scegli la prossima cartaScegli la prossima carta
Scegli casualmente una riga iScegli casualmente una riga iScegli casualmente una colonna j Scegli casualmente una colonna j Se mazzo_carte[i][j] è diverso da zero scegli una Se mazzo_carte[i][j] è diverso da zero scegli una nuova riga e colonna, ALTRIMENTI mazzo_carte[i]nuova riga e colonna, ALTRIMENTI mazzo_carte[i][j]=k[j]=kincrementa kincrementa k
Stampa una a una le carte nell’ordine Stampa una a una le carte nell’ordine selezionatoselezionato
Critico …potrei avere lunghe attese(attesa ‘infinita’) prima di trovare una posizione libera. Come potrei risolvereil problema? Posso scegliere casualmentesolo tra le posizioni non ancora riempite per esercizio
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
for (i=0;i<=3;i++){for (i=0;i<=3;i++){for (j=0;j<=12;j++){for (j=0;j<=12;j++){
if (wDeck[i][j]==k){if (wDeck[i][j]==k){printf(“%s di %s\n”,wFace[j],wSuit[i]);printf(“%s di %s\n”,wFace[j],wSuit[i]);}}
}}}}
}}
} }
Quattro di QuadriFante di FioriRe di Picche---
Scandiamo sempre tutta la matriceanche quando abbiamo trovato l’elemento che corrisponde allak-esima cartainefficiente. Qualche idea su comeevitare questo problema?
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Puntatori a funzioniPuntatori a funzioni
Un nome di funzione indica l’indirizzo di Un nome di funzione indica l’indirizzo di memoria in cui è memorizzata la prima memoria in cui è memorizzata la prima istruzione della funzioneistruzione della funzione
Esempio di uso:Esempio di uso:
una versione del bubblesort che consenta una versione del bubblesort che consenta di inserire da input se il vettore deve di inserire da input se il vettore deve essere ordinato in ordine crescente o essere ordinato in ordine crescente o decrescentedecrescente
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
BubblesortBubblesort
#include<stdio.h>#include<stdio.h>
#define SIZE 10#define SIZE 10
void bubble(int work[ ], const int size, void bubble(int work[ ], const int size,
int (*compare)(int a,int b));int (*compare)(int a,int b));
int ascending(int a, int b);int ascending(int a, int b);
int descending(int a,int b);int descending(int a,int b);
Puntatore ad una funzioneche prende come parametridue interi e restituisce uninteroCompare è un puntatore a funzione
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
BubblesortBubblesortint main()int main(){{
int order; /* 1 per ordine crescente, 2 per decrescente*/int order; /* 1 per ordine crescente, 2 per decrescente*/int counter;int counter;int a[SIZE]={2,6,4,8,10,12,89,68,45,37};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 printf(“si inserisca 1 per ordinare in ordine crescente, 2 per un ordinamento decrescente del vettore \n”);decrescente del vettore \n”);scanf(“%d”, &order);scanf(“%d”, &order);printf(“dati nell’ordine originale \n”);printf(“dati nell’ordine originale \n”);for (counter=0;counter<SIZE;counter++){for (counter=0;counter<SIZE;counter++){
for (count=0;count<size-1;count++){for (count=0;count<size-1;count++){if ((*compare)(work[count],work[count+1])){if ((*compare)(work[count],work[count+1])){
compare è unpuntatore ad unafunzione che prendedue parametri interi e restituisce un intero
int (*) (int,int);
un puntatore a funzione è dereferenziato perusare la funzioneInvoca la funzione puntata da compare conparametri work[count] e work[count+1]
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Swap, ascending, descendingSwap, ascending, descendingvoid swap(int *element1Ptr, int *element2Ptr)void swap(int *element1Ptr, int *element2Ptr){{
int hold;int hold;hold=*element1Ptr;hold=*element1Ptr;*element1Ptr=*element2Ptr;*element1Ptr=*element2Ptr;*element2Ptr=hold;*element2Ptr=hold;
}}/*ritorna 1 se non si segue l’ordinamento crescente*/ /*ritorna 1 se non si segue l’ordinamento crescente*/ int ascending(int a,int b)int ascending(int a,int b){{
A seconda che si voglia ordinarein ordine crescente o decrescenteoccorre testare due condizionidiverse per verificare se due elementiconsecutivi sono ordinati correttamenteo meno
printf(“si inserisca 1 per ordinare in ordine printf(“si inserisca 1 per ordinare in ordine crescente, 2 per un ordinamento decrescente crescente, 2 per un ordinamento decrescente del vettore \n”);del vettore \n”);scanf(“%d”, &order);scanf(“%d”, &order);printf(“dati nell’ordine originale \n”);printf(“dati nell’ordine originale \n”);for (counter=0;counter<SIZE;counter++){for (counter=0;counter<SIZE;counter++){
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Puntatori a funzione Puntatori a funzione (secondo esempio)(secondo esempio)
Un utente seleziona un’opzione da un menu. Un utente seleziona un’opzione da un menu. Ciascuna opzione è servita da una Ciascuna opzione è servita da una funzione differente.funzione differente.
I diversi puntatori a funzione sono I diversi puntatori a funzione sono memorizzati in un array di puntatori a memorizzati in un array di puntatori a funzione. La scelta dell’utente fornisce funzione. La scelta dell’utente fornisce l’indice del vettore. Il puntatore a funzione l’indice del vettore. Il puntatore a funzione è usato per invocare la funzione opportuna è usato per invocare la funzione opportuna in base alla scelta dell’utente.in base alla scelta dell’utente.
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
void (*f[3])(int)={function1,function2,function3};void (*f[3])(int)={function1,function2,function3};int choice,i;int choice,i;printf(“inserisci la scelta della funzione da invocare: 0, 1, 2 a seconda che 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 vogliate moltiplicare per uno, due o tre il valore inserito. Inserire il valore 3 per terminare l’esecuzione”);terminare l’esecuzione”);scanf(“%d”,&choice);scanf(“%d”,&choice);printf(“inserisci intero \n”);printf(“inserisci intero \n”);scanf(“%d”,&i);scanf(“%d”,&i);while(choice>=0 && choice <3){while(choice>=0 && choice <3){
(*f[choice])(i);(*f[choice])(i);printf(“inserisci la scelta della funzione da invocare: 0, 1, 2 a seconda che 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 vogliate moltiplicare per uno, due o tre il valore inserito. Inserire il valore 3 per terminare l’esecuzione”);terminare l’esecuzione”);scanf(“%d”, &choice);scanf(“%d”, &choice);printf(“inserisci intero \n”);printf(“inserisci intero \n”);scanf(“%d”,&i);scanf(“%d”,&i);}}return 0;return 0;
}}
inizializza un arraydi tre puntatori a funzioneQueste funzioni prendonoin input un intero e nonrestituiscono valori
invoca la funzione puntatada f[choice] sul valore interoinserito da input i
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Codice delle tre funzioni…Codice delle tre funzioni…
void function1(int a)void function1(int a){{
printf(“il valore di a moltiplicato per uno è %d\n”,a*1);printf(“il valore di a moltiplicato per uno è %d\n”,a*1);}}void function2(int a)void function2(int a){{
printf(“il valore di a moltiplicato per due è %d\n”,a*2);printf(“il valore di a moltiplicato per due è %d\n”,a*2);}}void function3(int a)void function3(int a){{
printf(“il valore di a moltiplicato per tre è %d\n”,a*3);printf(“il valore di a moltiplicato per tre è %d\n”,a*3);}}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Argomenti avanzati sulle funzioni…Argomenti avanzati sulle funzioni…
Classi di memoriaClassi di memoria
Regole di scopeRegole di scope
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Classi di memoriaClassi di memoriaUna variabile ha associato un tipo, un nome, una Una variabile ha associato un tipo, un nome, una dimensione ed un valoredimensione ed un valoreAltri attributi di una variabile sono Altri attributi di una variabile sono
la sua classe di memoriala sua classe di memoria– autoauto– registerregister– externextern– staticstatic
il periodo durante il quale l’identificatore ha associata memoria il periodo durante il quale l’identificatore ha associata memoria (storage duration)(storage duration)lo scope (in quali parti del programma si può far riferimento alla lo scope (in quali parti del programma si può far riferimento alla variabile)variabile)linkage (se il programma è suddiviso in più file se l’identificatore linkage (se il programma è suddiviso in più file se l’identificatore può essere usato solo in questo file oppure in altri file previa può essere usato solo in questo file oppure in altri file previa opportune dichiarazioni)opportune dichiarazioni)
ARGOMENTO CHE TRATTERETE AD ESERCITAZIONE/PROG2ARGOMENTO CHE TRATTERETE AD ESERCITAZIONE/PROG2
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Le variabili di tipo auto o register permangono in memoria Le variabili di tipo auto o register permangono in memoria fino a quando è attivo il blocco di istruzioni all’interno fino a quando è attivo il blocco di istruzioni all’interno del quale la variabile è definitadel quale la variabile è definita
Le variabili locali alle funzioni sono tipicamente di tipo Le variabili locali alle funzioni sono tipicamente di tipo auto (è la loro classe di memoria di default)auto (è la loro classe di memoria di default)
Se una variabile è di tipo register si suggerisce che venga Se una variabile è di tipo register si suggerisce che venga memorizzata in un registromemorizzata in un registro
I compilatori sanno ottimizzare l’uso dei registri meglio I compilatori sanno ottimizzare l’uso dei registri meglio di un programmatoredi un programmatore
possono decidere di ignorare la richiesta di mettere in possono decidere di ignorare la richiesta di mettere in un registro una variabileun registro una variabile
Le variabili visteFinora erano implicitamente dichiaratecome autoSe dichiarateall’inizio del mainè loro allocatamemoria fino all’uscita dalprogrammase dichiarateall’inizio di unafunzione la variabileha allocata memoriafino a quando non si esce dallafunzione
register int counter=1;dice che la variabileintera counter dovrebbeessere memorizzata in unregistro e inizializzata a 1
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Static storage durationStatic storage durationLe parole chiaveLe parole chiave
externextern staticstatic
sono usate per identificare variabili e funzioni di tipo static storagesono usate per identificare variabili e funzioni di tipo static storageMemoria è allocata una volta per tutte e le variabili sono Memoria è allocata una volta per tutte e le variabili sono
inizializzate all’inizio del programma. Tale memoria è inizializzate all’inizio del programma. Tale memoria è disponibile per l’intera durata del programmadisponibile per l’intera durata del programma
Le variabili globali sono di tipo extern per default. Sono dichiarate Le variabili globali sono di tipo extern per default. Sono dichiarate fuori da ogni funzione e mantengono memoria a loro allocata fuori da ogni funzione e mantengono memoria a loro allocata durante l’intera durata del programma. Possono essere riferite durante l’intera durata del programma. Possono essere riferite da una qualsiasi funzione che segue la loro dichiarazione.da una qualsiasi funzione che segue la loro dichiarazione.
Le variabili di tipo static invece sono note solo all’interno della Le variabili di tipo static invece sono note solo all’interno della funzione dove sono definite. Tuttavia quando si esce dalla funzione dove sono definite. Tuttavia quando si esce dalla funzione si continua a memorizzare il loro valore. La prossima funzione si continua a memorizzare il loro valore. La prossima volta che si invoca la funzione la variabile locale static avrà volta che si invoca la funzione la variabile locale static avrà come valore quello che aveva alla fine della precedente come valore quello che aveva alla fine della precedente invocazione.invocazione.
static int count=1;
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Regole di scopeRegole di scope
Lo scope di un identificatore è la porzione Lo scope di un identificatore è la porzione del programma all’interno della quale si del programma all’interno della quale si può fare riferimento all’identificatorepuò fare riferimento all’identificatore– function scopefunction scope– file scopefile scope– block scopeblock scope– function-prototype scopefunction-prototype scope
etichetteusate nel costruttoswitchpossono essereusate solo all’internodella funzione nellaquale compaiono(e possono essereriferite in qualsiasipunto della funzione)
Un identificatore dichiarato all’esterno di ognifunzione ha uno scope di tipo file scopePossono essere riferite in qualsiasi puntoall’interno del file a partire dal punto in cuil’identificatore è dichiaratoEsempi: variabili globali, definizioni di funzioni,prototipi)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Regole di scopeRegole di scope
Lo scope di un identificatore è la porzione Lo scope di un identificatore è la porzione del programma all’interno della quale si del programma all’interno della quale si può fare riferimento all’identificatorepuò fare riferimento all’identificatore– function scopefunction scope– file scopefile scope– block scopeblock scope– function-prototype scopefunction-prototype scope
Identificatori block scope possono essereriferiti all’interno delBlocco in cui sono dichiarateIl blocco è delimitato da {}Variabili static hanno uno scopedi bloccoVariabili locali ad una funzionehanno scope di bloccoGli unici identificatori di tipo function prototype scope sono quelli
usati nella lista dei parametri di un prototipo di funzione. Dato chetali nomi, se usati, sono ignorati dal compilatore, hanno valoresolo all’interno del prototipo. Gli stessi identificatori possono essere riutilizzati in altre parti del programma senza problemi di ambiguità
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
Se lo stesso identificatoreè usato in un blocco più internoall’interno del blocco internovale la definizione e inizializzazionedel blocco interno.
Il valore di x all’interno dello scope più esterno del main è: 5
Il valore di x all’interno dello scope più interno del main è: 7
Il valore di x all’interno dello scope più esterno del main è: 5
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…
void useLocal (void)void useLocal (void){{
int x=25; /*è di classe di memoria auto*/int x=25; /*è di classe di memoria auto*/printf(“”)printf(“”)printf(“valore di x entrati in useLocal, all’inizio printf(“valore di x entrati in useLocal, all’inizio della funzione: %d\n”,x);della funzione: %d\n”,x);x++;x++;printf(“valore di x entrati in useLocal, alla fine printf(“valore di x entrati in useLocal, alla fine della funzione: %d\n”,x);della funzione: %d\n”,x);
}}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
Il valore di x entrati in UseLocal all’iniziodella funzione è: 25Il valore di x entrati in UseLocal alla finedella funzione è: 26
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…
void useStaticLocal()void useStaticLocal(){{
static int x=50; /*inizializzata solo la prima volta static int x=50; /*inizializzata solo la prima volta che si entra nella funzione*/che si entra nella funzione*/printf(“local static vale %d all’inizio della funzione printf(“local static vale %d all’inizio della funzione useStaticLocal”,x);useStaticLocal”,x);x++;x++;printf(“local static vale %d alla fine della funzione printf(“local static vale %d alla fine della funzione useStaticLocal”,x);useStaticLocal”,x);
}}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…
void useGlobal()void useGlobal()
{{
printf(“global x vale %d all’entrata di printf(“global x vale %d all’entrata di useGlobal\n”,x);useGlobal\n”,x);
x*=10;x*=10;
printf(“global x vale %d alla fine di printf(“global x vale %d alla fine di useGlobal\n”,x);useGlobal\n”,x);
}}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
local static vale 50 all’inizio della funzione local static vale 50 all’inizio della funzione useStaticLocaluseStaticLocallocal static vale 51 alla fine della funzione local static vale 51 alla fine della funzione useStaticLocaluseStaticLocal
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
Global x vale 1 all’entrata diuseGlobal Global x vale 10 alla fine diuseGlobal
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
Il valore di x entrati in UseLocal all’iniziodella funzione è: 25Il valore di x entrati in UseLocal alla finedella funzione è: 26
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
local static vale 51 all’inizio della funzione local static vale 51 all’inizio della funzione useStaticLocaluseStaticLocallocal static vale 52 alla fine della funzione local static vale 52 alla fine della funzione useStaticLocaluseStaticLocal
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…#include <stdio.h>#include <stdio.h>
int x=5;int x=5; /*variabile locale al main*//*variabile locale al main*/printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);printf(“il valore di x all’interno dello scope più esterno del main è: %d”,x);{/*comincia un nuovo scope*/{/*comincia un nuovo scope*/int x=7; /*variabile locale al blocco*/int x=7; /*variabile locale al blocco*/printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);printf(“il valore di x all’interno dello scope più interno del main è: %d”,x);}}printf(“il valore di x nello scope più esterno del main è: %d”, x);printf(“il valore di x nello scope più esterno del main è: %d”, x);useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();useLocal();useLocal();useStaticLocal();useStaticLocal();useGlobal();useGlobal();return 0;return 0;
}}
Global x vale 10 all’entrata diuseGlobal Global x vale 100 alla fine diuseGlobal
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
RicorsioneRicorsione
Abbiamo visto come un problema complesso Abbiamo visto come un problema complesso possa essere scomposto in task, ciascuno possa essere scomposto in task, ciascuno realizzato tramite una funzionerealizzato tramite una funzioneUna funzione può invocare altre funzioniUna funzione può invocare altre funzioniE’ possibile anche invocare la STESSA E’ possibile anche invocare la STESSA funzione, su un input diversofunzione, su un input diverso– Un task complesso può essere risolto invocando la Un task complesso può essere risolto invocando la
funzione che realizza il task su dei sottoproblemi, funzione che realizza il task su dei sottoproblemi, usando la capacità di svolgere il task su sottoproblemi usando la capacità di svolgere il task su sottoproblemi per riuscire a svolgere il task sull’intero problema per riuscire a svolgere il task sull’intero problema
ricorsionericorsione
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Ricorsione…un esempioRicorsione…un esempioVogliamo scrivere una funzione che consenta di Vogliamo scrivere una funzione che consenta di calcolare il fattoriale n!calcolare il fattoriale n!n!= n*(n-1)*(n-2)*(n-3)*…*2*1Approccio 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 nAbbiamo 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 -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Viene calcolato fatt(5)5*24=120e viene restituito tale valorealla funzione chiamante main()
fatt(5)fatt(4)
fatt(2)fatt(3)
fatt(1)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Alcuni commenti…Alcuni commenti…Approccio ricorsivoApproccio ricorsivo– richiede l’invocazione di molte chiamate a funzione, di richiede l’invocazione di molte chiamate a funzione, di
allocare ogni volta memoria per i parametri e le variabili allocare ogni volta memoria per i parametri e le variabili localilocali
può essere inefficientepuò essere inefficienteTUTTAVIA ragionare in modo ricorsivo è molto utile e TUTTAVIA ragionare in modo ricorsivo è molto utile e
vedrete di qui a poco (PROG2) che esistono strutture vedrete di qui a poco (PROG2) che esistono strutture dati molto importanti quali gli alberi sui quali si riesce a dati molto importanti quali gli alberi sui quali si riesce a ragionare efficamente solo in modo ricorsivoragionare efficamente solo in modo ricorsivo
RAGIONARE IN MODO RICORSIVO E’ COMPLESSO MA RAGIONARE IN MODO RICORSIVO E’ COMPLESSO MA E’ Q.SA DI FONDAMENTALE PER UN INFORMATICO!!E’ Q.SA DI FONDAMENTALE PER UN INFORMATICO!!
Abbiamo visto cosa succede in memoria quando Abbiamo visto cosa succede in memoria quando invochiamo una sequenza di chiamate ricorsive…è invochiamo una sequenza di chiamate ricorsive…è importante capire come si ragiona ricorsivamenteimportante capire come si ragiona ricorsivamente
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Come si ragiona ricorsivamenteCome 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 generaleSe gli output della invocazioni su casi più piccoli possono essere elaborati ed usati per trovare la soluzione al problema (OUTPUT) peril caso più grandeAVER DETERMINATO IL MODO DI FARE CIO’ CI DARA’ IL NOSTROCODICE RICORSIVO
output1
output2
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Come si ragiona ricorsivamenteCome 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 generaleSe gli output della invocazioni su casi più piccoli possono essere elaborati ed usati per trovare la soluzione al problema (OUTPUT) peril caso più grandeAVER DETERMINATO IL MODO DI FARE CIO’ CI DARA’ IL NOSTROCODICE RICORSIVO
output1
output2
Sarà poi fondamentaleindividuare i casi basee assicurarci che tuttele sequenze di chiamatericorsive termininosempre con l’invocazionedi un caso base
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio…Un esempio…
SI scriva una funzione ricorsiva che dati due SI scriva una funzione ricorsiva che dati due numeri interi a e b calcoli a+bnumeri interi a e b calcoli a+b
Se so calcolare x+y, x<=a, y<b, come posso Se so calcolare x+y, x<=a, y<b, come posso usarlo per calcolare a+busarlo per calcolare a+b
a+b=(a+b-1)+1a+b=(a+b-1)+1
Calcolato dall’invocazione della funzione su a e b-1
Caso base: se b==0, a+b=a
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
SoluzioneSoluzione
int somma (int a, int b)int somma (int a, int b)
{{
if (b==0)if (b==0)
return a;return a;
elseelse
return (somma(a,b-1)+1);return (somma(a,b-1)+1);
}}Vediamo cosa succede invocando somma (3,2)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Un esempio..Un esempio..
Calcolo di 3+2Calcolo di 3+2
Viene invocata Viene invocata
x=somma(3,2);x=somma(3,2);int somma (int a, int b)int somma (int a, int b){{
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Numeri di FibonacciNumeri di Fibonacci
La serie di FibonacciLa serie di Fibonacci0,1,1,2,3,5,8,13,21,..0,1,1,2,3,5,8,13,21,..Comincia con i numero 0 e 1 ed ha la proprietà che se si 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)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 E’ una serie che occorre in natura. Il rapporto tra due
numeri consecutivi della serie di Fibonacci converge al numeri consecutivi della serie di Fibonacci converge al numero 1.618.. che è chiamata sezione aureanumero 1.618.. che è chiamata sezione aurea
Usare come rapporto tra dimensioni la sezione aurea è Usare come rapporto tra dimensioni la sezione aurea è esteticamente piacevoleesteticamente piacevole usato sin dall’antichità in usato sin dall’antichità in architettura (esempio rapporto tra le dimensioni di una architettura (esempio rapporto tra le dimensioni di una finestra, le dimensioni relative dei lati di una cartolina finestra, le dimensioni relative dei lati di una cartolina etc.) etc.)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
La ricorsione in molti casi è utile però può ridurre l’efficienza. Numero dichiamate elevato significa che paghiamo un overhead elevato (tempo e spazio) per invocare le funzioni, allocare memoria per le variabili locali
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di HanoiTorri di Hanoi La leggenda narra che in un tempio del profondo La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto d’appoggio C.64, esisteva anche un terzo paletto d’appoggio C.
A B C
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di HanoiTorri di Hanoi La leggenda narra che in un tempio del profondo La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto d’appoggio C.64, esisteva anche un terzo paletto d’appoggio C.
A B C
Ogni mossa poteva portareallo spostamento di un unicodisco E in ogni momentoi dischi dovevanoessere posizionati inordine decrescente su ciascuno dei paletti
La leggenda narra che il mondo finirà primache i monaci siano riusciti a completarequesto compito!
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi…un esempioTorri di Hanoi…un esempio La leggenda narra che in un tempio del profondo La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto d’appoggio C.64, esisteva anche un terzo paletto d’appoggio C.
A B C
Ad esempio il disco viola può esserespostato in una mossa da A a B
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi…un esempioTorri di Hanoi…un esempio La leggenda narra che in un tempio del profondo La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto d’appoggio C.64, esisteva anche un terzo paletto d’appoggio C.
A B C
Nella mossa successiva il disco azzurro può essere spostato da A a C
Il disco azzurro NONpoteva essere spostatoda A a B perché talespostamento non avrebbesoddisfatto il vincolo diordinamento decrescentedei dischi in B
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi…un esempioTorri di Hanoi…un esempio La leggenda narra che in un tempio del profondo La leggenda narra che in un tempio del profondo oriente i monaci fossero occupati nel compito di oriente i monaci fossero occupati nel compito di spostare dei dischi di pietra impilati in ordine di spostare dei dischi di pietra impilati in ordine di dimensione decrescente in un paletto A,dal dimensione decrescente in un paletto A,dal paletto (A) al paletto B. Il numero dei dischi era paletto (A) al paletto B. Il numero dei dischi era 64, esisteva anche un terzo paletto d’appoggio C.64, esisteva anche un terzo paletto d’appoggio C.
A B C
Nella mossa successiva nonpossiamo direttamente spostare il disco verde
Possiamo ad esempio prima spostare ildisco viola in C e poi il disco verde in B
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di HanoiTorri di HanoiProblema di difficile risoluzione iterativa se Problema di difficile risoluzione iterativa se abbiamo molti dischi (e dobbiamo trovare abbiamo molti dischi (e dobbiamo trovare un algoritmo che valga sempre, per un algoritmo che valga sempre, per qualsiasi numero di dischi)qualsiasi numero di dischi)Ragionare in modo ricorsivo aiuta a Ragionare in modo ricorsivo aiuta a trovare una soluzionetrovare una soluzione
A B
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di HanoiTorri di HanoiCosa vogliamo fare?Cosa vogliamo fare?– Muovere n dischi dal paletto A al paletto B Muovere n dischi dal paletto A al paletto B
usando C come appoggiousando C come appoggio
Come lo possiamo fare?Come lo possiamo fare?– Muovere n-1 dischi dal paletto A al paletto C Muovere n-1 dischi dal paletto A al paletto C
usando B come appoggiousando B come appoggio
A B
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di HanoiTorri di HanoiCosa vogliamo fare?Cosa vogliamo fare?– Muovere n dischi dal paletto A al paletto B usando C Muovere n dischi dal paletto A al paletto B usando C
come appoggiocome appoggio
Come lo possiamo fare?Come lo possiamo fare?– Muovere n-1 dischi dal paletto A al paletto C usando Muovere n-1 dischi dal paletto A al paletto C usando
B come appoggioB come appoggio– Spostare il disco più grande da A in BSpostare il disco più grande da A in B
A B
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di HanoiTorri di HanoiCosa vogliamo fare?Cosa vogliamo fare?– Muovere n dischi dal paletto A al paletto B usando C Muovere n dischi dal paletto A al paletto B usando C
come appoggiocome appoggio
Come lo possiamo fare?Come lo possiamo fare?– Muovere n-1 dischi dal paletto A al paletto C usando Muovere n-1 dischi dal paletto A al paletto C usando
B come appoggioB come appoggio– Spostare il disco più grande da A in BSpostare il disco più grande da A in B– Muovere n-1 dischi da C a B usando A come Muovere n-1 dischi da C a B usando A come
appoggioappoggio
A B
Chiamate ricorsive
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi-CodiceTorri di Hanoi-Codice#include<stdio.h>#include<stdio.h>void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *);void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *);main()main(){{
int i,n,n_A,n_B,n_C;int i,n,n_A,n_B,n_C;int A[100]={0};int A[100]={0};int B[100]={0};int B[100]={0};int C[100]={0};int C[100]={0};n_A=n_B=n_C=0;n_A=n_B=n_C=0;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);scanf(“%d”, &n);while ((n>100)||(n<1))while ((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);scanf(“%d”, &n);
I vettori A, B, Cconterranno i dischi(ed il loro ordine)impilati nei pioli A,B, e C
Dato un vettore A, n_Aindicherà il numero didischi impilati in A (memorizzati nelle locazioni di memoria0,…,n_A-1)n_A sarà quindi anchel’indice della prossimaposizione libera del vettore
Numero di dischiVettore che rappresenta il primo pioloPuntatore alla locazione che contiene La prima locazione libera relativa al primo piolo
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi-CodiceTorri di Hanoi-Codice#include<stdio.h>#include<stdio.h>void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *);void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *);main()main(){{
int i,n,n_A,n_B,n_C;int i,n,n_A,n_B,n_C;int A[100]={0};int A[100]={0};int B[100]={0};int B[100]={0};int C[100]={0};int C[100]={0};n_A=n_B=n_C=0;n_A=n_B=n_C=0;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);scanf(“%d”, &n);while ((n>100)||(n<1))while ((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);scanf(“%d”, &n);
I dischi hanno associatoun indice da 1,..,n I dischi più grandi avrannoassociato un indice piùpiccolo
Se il primo piolo contieneI dischi in figura il corrispettivovettore A conterrà nelle primen_A=4 posizioni i valori 1,2,3,4
4
3
2
1
A11 22 33 44
4
n_A
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi-CodiceTorri di Hanoi-Codice#include<stdio.h>#include<stdio.h>void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *);void hanoi (int,int[ ], int *, int [ ], int *, int [ ], int *);main()main(){{
int i,n,n_A,n_B,n_C;int i,n,n_A,n_B,n_C;int A[100]={0};int A[100]={0};int B[100]={0};int B[100]={0};int C[100]={0};int C[100]={0};n_A=n_B=n_C=0;n_A=n_B=n_C=0;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);scanf(“%d”, &n);while ((n>100)||(n<1))while ((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);scanf(“%d”, &n);
Inizializza i vettori A, B e C a zeron_A,n_B,n_C a zero (i vettori non hannoelementi memorizzati)
Prende da input un numero valido didischi n
Mette in A i vari dischi dal più grande al più piccolo(situazione quando si comincia a spostare da A a Bi dischi). Si aggiorna coerentemente n_A.
Si invoca la funzione hanoi il cuiCompito sarà spostare n dischi daA a B seguendo le regole per ilmovimento dei dischi e mantenendoaggiornate le informazioni sulcontenuto e num. Di elementi delvettore
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Torri di Hanoi-CodiceTorri di Hanoi-Codice/*pre: num >=1*//*pre: num >=1*/void hanoi(int num, int a[ ], int *N_a, int b[ ], int *N_b, int c[ ], int void hanoi(int num, int a[ ], int *N_a, int b[ ], int *N_b, int c[ ], int
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Ricorsione e vettoriRicorsione e vettori
Si scriva una funzione ricorsiva somma_v che Si scriva una funzione ricorsiva somma_v che dato un vettore di interi vett produca in output dato un vettore di interi vett produca in output la somma degli elementi di vettla somma degli elementi di vett
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Ricorsione e vettoriRicorsione e vettori
Si scriva una funzione ricorsiva somma_v che Si scriva una funzione ricorsiva somma_v che dato un vettore di interi vett produca in output dato un vettore di interi vett produca in output la somma degli elementi di vettla somma degli elementi di vett– Se il vettore ha un unico elemento allora la somma Se il vettore ha un unico elemento allora la somma
dei suoi elementi è pari al valore dell’elementodei suoi elementi è pari al valore dell’elemento– Altrimenti la somma dei primi n elementi è pari al Altrimenti la somma dei primi n elementi è pari al
valore dell’n-esimo elemento + la somma dei primi valore dell’n-esimo elemento + la somma dei primi n-1 elementi n-1 elementi
00 33 22 …… -1-1 99 vett
Tale somma èottenuta tramitechiamata ricorsiva
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Somma degli elementi di un vettoreSomma degli elementi di un vettore
/*pre: il vettore ha almeno un elemento*//*pre: il vettore ha almeno un elemento*/int somma_v(int vett[ ], int n)int somma_v(int vett[ ], int n){{
if (n==1)if (n==1)return (vett[0]);return (vett[0]);
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Ricerca di un elemento in un vettoreRicerca di un elemento in un vettoreSi scriva una funzione ricorsiva search_v che dato Si scriva una funzione ricorsiva search_v che dato un vettore di interi vett ed un intero key determini un vettore di interi vett ed un intero key determini se l’elemento key è presente tra gli elementi del se l’elemento key è presente tra gli elementi del vettorevettore– Se il vettore ha un unico elemento allora la funzione Se il vettore ha un unico elemento allora la funzione
restituisce 1 se l’elemento del vettore ha valore pari a restituisce 1 se l’elemento del vettore ha valore pari a key, 0 altrimentikey, 0 altrimenti
– Altrimenti la funzione restituisce 1 se e solo se O Altrimenti la funzione restituisce 1 se e solo se O l’elemento key è contenuto nell’ultimo elemento del l’elemento key è contenuto nell’ultimo elemento del vettore OPPURE è contenuto nei primi n-1 elementi del vettore OPPURE è contenuto nei primi n-1 elementi del vettore vettore
00 33 22 …… -1-1 99 vett
Tale verifica èeffettuata tramitechiamata ricorsiva
key=3
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Ricerca di un elemento in un Ricerca di un elemento in un vettorevettore
/*pre: il vettore ha almeno un elemento*//*pre: il vettore ha almeno un elemento*/int search_v(int vett[ ], int n, int key)int search_v(int vett[ ], int n, int key){{
if (n==1)if (n==1)return (vett[0]==key);return (vett[0]==key);
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Minimo in un vettoreMinimo in un vettoreSi scriva una funzione ricorsiva min_v che dato un Si scriva una funzione ricorsiva min_v che dato un vettore di interi vett determini il valore vettore di interi vett determini il valore dell’elemento più piccolo del vettoredell’elemento più piccolo del vettore– Se il vettore ha un unico elemento allora la funzione Se il vettore ha un unico elemento allora la funzione
restituisce il valore dell’elementorestituisce il valore dell’elemento– Altrimenti si calcola il valore più piccolo tra i primi n-1 Altrimenti si calcola il valore più piccolo tra i primi n-1
elementi. Se tale valore è più piccolo dell’n-esimo elementi. Se tale valore è più piccolo dell’n-esimo elemento allora è il valore più piccolo del vettore. elemento allora è il valore più piccolo del vettore. ALTRIMENTI il valore più piccolo del vettore è costituito ALTRIMENTI il valore più piccolo del vettore è costituito dall’n-esimo elemento del vettore dall’n-esimo elemento del vettore
00 33 22 …… -1-1 99 vettIl valore più piccolo tra i primi n-1 elementi è restituito dalla chiamataricorsiva
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Minimo in un vettoreMinimo in un vettore/*pre: il vettore ha almeno un elemento*//*pre: il vettore ha almeno un elemento*/int min_v(int vett[ ], int n)int min_v(int vett[ ], int n){{
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
EserciziEsercizi
Esercizi su stringhe e caratteri Esercizi su stringhe e caratteri – Versioni iterativeVersioni iterative– Versioni ricorsive Versioni ricorsive ® per indicare una ® per indicare una
soluzione ricorsivasoluzione ricorsiva
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1Esercizio 1
Si scriva una procedura Iterativa che, dato un testo (di dimensione minore di max_size), stampi il testo invertito e senza gli spazi
Si memorizza il testo –tranne gli spazi-in una stringa
si stampano i caratteri della stringa (dall’ultimo al primo)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1-caratteriEsercizio 1-caratteri
void elimina_spazi_e_inverti (int max_size)void elimina_spazi_e_inverti (int max_size){{ int c,count,i;int c,count,i; char str[max_size];char str[max_size]; count=0;count=0; while (((c=getchar()) != EOF) &&(count<max_size)) while (((c=getchar()) != EOF) &&(count<max_size)) {{ if (c!=‘ ‘)if (c!=‘ ‘) {{ str[count]=c;str[count]=c; count++;count++; }} }} str[count]=‘\0’;str[count]=‘\0’; for (i=count-1;i>=0;i- -)for (i=count-1;i>=0;i- -) printf(“%c”,str[i]);printf(“%c”,str[i]);}}
Si scriva una procedura Iterativa che, dato un testo (di dimensioneminore di max_size),
stampi il testoinvertito e senza
gli spazi
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1, versione ricorsivaEsercizio 1, versione ricorsiva
Si scriva una procedura ricorsiva che, dato un testo stampi il testo invertito e senza gli spazi
Leggi il carattere corrente e memorizzalo in cLeggi il resto del testo stampandolo invertito e senza gli spaziSe c è diverso da uno spazio stampa c
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1-caratteri ®Esercizio 1-caratteri ®
void Relimina_spazi_e_inverti ()void Relimina_spazi_e_inverti (){{ int c;int c; if ((c=getchar()) != EOF) if ((c=getchar()) != EOF) {{ Relimina_spazi_e_inverti();Relimina_spazi_e_inverti(); if (c!=‘ ‘)if (c!=‘ ‘) putchar ( c);putchar ( c);}}}}
Si scriva una procedura ricorsiva che, dato un testo stampa il testo
invertito e senzagli spazi
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1-stringheEsercizio 1-stringhe/*stampa di una stringa *//*stampa di una stringa */void printstringa (char *);void printstringa (char *);
/*Post: stampa il contenuto della stringa*//*Post: stampa il contenuto della stringa*/void printstringa (char *s)void printstringa (char *s){{
for (;*s!=‘\0’;s++) for (;*s!=‘\0’;s++) putchar(*s);putchar(*s);
}}
Si scriva una procedura iterativa
che, data una stringa s presa in
input ne stampi i caratteri in output
OPPURE:void printstringa (char *s){ int i; for (i=0;s[i]!=‘\0’;i++) putchar(s[i]);}
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1-stringheEsercizio 1-stringhe
Si scriva una procedura ricorsiva
che, data una stringa s presa in input ne stampi i caratteri in output
Stampa l’elemento correnteStampa il resto degli elementi della stringa
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 1-stringhe ®Esercizio 1-stringhe ®/*stampa di una stringa (ricorsiva)*//*stampa di una stringa (ricorsiva)*/void Rprintstringa (char *);void Rprintstringa (char *);
/*Post: stampa il contenuto della stringa*//*Post: stampa il contenuto della stringa*/void Rprintstringa (char *s)void Rprintstringa (char *s){{
if (*s != '\0')if (*s != '\0'){{putchar(*s);putchar(*s);Rprintstringa (s+1);Rprintstringa (s+1);
}}}}
Si scriva una procedura ricorsiva
che, data una stringa s presa in
input ne stampi i caratteri in output
Attenzione: qui abbiamo usatol’aritmetica dei puntatori perchiamare la funzione ricorsivasul resto della stringa, esclusol’elemento corrente
Come dovremmo modificare il codiceper stampare i caratteri della stringa inordine inverso?
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 2-stringheEsercizio 2-stringhe
Si scriva una procedura ricorsiva
che, data una stringa s presa in input ne stampi i caratteri in output in ordine inverso
Memorizza l’elemento corrente in cStampa il resto degli elementi della stringa in ordine inversoStampa quanto memorizzato in c
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 2-stringhe ®Esercizio 2-stringhe ®/*stampa di una stringa (ricorsiva)*//*stampa di una stringa (ricorsiva)*/void Rprintstringa_invertita (char *);void Rprintstringa_invertita (char *);
/*Post: stampa il contenuto della stringa invertito*//*Post: stampa il contenuto della stringa invertito*/void Rprintstringa_invertita (char *s)void Rprintstringa_invertita (char *s){{
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Cosa succede in memoria…Cosa succede in memoria…All’entrata nella funzione si alloca memoria per il All’entrata nella funzione si alloca memoria per il puntatore s che punta al primo elemento della puntatore s che punta al primo elemento della stringa correntestringa corrente
Non siamo arrivati al carattere di fine stringa Non siamo arrivati al carattere di fine stringa quindi si invoca la chiamata ricorsivaquindi si invoca la chiamata ricorsiva
L’invocazione della chiamataricorsiva farà stampare in ordineinverso il resto della stringa a partiredal secondo carattere(s+1) è la locazione di memoriadove è memorizzato il secondocarattere della stringaeul
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Cosa succede in memoria…Cosa succede in memoria…All’entrata nella funzione si alloca memoria per il All’entrata nella funzione si alloca memoria per il puntatore s che punta al primo elemento della puntatore s che punta al primo elemento della stringa correntestringa corrente
Non siamo arrivati al carattere di fine stringa Non siamo arrivati al carattere di fine stringa quindi si invoca la chiamata ricorsivaquindi si invoca la chiamata ricorsiva
L’invocazione della chiamataricorsiva farà stampare in ordineinverso il resto della stringa a partiredal secondo carattere(s+1) è la locazione di memoriadove è memorizzato il secondocarattere della stringaeul
Basterà quindi stampare ilcarattere puntato da s
eulb
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 3-stringheEsercizio 3-stringhe/*calcola la lunghezza di una stringa *//*calcola la lunghezza di una stringa */int String_length(char *);int String_length(char *);
main()main(){{char str1[1024];char str1[1024];printf(“inserisci una stringa \n”);printf(“inserisci una stringa \n”);scanf(“%s”,str1);scanf(“%s”,str1);printf(“la lunghezza della stringa e’ %d \n”, String_length(str1));printf(“la lunghezza della stringa e’ %d \n”, String_length(str1));………………………………………………}}
/*calcola la lunghezza della stringa*//*calcola la lunghezza della stringa*/
int String_length(char *s1)int String_length(char *s1){{ int count=0:int count=0:
while (*s1 != ‘\0’)while (*s1 != ‘\0’) { {
count++;count++; s1++;s1++; }}
return count;return count;}}
Si scriva una funzione iterativa
che, data una stringa ne calcoli il numero di caratteri (escluso
il carattere di fine stringa)
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Esercizio 3-stringhe ®Esercizio 3-stringhe ®/*calcola il numero di caratteri in una stringa*//*calcola il numero di caratteri in una stringa*/int Rsizestringa (char *, int);int Rsizestringa (char *, int);
main()main(){{char str1[1024];char str1[1024];printf(“inserisci stringa \n”);printf(“inserisci stringa \n”);scanf(“%s”,str1);scanf(“%s”,str1);printf(“il numero di caratteri della stringa e’ %d \n”,printf(“il numero di caratteri della stringa e’ %d \n”,Rsizestringa(str1,0) );Rsizestringa(str1,0) );………………………………………………}}
/*calcola il numero di caratteri in una stringa*//*calcola il numero di caratteri in una stringa*//*Pre: s stringa, i>=0, chiamato con i==0 *//*Pre: s stringa, i>=0, chiamato con i==0 *//*Post: restituisce il numero di caratteri della /*Post: restituisce il numero di caratteri della stringa (escluso il carattere di fine stringa */stringa (escluso il carattere di fine stringa */int Rsizestringa(char s[ ], int i)int Rsizestringa(char s[ ], int i){{
La rappresentazione dei reali è binaria. Alcuni numeri che ciSembrerebbero perfettamente rappresentabili hanno dei problemidi rappresentazione in binario.
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Manipolazione di reali in CManipolazione di reali in C
Ragionando in base 10 è facile comprendere un Ragionando in base 10 è facile comprendere un problema: problema:
Consideriamo la frazione 1/3Consideriamo la frazione 1/3
Corrisponde ad un numero periodicoCorrisponde ad un numero periodico– 0.333….0.333….I numeri reali in una macchina sono memorizzati con I numeri reali in una macchina sono memorizzati con
un numero limitato di byte un numero limitato di byte si perde in precisione si perde in precisione nella rappresentazionenella rappresentazione
Il problema non riguarda solo i numero periodici!Il problema non riguarda solo i numero periodici!
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Errore nella rappresentazione dei Errore nella rappresentazione dei realireali
Abbiamo un numero limitato di byte (es. 8) Abbiamo un numero limitato di byte (es. 8) per rappresentare un double.per rappresentare un double.
Tra quanti numeri è possibile distinguere Tra quanti numeri è possibile distinguere usando 8*8=64 bit?usando 8*8=64 bit?
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
Errore nella rappresentazione dei Errore nella rappresentazione dei realireali
Abbiamo un numero limitato di byte (es. 8) Abbiamo un numero limitato di byte (es. 8) per rappresentare un double.per rappresentare un double.
Tra quanti numeri è possibile distinguere Tra quanti numeri è possibile distinguere usando 8*8=64 bit?usando 8*8=64 bit?
226464
L’intervallo dei reali rappresentati è quindi diviso in 226464 sottointervalliniNon possiamo avere una rappresentazione dell’intervallo continuodei numeri reali
Se immaginate che il numero reale che si trova nel mezzo dell’intervallo sia rappresentato con la sequenzadi bit che è associata all’intervallo, e che tutti gli altrivalori che cadono nell’intervallo siano approssimaticon tale sequenza di bit l’errore massimo è q/2 conq ampiezza dei sottointervallini.
c’è un errore di rappresentazione maggiore il numero di bit minore l’errore di rappresentazioneChe comunque non può essere totalmente annullato
È un errore di rappresentazione che ci portiamo dietro e che può ancheAccumularsi facendo operazioni sui reali
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
EsempioEsempio
Nel caso di 0.1Nel caso di 0.1
La stampa del valore decimale La stampa del valore decimale dell’approssimazione binaria del numero dell’approssimazione binaria del numero fornisce il seguente risultatofornisce il seguente risultato
0.100000000000000010.10000000000000001
Non è un bug! Come abbiamo visto dipende dalla rappresentazionedei numeri reali
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
EsempioEsempio
Fare operazioni sui reali può portare a Fare operazioni sui reali può portare a sorpresesorprese
sum = 0.0sum = 0.0
for (i=0;i<10;i++)for (i=0;i<10;i++)
sum += 0.1;sum += 0.1;
Il valore di sum all’uscita dal ciclo è:Il valore di sum all’uscita dal ciclo è:
0.999999999999999890.99999999999999989
Prof.ssa Chiara Petrioli -- corso di progrProf.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007ammazione 1, a.a. 2006/2007
In sintesiIn sintesiLa rappresentazione dei reali porta ad approssimazioni, La rappresentazione dei reali porta ad approssimazioni, che possono accumularsi o bilanciarsi facendo operazioni che possono accumularsi o bilanciarsi facendo operazioni sui realisui reali– Non è un bug, è q.sa di intrinseco nella rappresentazione di un Non è un bug, è q.sa di intrinseco nella rappresentazione di un
intervallo continuo in una macchinaintervallo continuo in una macchina
Cosa si può fare:Cosa si può fare:– tenerne conto nello scrivere un programma (nessuna soluzione tenerne conto nello scrivere un programma (nessuna soluzione
prefatta, criteri generali-vedi qui di seguito- e buon senso portano prefatta, criteri generali-vedi qui di seguito- e buon senso portano alla soluzione)alla soluzione)
– Ad esempio anziché testare se A=B nel caso in cui A e B siano Ad esempio anziché testare se A=B nel caso in cui A e B siano diversi, testare se A e B sono pressochè uguali |A-B|<= epsilon diversi, testare se A e B sono pressochè uguali |A-B|<= epsilon (cercando così di filtrare problemi di rappresentazione che si (cercando così di filtrare problemi di rappresentazione che si ripercuotono tipicamente sulle cifre meno significative).ripercuotono tipicamente sulle cifre meno significative).
– Esistono librerie ‘a precisione infinita’ (o meglio a precisione Esistono librerie ‘a precisione infinita’ (o meglio a precisione arbitraria)arbitraria)libreria BigDigitslibreria BigDigits
Non sono a precisione infinita ma cercano di allocare dinamicamente Non sono a precisione infinita ma cercano di allocare dinamicamente maggiore o minore memoria per memorizzare i numeri reali in modo da maggiore o minore memoria per memorizzare i numeri reali in modo da aumentare l’accuratezza con cui sono rappresentatiaumentare l’accuratezza con cui sono rappresentati
Memorizzano in strutture dati a dimensione variabile i numeri realiMemorizzano in strutture dati a dimensione variabile i numeri reali Rallentano l’esecuzioneRallentano l’esecuzione