24
Politecnico Politecnico di Milano di Milano Esercizi Esercizi Puntatori, struct con campi puntatore, Puntatori, struct con campi puntatore, puntatori a struct, puntatori a struct, rapporto tra array e puntatori. rapporto tra array e puntatori. FUNZIONI FUNZIONI Passaggio di parametri per indirizzo, Passaggio di parametri per indirizzo, passaggio di array. passaggio di array.

Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

Embed Size (px)

Citation preview

Page 1: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

PolitecnicoPolitecnicodi Milanodi Milano

EserciziEsercizi

Puntatori, struct con campi puntatore, puntatori a Puntatori, struct con campi puntatore, puntatori a struct,struct,

rapporto tra array e puntatori.rapporto tra array e puntatori.

FUNZIONIFUNZIONIPassaggio di parametri per indirizzo, passaggio di Passaggio di parametri per indirizzo, passaggio di

array.array.

Page 2: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 22 - -

#include <stdio.h>

void swapInt (int a1, int a2){

int tmp;tmp = a1;a1 = a2;a2 = tmp;

}

void main (){

int n1 = 3, n2 = 4;swapInt (n1, n2);printf ("n1=%d,n2=%d",n1,n2);

}

Passando i parametri per valore, il risultato non è quello atteso!wrongSwapInt() scambia il contenuto delle variabili localia1 e a2 Nessun effetto sulle variabili n1 e n2

La funzione La funzione swapInt()swapInt()primo tentativoprimo tentativo

Page 3: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 33 - -

Parametri per indirizzoParametri per indirizzo

Definizione:

void funzione (float *p1, char *p2){

*p1 = 1.125; *p2 = 'z';

}

Chiamata:float x;char y;funzione (&x, &y);

I parametri formali puntano ai parametri attualiLe modifiche effettuate sui parametri formali sono in realtà eseguite sui parametri attuali.

Page 4: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 44 - -

La funzione La funzione swapInt()swapInt()versione correttaversione corretta

#include <stdio.h>

void swapInt (int *p1, int *p2){

int tmp;tmp = *p1;*p1 = *p2;*p2 = tmp;

}

void main (){

int n1 = 3, n2 = 4;swapInt (&n1, &n2);printf ("n1=%d,n2=%d",n1,n2);

}

Page 5: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 55 - -

Indovina numeroIndovina numero

Scrivere un programma che, utilizzando le funzioni, implementi un gioco nel quale l’utente deve indovinareun numero segreto entro un massimo di tentativiLa funzione indovinaNumero():

Permette di inserire un numeroConfronta il numero inserito con quello da individuare e visualizza il messaggo “troppo grande” o “troppo piccolo” Se il numero inserito è corretto, la funzione ritorna vero, altrimenti ricomincia il ciclo (un parametro fissa il numero max di tentativi)Se, esauriti i tentativi permessi, il numero segreto non è stato individuato, la funzione ritorna falso.

Page 6: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 66 - -

Indovina numeroIndovina numero

#include <stdio.h>

typedef enum {falso, vero} Booleano;

Booleano indovinaNumero (unsigned int *ripetiz, unsigned int maxRipetiz, unsigned long int numero){ unsigned long int tentativo; unsigned int n = 0; Booleano trovato = falso; do { printf ("Tentativo %u: ", n + 1); scanf ("%lu", &tentativo); n++;

Page 7: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 77 - -

Indovina numeroIndovina numero

if (tentativo == numero) { trovato = vero; } else if (tentativo > numero) { printf ("Troppo grande!\n"); } else { printf ("Troppo piccolo!\n"); } }while (!trovato && n < maxRipetiz); *ripetiz = n; return trovato;}

Page 8: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 88 - -

Indovina numeroIndovina numero

void main(){ const unsigned long int NUMERO = 999, MAXRIP = 3; Booleano indovinato; unsigned int nRip; indovinato = indovinaNumero (&nRip,MAXRIP,NUMERO); if (!indovinato) { printf ("Tentativi esauriti"); } else { printf ("Ok al tentativo %u", nRip); }}

Page 9: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 99 - -

Puntatore a Puntatore a structstruct

Due modi equivalenti di accedere ad un campo di una struct, usando un puntatore:

Esempio, evendo questo tipo strutturato:

typedef struct{ int a; int b; int c;} MioTipo;MioTipo *f;

Accedo al campo a attraverso *f usando:(*f).a oppuref->a

f

c

b

a

Page 10: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1010 - -

AreaArea

Scrivere un programma che, sfruttando le funzioni, permetta di calcolare l’area di un cerchio o di un quadrato.L’utente inserisce un numero, dichiarando se si tratta del raggio di un cerchio o del lato di un quadratoSe l’utente inserisce un numero negativo viene visualizzato un errore, altrimenti il sistema calcola l’area in modo appropriato.

Page 11: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1111 - -

AreaArea

#include <stdio.h>#define PI 3.1415#define NUMERO_NEGATIVO -1;#define NO_ERRORE 0;

typedef enum {quadrato, cerchio} Forma;typedef struct{

Forma qualeForma;float a;float area;

} InfoFigura; .

Page 12: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1212 - -

AreaArea

int calcolaArea (InfoFigura *f){

if ((*f).a < 0){

return NUMERO_NEGATIVO;}if ((*f).qualeForma == quadrato){

(*f).area = (*f).a * (*f).a;}else{

(*f).area = (*f).a * (*f).a * PI;}return NO_ERRORE;

} .

