Struttura della lezione Lezione 6: Array e puntatori Vittorio Scarano Laboratorio di Informatica I Corso di Laurea in Informatica Università degli Studi di Salerno Una funzione per i numeri di Fibonacci Array Passaggio di parametri per riferimento di array Puntatori (cenni iniziali) definizione Passaggio di parametri per riferimento Una funzione per Fibonacci Array #define LIMIT 0 int fib (void); int i; printf ("Fib(0)=0\n"); printf ("Fib()=\n"); for (i=; i< LIMIT; i++) printf ("Fib(%d)=%d\n", i, fib()); int fib () static int f0=0, f=; int f; f = f0 + f; f0 = f; return ( f = f ); Prototipo di fib(void) Variabili statiche vengono allocate la prima volta che fib è chiamata non vengono deallocate 3 4 Un array è una collezione di dati ordinata è possibile contare gli elementi omogenea tutti i dati hanno lo stesso tipo Ogni valore nell array è un elemento Non è possibile avere nello stesso array elementi di tipo diverso Una visione dell array Dichiarazione di un array 0 3 4 5 Un insieme di contenitori numerati a partire da 0 che contengono valori dello stesso tipo Un array è caratterizzato da il tipo (comune) degli elementi la dimensione Per dichiarare un array si deve specificare: tipo nome (identificativo) dimensione tipoelemento identificativo[dimensione] 5 6
Alcune dichiarazioni Un esempio di array La dimensione degli array è costante stabilita durante la compilazione Consigliabile usare le costanti simboliche Esempi: int float voti[30]; velocita[0]; #define NUM_STUDENTI 30.. int voti[num_studenti]; 0 3 4 5 6 Dichiarazione int voti [ 7 ]; Da notare: la dimensione è 7 gli elementi sono numerati a partire da 0 7 8 Selezione di elementi in un array Un esempio di uso: media di voti Per riferire un elemento di un array si usa l identificativo dell array e l indice della sua posizione Esempio: voti [ ] = 8; voti [ ] = voti [ ] + 3; voti [ 5 ] = 30; 8 30 0 3 4 5 6 9 /* gym.c: media dei voti dei giudici */ #include <stdio.h> #define NUM_GIUD 5 double totale, voti[num_giud]; int i; for (i = 0 ; i < NUM_GIUD; i++) printf ( Inserire voto giud %d, i+); scanf ( %lf, &voti[i]); for (i = totale = 0 ; i < NUM_GIUD; i++) totale + = voti[i]; printf ( Media: %lf\n, totale/num_giud); Dichiarazione voti Input nell array L utente conta da! Memorizzazione Calcolo totale inizializzazione e conversione implicita 0 Rappresentazione interna dei dati Rappresentazione interna di un array I dati vengono memorizzati in bytes Ogni byte ha un indirizzo La allocazione di variabili di tipo tipo alloca tanti byte quanto sizeof(tipo) Esempi: char carat; int indice; double totale: carat indice totale 000 003 004 005 006 007 008 00 0 0 03 04 05 Locazioni consecutive a partire da un indirizzo di partenza Per int voti[5]; Per accedere a voti[3] il compilatore somma indirizzo dell array (000) 3 * sizeof (int) ottenendo l indirizzo 006 Se accedo a voti[6]? Si somma 000 + 6* sizeof (int) ottenendo l indirizzo 0! voti[0] voti[] voti[] voti[3] voti[4]!!!!!!! 000 003 004 005 006 007 008 00 0 0 03 04 05
Inizializzazione di array Un esempio di uso: trovare il minimo In ANSI C è possibile inizializzare un array quando lo si dichiara Esempi: int a[3] =,, ; float f[5] = 0., 0., 0.3,.5,.0; int b[] =,, 3, 4; /* dichiara b di 4 elementi */ /* minimo.c: ricerca del minimo */ #include <stdio.h> #define DIM 5 int i, min, num [DIM]; for (i = 0 ; i < DIM; i++) printf ( Inserire numero %d:, i+); scanf ( %d, &num[i]); for (i =, min = num[0] ; i < DIM; i++) min= (min < num[i])? min: num[i]; printf ( Il minimo e %d\n, min); Dichiarazione num Input nell array Calcolo min inizializzazione a num[0] assegnazione nuovo valore se minore del minimo 3 4 Array palindromo Un esempio di uso: array palindromo Un array di N elementi è palindromo: se i valori letti dal primo all ultimo elemento sono uguali ai valori letti dall ultimo al primo elemento SI NO SI 3 4 3 0 3 4 5 6 4 4 4 0 3 4 5 6 3 4 4 3 0 3 4 5 5 /* palind.c: controlla se array palindromo */ #include <stdio.h> #define DIM 5 /* dimensione dispari */ #define TRUE int i, palindromo = TRUE, num [DIM]; for (i = 0 ; i < DIM; i++) printf ( Inserire numero %d:, i+); scanf ( %d, &num[i]); for (i = 0; palindromo && i < DIM/ ; i++) palindromo=(num[i] == num[ DIM- i- ]); if (palindromo) printf ( E palindromo..\n ); else printf ( Non e palindromo..\n ); Costanti simbolica Input nell array palindromo viene inizializzato a TRUE L indice i copre la prima metà dell array Si esce dal for con palindromo a FALSE palindromo a TRUE perchè i ha scorso tutta la prima metà 6 Idiomi di programmazione e funzioni Passaggio di parametri per riferimento E utile implementare idiomi ricorrenti con funzioni. Alcuni esempi per gli array: input di un array di interi output di un array di interi Problema: come si fa a passare un array come parametro? Gli array possono essere passati come parametri ad una funzione Quando si passa una variabile, il passaggio avviene per valore viene creata una variabile locale nella quale viene copiato il valore della variabile passata quindi, le modifiche sul parametro formale (variabile locale) non si riflettono sul parametro attuale (variabile passata come parametro) 7 8 3
Passaggio di array come parametri Un esempio: una funzione per l input Ogni array ha un indirizzo di memoria a partire dal quale è memorizzato Esistono diverse maniere per usare l indirizzo di un array int a[0] semplicemente specificando il nome dell array a indica l indirizzo di partenza dell array a Ad una funzione è possibile passare l indirizzo di memorizzazione dell array le modifiche effettuate nella funzione sono sull array passato non su una copia! 9 /* funz.c: somma un array */ #define SIZE 7 void inputarray (int[ ], int); int i, num[size], sum=0; inputarray (num, SIZE); for (i = 0 ; i < SIZE; i++) sum + = num [i]; printf ( Somma =%d \n, sum); void inputarray (int a[ ], int dim) int i; for (i=0; i< dim; i++) printf ( Inserire elemento %d:, i+); scanf ( %d, &a[i]); Prototipo di inputarray primo parametro è un array (per riferimento) secondo parametro è passato per valore Input dell array Calcolo e output della somma Definizione funzione 0 Altro esempio: una funzione di somma Un esercizio /* funz.c: somma un array */ #define SIZE 7 void inputarray (int[ ], int); int somma(int [ ], int); int num[size]; inputarray (num, SIZE); printf ( Somma =%d \n, somma(num,size) ); Prototipo di inputarray e di somma Input dell array Calcolo e output della somma Definizione funzione somma La definizione di inputarray è la stessa int somma (int a[ ], int dim) int i, sum=0; for (i = 0 ; i < dim; i++) sum + = a [i]; return (sum); Scrivere un programma che prende in input un array di 0 interi e restituisce il numero di interi nell array che sono il prodotto di due interi inseriti nell array Commenti: uso della funzione inputarray() per calcolare il risultato: ho bisogno di tutte le terne di indici distinti per generarle uso 3 cicli E la soluzione.. I puntatori #define DIM 0 void inputarray (int a[ ], int size); int arr[dim]; int result = 0; int i, j, k; inputarray (arr, DIM); Prototipo di inputarray primo parametro è un array (per riferimento) secondo parametro è passato per valore Input dell array Generazione di tre indici distinti: i,j,k Calcolo result for (i=0; i < DIM-; i++) for (j=i+; j < DIM-; j++) for (k = j+; k < DIM; k++) result += (arr[i]*arr[j]== arr[k])+ (arr[i]*arr[k]== arr[j])+ (arr[j]*arr[k]== arr[i]); printf ("result=%d\n", result); a = &b; 3 4 Una variabile viene memorizzata in una o più locazioni di memoria Per una variabile var: &var rappresenta l indirizzo della variabile Puntatori: variabili che contengono indirizzi Esempio int *a; int b; 4
Rappresentazione interna dei puntatori Passaggio di parametri int *a; int b; a = &b; La variabile a è un puntatore La variabile b è un intero Il puntatore a contiene l indirizzo di b a b 000 003 004 005 006 007 008 00 0 0 03 04 Passaggio di parametri per valore: il valore del parametro attuale viene copiata nel parametro formale (variabile locale) conseguenza: modifiche apportate all interno della funzione non hanno effetto sulle variabili passate alla funzione Un problema di esempio: scrivere una funzione che effettui lo scambio (swap) di valore tra due interi. 05 5 6 Una soluzione (sbagliata!) Perchè wrongswap() non funziona? void wrongswap (int, int); int i=, j=; /* Stampa i=, j= */ wrongswap (i, j); /* Stampa sempre i=, j=!*/ Prototipo della funzione wrongswap() Esempio di uso: inizializzo i e j ne stampo il valore effettuo lo scambio ne ristampo il valore wrongswap(int,int): dichiara variabile temp scambia a e b usando void wrongswap (int a, int b) void wrongswap (int a, int b) int temp; int temp; temp = a; temp = a; a = b; a = b; b = temp; b = temp; temp. 7 8 Quando passo i e j a wrongswap i valori sono copiati in a e b Le modifiche (swap) sono effettuate su a e b che sono locali wrongswap (i, j); i j a b temp X X Passaggio di parametri per riferimento La soluzione giusta Alla funzione vengono passati i riferimenti delle variabili, cioè gli indirizzi In questa maniera la funzione modificherà le variabili i cui indirizzi sono stati passati Modifiche necessarie: alla funzione devono essere passati gli indirizzi i parametri devono essere indicati come puntatori 9 void swap (int *, int *); int i=, j=; /* Stampa i=, j= */ swap (&i, &j); /* Stampa i=, j=!*/ void swap (int *a, int *b) int temp; temp = *a; *a = *b; *b = temp; Prototipo: i parametri sono puntatori ad interi Chiamata di swap: gli indirizzi di i e j La funzione swap dichiara variabile temp mette in temp il valore puntato da a mette nella variabile puntata da a il valore puntato da b mette nella variabile puntata da b il valore di temp 30 5
Perchè swap() funziona? Esercizi Quando passo &i e &j i valori degli indirizzi sono copiati in a e b Le modifiche (swap) sono effettuate su *a e *b e quindi su i e j! void swap (int *a, int *b) int temp; temp = *a; *a = *b; *b = temp; swap (&i, &j); i j a b temp X X 3 Scrivere dei programmi strutturati con funzioni che: prende in input 0 interi in un array e ne trova il massimo prende in input 0 interi in un array e trova i primi 3 massimi spostandoli in coda all array prende in input 0 interi in un array e li ordina in ordine crescente prende in input 0 interi in un array e inverte l array 3 Esercizi Esercizi Scrivere una funzione is_prime(int n) che restituisca se n è primo e 0 altrimenti Scrivere una funzione is_fib(int n) che restituisca se n è un numero di Fibonacci e 0 altrimenti Scrivere una funzione fattorizza (int n, int fattori[]) che fattorizza (trova i fattori) di un intero n, li mette nell array fattori e ne restituisce il Scrivere una funzione prodotto che prende un intero k (non primo) e restituisce due interi a e b tali che k=a*b Scrivere una funzione ricorsiva ric_ciao (int n) che stampi Ciao per tante volte quanto vale n numero alla funzione chiamante 33 34 6