200 likes | 310 Vues
24 aprile 2002. Avvisi:. Risultati 1 o Esonero: (entro) lunedi 27 disponibili nella pag. WEB , ma anche esposti nella bacheca fuori dal corridoio 2 o dente, piano terra. “Speciale 1 o Esonero”: soluzioni , commenti, correzioni compiti prossima lezione (giovedì 2 maggio).
E N D
24 aprile 2002 Avvisi: • Risultati 1o Esonero: (entro) lunedi 27 disponibili nella pag. WEB , ma anche esposti nella bacheca fuori dal corridoio 2o dente, piano terra. • “Speciale 1o Esonero”: soluzioni , commenti, correzioni compiti prossima lezione (giovedì 2 maggio). • Progetti: gia’ disponibili nella pag. WEB.
Qualche minuto di “laboratorio” • Esercizio 6.19 • Scrivere un programma C che simuli il lancio di due dadi. Il programma dovra’ utilizzare rand per lanciare il primo dado e poi invocarla nuovamente per lanciare il secondo dado: poi calcolera’ la somma dei due valori. (Nota: tale somma puo’ variare tra 2 e 12). Tale programma dovra’ lanciare i due dadi 36.000 volte e poi dovra’ visualizzare i seguenti risultati: • Un vettore di frequenze F per i risultati di ogni lancio cioe’ tale che F(i) rappresenta quante volte la somma dei due dadi e’ stata uguale ad i con i=2,3,…12. • Una matrice D 6x6 tale che D(i,j) rappresenta quante volte si e’ ottenuto i col primo dado e j con il secondo dado con i,j=1,2,…,6. Vediamo le soluzioni proposte da voi…
Chiamata di funzioni per riferimento • Chiamata per riferimento usando puntatori come argomenti • Si passa l’indirizzo di un argomento usando l’operatore & • Consentono di cambiare il valore nella locazione di memoria • Gli array non si possono passare con & perche’ il nome dell’array e’ gia’ un puntatore • operatore* • Usato come alias per una variabile all’interno di una funzione void double(int *number) {*number = 2 * (*number);} *numbersi usa come alias per la variabile passata
/* Elevare al cubo mediante una chiamata per valore */ • #include <stdio.h> • int cubeByValue(int); • main() • { • int number = 5; • printf("The original value of number is %d\n", number); • number = cubeByValue(number); • printf("The new value of number is %d\n", number); • return 0; • } • int cubeByValue(int n) • { • return n * n * n; /* eleva al cubo */ • } The original value of number is 5 The new value of number is 125 Output
1 /* Fig. 7.7: fig07_07.c 2 Elevare al cubo mediante chiamata per riferimento Notare che viene dato l’indirizzo di number – infatti cubeByReference aspetta un puntatore (indirizzo di una variabile). 3 mediante puntatori */ 4 5 #include <stdio.h> 6 7 void cubeByReference( int * ); 8 All’interno di cubeByReference, si usa *nPtr (*nPtr e’ number). 9 int main() 10 { 11 int number = 5; 12 13 printf( "The original value of number is %d", number ); 14 cubeByReference( &number ); 15 printf( "\nThe new value of number is %d\n", number ); 16 17 return 0; 18 } 19 20 void cubeByReference( int *nPtr ) 21 { 22 *nPtr = *nPtr * *nPtr * *nPtr; 23 } The original value of number is 5 The new value of number is 125 Output
Usare il qualificatore Const con i puntatori • Qualificatore const– una variabile non puo’ essere cambiata • Utile avere const se la funzione non deve cambiare una variabile • Tentativi di cambiare un const produce “errore” in compilazione • Puntatori const – puntano alla stessa locazione di memoria • Devono essere inizializzati quando sono dichiarati int *const myPtr = &x; • Tipo int *const – puntatore costante a un int const int *myPtr = &x; • Puntatori regolari a const int const int *const Ptr = &x; • const puntatore a const int • x puo’ essere cambiato, ma non *Ptr
/* Fig7_10 Converting lowercase letters to uppercase letters */ • /* using a non-constant pointer to non-constant data */ • #include <stdio.h> • void convertToUppercase(char *); • main() • { • char string[] = "characters"; • printf("The string before conversion is: %s\n", string); • convertToUppercase(string); • printf("The string after conversion is: %s\n", string); • return 0; • } • void convertToUppercase(char *s) • { • while (*s != '\0') { • if (*s >= 'a' && *s <= 'z') • *s -= 32; /* convert to ASCII uppercase letter */ • ++s; /* increment s to point to the next character */ • } • }
The string before conversion is: characters The string after conversion is: CHARACTERS Output
/* Fig7_11 Printing a string one character at a time using */ • /* a non-constant pointer to constant data */ • #include <stdio.h> • void printCharacters(const char *); • main() • { • char string[] = "print characters of a string"; • printf("The string is:\n"); • printCharacters(string); • putchar('\n'); • return 0; • } • void printCharacters(const char *s) • { • for ( ; *s != '\0'; s++) /* no initialization */ • putchar(*s); • } The string is: print characters of a string Output
/* Fig7_12.c Attempting to modify data through a */ • /* non-constant pointer to constant data */ • #include <stdio.h> • void f(const int *); • main() • { • int y; • f(&y); /* f attempts illegal modification */ • return 0; • } • void f(const int *x) • { • *x = 100; /* cannot modify a const object */ • } Dev-C++ 13 Warning: assignment of read-only location Borland 13 ERROR: Cannot modify a const object
/* Fig. 7.13 Attempting to modify a constant pointer to */ • /* non-constant data */ • #include <stdio.h> • main() • { • int x, y; • int * const ptr = &x; • ptr = &y; /* attempt to modify a const pointer*/ • return 0; • } Dev-C++ 10 Warning: assignment to read-only variable ‘ptr’ Borland 10 ERROR: Cannot modify a const object
1 /* Fig. 7.14: fig07_14.c 2 Attempting to modify a constant pointer to 3 constant data */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 int x=5, y; 10 11 constint * const ptr = &x; 12 13 14 15 *ptr = 7; 16 ptr = &y; 17 18 return 0; 19 } FIG07_13.c: Error E2024 FIG07_13.c 15: Cannot modify a const object in function main 16: Cannot modify a const object in function main *** 2 errors in Compile ***
Bubble Sort usando chiamata per riferimento • Implementare bubblesort usando puntatori • Scambia due elementi • La funzione swap deve ricevere un indirizzo (usando &) degli elementi dell’array • Gli elementi dell’array hanno una chiamata-per-valore per default • Usando puntatori e l’operatore *, la funzione swap puo’ scambiare elementi dell’array
1 /* Fig. 7.15: fig07_15.c 2 This program puts values into an array, sorts the values into Bubblesort prende l’indirizzo dell’array. Il nome di un array e’ un puntatore.. 3 ascending order, and prints the resulting array. */ 4 #include <stdio.h> 5 #define SIZE 10 6 void bubbleSort( int *, constint ); 7 8 int main() 9 { 11 int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 12 int i; 13 14 printf( "Data items in original order\n" ); 15 16 for ( i = 0; i < SIZE; i++ ) 17 printf( "%4d", a[ i ] ); 18 19 bubbleSort( a, SIZE ); /* ordina l’array */ 20 printf( "\nData items in ascending order\n" ); 21 22 for ( i = 0; i < SIZE; i++ ) 23 printf( "%4d", a[ i ] ); 24 25 printf( "\n" ); 27 return 0; 28 }
33 int pass, j; 34 for ( pass = 0; pass < size - 1; pass++ ) 35 36 for ( j = 0; j < size - 1; j++ ) 37 38 if ( array[ j ] > array[ j + 1 ] ) 39 swap( &array[ j ], &array[ j + 1 ] ); 40 } 41 42 void swap( int *element1Ptr, int *element2Ptr ) 43 { 44 int hold = *element1Ptr; 45 *element1Ptr = *element2Ptr; 46 *element2Ptr = hold; 47 } 29 30 void bubbleSort( int *array, constint size ) 31 { 32 void swap( int *, int * ); Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 Output
103 void bubbleSort( int a[] ) 104 { 105 int pass, j, hold; 106 107 for ( pass = 1; pass <= SIZE - 1; pass++ ) 108 109 for ( j = 0; j <= SIZE - 2; j++ ) 110 111 if ( a[ j ] > a[ j + 1 ] ) { 112 hold = a[ j ]; 113 a[ j ] = a[ j + 1 ]; 114 a[ j + 1 ] = hold; 115 } 116 } Nelle lezioni precedenti…
Aritmetica con i puntatori • Alcune operazioni aritmetiche possono essere utilizzate con i puntatori • Incrementa/decrementa puntatori (++ o --) • Si puo’ aggiungere/sottrarre un intero a/da un puntatore ( + o +=, - o -=) • Puntatori possono essere sottratti uno dall’altro • Attenzione: Sono operazioni senza significato a meno che non siano effettuate su array.
locazione 3000 3004 3008 3012 3016 variabile puntatore vPtr v[0] v[1] v[2] v[4] v[3] Aritmetica con i puntatori • int v[5] (supp int e’ di 4 byte) • vPtr = v oppure vPtr = &v[0] • vPtr punta al primo elemento v[0]nella locazione 3000. (vPtr = 3000) • vPtr +=2; assegna a vPtr valore 3008 • vPtr punta a v[2], ma un int vale 4 byte!
Aritmetica con i puntatori • Sottrarre puntatori • Restituisce il numero di elementi tra uno e l’altro • vPtr2 = &v[2]; vPtr = &v[0]; vPtr2 - vPtr = 2. (numero di elementi del vettore tra vPtr2 e vPtr ) • Confronti tra puntatori ( <, == , > ) • Per vedere quale puntatore punta all’elemento dellarray di indice maggiore… • Anche per controllare se un puntatore punta a
Aritmetica con i puntatori • Puntatori dello stesso tipo possono essere assegnati uno all’altro • Se non sono dello stesso tipo, deve essere usato un operatore cast • Eccezione: puntatori a void (tipo void *) • Puntatori generici, rappresentano qualunque tipo • Non occorre casting per convertire un puntatore ad un puntatore void • Puntatori void non possono essere dereferenziati