Page 13: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1313 - -

AreaArea

void main(){

InfoFigura figura;int errore;

printf ("Figura (0=quadrato, 1=cerchio)? ");scanf ("%u", &figura.qualeForma);printf ("lato o raggio: ");scanf ("%f", &figura.a);errore = calcolaArea (&figura);if (errore == NO_ERRORE){

printf ("Area: %f", figura.area);}

} .

Page 14: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1414 - -

Richiamo: array e puntatoriRichiamo: array e puntatori

Il nome dell’array, usato senza le parentesi, rappresenta l’indirizzo in memoria della prima cella(ovvero, un puntatore ad essa)L’indirizzo non può essere modificato (ovvero, il nome rappresenta un puntatore costante)E’ possibile definire un puntatore ed usarlo come array!

int vettA[4], vettB[4];int *pIntero;…pIntero = vettA; /* Corretto: pIntero punta a vettA */pIntero[1] = 3; /* Corretto: pIntero come array */vettB = vettA; /* Errore di compilazione! */vettA = pIntero; /* Errore di compilazione! */

Page 15: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1515 - -

Parametri arrayParametri array

Sfrutta le caratteristiche di puntatori e arrayDefinizione:void funzione (float *v1, char *v2){

v1[3] = 1.125; /* v1 come array */v2[15] = 'z'; /* v2 come array */

}

Chiamata:float a[10];char b[20];funzione (a, b); /*senza & perché nome è puntatore*/

Definizione equivalente: void funzione (float v1[], char v2[])

Passaggio per indirizzo!

Page 16: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1616 - -

Media e varianzaMedia e varianza

Scrivere un programma che, utilizzando le funzioni, calcoli la media e la varianza di un array di numeri realiUtilizzare le funzioni:

leggi(): permette di inserire il vettore di numerimedia(): calcola e ritorna la mediavarianza(): calcola e ritorna la varianzascrivi(): visualizza il vettore, la media e la varianza.

Page 17: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1717 - -

Media e varianzaMedia e varianza

#include <stdio.h>#include <math.h>

void leggi (float vet[], unsigned int lungh){

unsigned int i;

for (i = 0; i < lungh; i++){

printf ("Numero: ");scanf ("%f", &vet[i]);

}}

Non si usa return perché vet è passato per indirizzo.

Page 18: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1818 - -

Media e varianzaMedia e varianza

float media (float vet[], unsigned int lungh){

unsigned int i;float m = 0;

for (i = 0; i < lungh; i++){

m = m + vet[i];}return m / lungh;

} .

Page 19: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 1919 - -

Media e varianzaMedia e varianza

float varianza (float vet[], unsigned int lungh, float media){

unsigned int i;float v = 0;

for (i = 0; i < lungh; i++){

vet[i] = pow (vet[i] - media, 2.0);}for (i = 0; i < lungh; i++){

v = v + vet[i];}return v / (lungh – 1);

} .

Page 20: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 2020 - -

Media e varianzaMedia e varianza

void scrivi (float vet[], unsigned int lungh, float med, float var){

unsigned int i;

for (i = 0; i < lungh; i++){

printf ("%f\n", vet[i]);}printf ("Media: %f, varianza: %f", med, var);

}

Page 21: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 2121 - -

Media e varianzaMedia e varianza

void main(){

const unsigned int MAX = 3;float array[MAX];float m, v;leggi (array, MAX); /* non uso & */m = media (array, MAX);v = varianza (array, MAX, m); scrivi (array, MAX, m, v);

}Side effect su array

Cosa visualizza la funzione scrivi() ?

Non funziona! Serve un altro vettore in cui salvare array prima che venga modificato.

Page 22: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 2222 - -

Media e varianzaMedia e varianza

void main(){

const unsigned int MAX = 3;float array[MAX], copia[MAX];float m, v;unsigned int i;leggi (array, MAX); /* non uso & */m = media (array, MAX);for (i = 0; i < MAX; i++){

copia[i] = array[i];}v = varianza (array, MAX, m); scrivi (copia, MAX, m, v);

}

Side effect su array

Adesso scrivi() stampa il vettore corretto

Page 23: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 2323 - -

Copia di Copia di structstruct con campi con campi puntatorepuntatore

Se la struct contiene dei puntatori:

typedef struct{

int *a;int b[2];

}Tipo;int w[2]={5,6};Tipo x, y;

x.a = w;x.b[0] = 7;x.b[1] = 8;y = x;

y

a

b 7 8

a

b 7

x

w 5

8

6

Avrò un alias (x.a e y.a puntano alla stessa variabile).

Page 24: Politecnico di Milano Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri

- - 2424 - -

Riassumendo: quando usare…Riassumendo: quando usare…

Passaggio parametri per copia (o per valore):La funzione deve ritornare un solo valore (e quindi basta usare il return); i parametri sono “parametri di input”

Passaggio parametri per indirizzo:La funzione deve ritornare più valori (e quindi non basta usare il return) e non voglio usare variabili globali;i parametri sono “parametri di input/output”

Caso particolare: gli arrayIl nome dell’array rappresenta l’indirizzo in memoria della prima cellaPassando l’array come parametro, ne passo in realtà l’indirizzoQuindi, gli array sono sempre passati per indirizzo e non per copia (possibili side effect).