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);}
*number si usa come alias per la variabile passata
1.
2.
3.
/* Elevare al cubo mediante una chiamata per valore */
#include <stdio.h>
int cubeByValue(int);
4.
5.
6.
7.
8.
9.
10.
11.
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;
}
12.
13.
14.
15.
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
3
mediante puntatori */
4
5 #include <stdio.h>
6
7 void cubeByReference( int * );
Notare che viene dato
8
l’indirizzo di number –
9 int main()
infatti cubeByReference
10 {
aspetta un puntatore
11
int number = 5;
(indirizzo di una variabile).
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 }
All’interno di cubeByReference,
19
si usa *nPtr (*nPtr e’ number).
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
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
/* 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') {
16.
17.
if (*s >= 'a' && *s <= 'z')
*s -= 32; /* convert to ASCII uppercase letter */
18.
19.
20.
++s;
}
}
/* increment s to point to the next character */
The string before conversion is: characters
The string after conversion is:
CHARACTERS
Output
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
/* 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;
}
13.
14.
15.
16.
17.
void printCharacters(const char *s)
{
for ( ; *s != '\0'; s++)
/* no initialization */
putchar(*s);
}
The string is:
print characters of a string
Output
1.
2.
3.
4.
5.
6.
7.
/* 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;
8.
9.
10.
f(&y);
return 0;
}
11.
12.
13.
14.
void f(const int *x)
{
*x = 100; /* cannot modify a const object */
}
*/
/* f attempts illegal modification */
13
Warning: assignment of read-only location
Dev-C++
13
ERROR: Cannot modify a const object
Borland
1.
2.
3.
/* Fig. 7.13 Attempting to modify a constant pointer to */
/* non-constant data
*/
#include <stdio.h>
4.
5.
6.
7.
main()
{
int x, y;
int * const ptr = &x;
8.
ptr = &y; /* attempt to modify a const pointer*/
9.
10.
return 0;
}
10
Warning: assignment to read-only variable ‘ptr’
Dev-C++
10
ERROR: Cannot modify a const object
Borland
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Fig. 7.14: fig07_14.c
Attempting to modify a constant pointer to
constant data */
#include <stdio.h>
int main()
{
int x=5, y;
const int * const ptr = &x;
*ptr = 7;
ptr = &y;
return 0;
}
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-pervalore 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
3
ascending order, and prints the resulting array. */
4 #include <stdio.h>
5 #define SIZE 10
6 void bubbleSort( int *, const int );
7
8 int main()
9 {
11
int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
12
int i;
13
Bubblesort prende
14
printf( "Data items in original order\n" );
l’indirizzo dell’array.
15
Il nome di un array e’ un
16
for ( i = 0; i < SIZE; i++ )
puntatore..
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 }
29
30 void bubbleSort( int *array, const int size )
31 {
32
void swap( int *, int * );
33
int pass, j;
34
for ( pass = 0; pass < size - 1; pass++ )
35
36
for ( j = 0; j < size - 1; j++ )
37
38
39
if ( array[ j ] > array[ j + 1 ] )
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 }
Data items in original order
2
6
4
8 10 12 89 68
Data items in ascending order
2
4
6
8 10 12 37 45
45
37
Output
Nelle lezioni precedenti…
103
104
105
106
107
108
109
110
111
112
113
114
115
116
void bubbleSort( int a[] )
{
int pass, j, hold;
for ( pass = 1; pass <= SIZE - 1; pass++ )
for ( j = 0; j <= SIZE - 2; j++ )
if ( a[
hold
a[ j
a[ j
}
}
j
=
]
+
] > a[ j + 1 ] ) {
a[ j ];
= a[ j + 1 ];
1 ] = hold;
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.
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!
locazione
3000
v[0]
3004
v[1]
variabile puntatore
vPtr
3008
v[2]
3012
v[3]
3016
v[4]
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
Scarica

versione power point