420 likes | 620 Views
Array e puntatori. Corso di Informatica A Vito Perrone. Indice. Tipi di dati strutturati: Array Puntatori Tipi di dati strutturati: Array Esempio. I tipi strutturati: 1. Il costruttore array. Definizione del nuovo tipo anArray : typedef int anArray[20];
E N D
Array e puntatori Corso di Informatica A Vito Perrone
Indice • Tipi di dati strutturati: Array • Puntatori • Tipi di dati strutturati: Array • Esempio Strutture di controllo in C Informatica A – V. Perrone
I tipi strutturati:1.Il costruttore array • Definizione del nuovo tipo anArray:typedef int anArray[20]; • dichiazione di variabili di tipo anArray:anArray lista1, lista2; • La dichiarazione:int lista[20]; • Va perciò interpretata come un’abbreviazione per:typedefint arrayAnonimo[20];arrayAnonimo lista; Strutture di controllo in C Informatica A – V. Perrone
Quando esplicitare il nome del tipo? • Dichiarazione mediante nuovo tipo: • typedef doubleVettoreDiReali[20]; • VettoreDiReali v1, v2, v3; • Più semplice e altrettanto chiara: • double v1[20], v2[20], v3[20]; • Dichiarazione mediante nuovi tipi: • typedef double PioggeMensili[12]; • typedef double IndiciBorsa[12]; • PioggeMensili Piogge01, Piogge02, Piogge03; • IndiciBorsa Indici01, Indici02, Indici03; • Preferibile a: • double Piogge01[12], Piogge02[12],Piogge03[12], Indici01[12], Indici02[12], Indici03[12]; Strutture di controllo in C Informatica A – V. Perrone
Matrici • E’ possibile definire un array di array (una matrice): • typedef intVettore[20]; • typedefVettore MatriceIntera20Per20[20]; • MatriceIntera20Per20 matrice1; • Oppure, più brevemente: • typedefint MatriceIntera20Per20[20][20]; MatriceIntera20Per20 matrice1; • Anche una matrice può essere definita in modo abbreviato: • int matrice1[20][20]; • E’ possibile definire array di array di array…: • int matriceTridimensionale1[10][20][30]; • Per accedere agli elementi di matriceTridimensionale1: • matriceTridimensionale1[2][8][15] • colore ListaColori[10]; Strutture di controllo in C Informatica A – V. Perrone
Dimensione degli array • Un array ha dimensioni fisse minor flessibilità del linguaggio typedef charString[30]; String Nome, Cognome; • Parole corte provocano spreco di memoria (fisica) • Parole lunghe: dovremmo anche prevedere istruzioni del tipo: if(LunghezzaParola == 30) printf("Parola troppo lunga"); • Perché?Principio dell’allocazione statica della memoria. Strutture di controllo in C Informatica A – V. Perrone
Un parziale rimedio (1) /* Programma InvertiSequenza */ #include <stdio.h> main() { int Contatore; int Memorizzazione[100]; Contatore = 0; while (Contatore < 100) /* si ricordi che il valore dell'indice di un array di 100 elementi varia da 0 a 99 */ { scanf("%d", &Memorizzazione[Contatore]); Contatore = Contatore + 1; } … Strutture di controllo in C Informatica A – V. Perrone
Un parziale rimedio (2) /* Programma InvertiSequenza (continuazione) */ … Contatore = Contatore – 1; while (Contatore >= 0) { printf("%d\n", Memorizzazione[Contatore]); Contatore = Contatore – 1; } } E se invece di 100 la sequenza fosse lunga 1000? Strutture di controllo in C Informatica A – V. Perrone
Un parziale rimedio (3) /* Program InvertiSequenza */ #include <stdio.h> #define LunghezzaSequenza 100 main() { int Contatore; int Memorizzazione[LunghezzaSequenza]; Contatore = 0; while (Contatore < LunghezzaSequenza) { scanf("%d", &Memorizzazione[Contatore]); Contatore = Contatore + 1; } … Strutture di controllo in C Informatica A – V. Perrone
Un parziale rimedio (4) /* Program InvertiSequenza (continuazione) */ … Contatore = Contatore – 1; while (Contatore >= 0) { printf("%d\n", Memorizzazione[Contatore]); Contatore = Contatore – 1; } } NB: la stessa cosa non si poteva fare con la dichiarazione const Strutture di controllo in C Informatica A – V. Perrone
Assegnamento tra array: attenzione! • Dati i seguenti array:typedef intanArray[10]; anArray Array1, Array2; • L’istruzione:Array2 = Array1; • E’ scorretta! • Sarà necessaria un’istruzione ciclica che “scorra” i singoli elementi dell’array • i = 0; while (i < 10) array2[i] = array1[i]; • Capiremo il perché in seguito Strutture di controllo in C Informatica A – V. Perrone
Programma concatenazione stringhe (1) #include <stdio.h> #define LunghezzaArray 50 main() { int i, j, k; char TempCar; char Array1[LunghezzaArray], Array2[LunghezzaArray]; /* Nella seguente dichiarazione il valore LunghezzaArray]*2 è un valore costante calcolato a tempo di compilazione */ char ArrayConc[LunghezzaArray*2]; /* Legge la prima stringa assicurandosi che essa non superi la dimensione dell'array, 50 caratteri /* i = 0; while (i < LunghezzaArray) /* Si ricordi che il valore dell'indice di un array di LunghezzaArray elementi è compreso fra 0 e LunghezzaArray–1 */ { scanf("%c", &TempCar); Array1[i] = TempCar; i = i + 1; } … Strutture di controllo in C Informatica A – V. Perrone
Programma concatenazione stringhe (2) … /* Legge la seconda stringa assicurandosi che essa non superi la dimensione dell'array, 50 caratteri /* i = 0; while (i < LunghezzaArray) { scanf("%c%, &TempCar); Array2[i] = TempCar; i = i + 1; } /* Confronta le due stringhe per capire quale precede l'altra in ordine alfabetico */ i = 0; while (i < LunghezzaArray && Array1[i] == Array2[i]) i = i+1; if (i == LunghezzaArray || Array1[i] < Array2[i]) /* Le due stringhe sono uguali o la prima precede la seconda in ordine alfabetico */ … Strutture di controllo in C Informatica A – V. Perrone
Programma concatenazione stringhe (3) … /* Le due stringhe sono uguali o la prima precede la seconda in ordine alfabetico */ { k = 0; j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array1[j]; k = k + 1; j = j + 1; } j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array2[j]; k = k + 1; j = j + 1; } } else … Strutture di controllo in C Informatica A – V. Perrone
Programma concatenazione stringhe (4) … /* Se la seconda stringa precede la prima in ordine alfabetico, ossia se (Array2[i] < Array1[i]) */ { k = 0; j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array2[j]; k = k + 1; j = j + 1; } j = 0; while (j < LunghezzaArray) { ArrayConc[k] = Array1[j]; k = k + 1; j = j + 1; } } /* Stampa la stringa ottenuta dalla concatenazione */ k = 0; while (k < (LunghezzaArray*2)) {printf("%c", ArrayConc[k]); k = k + 1;} } Strutture di controllo in C Informatica A – V. Perrone
Alcune precisazioni sugli array 1/2 • La dichiarazione: int a[100]; alloca memoria per 100 elementi interi, a partire da un certo indirizzo di memoria scelto dal calcolatore • n.b. il numero degli elementi dell’array e la dimensione del tipo base devono essere noti al compilatore • Per accedere a un elemento dell’array a • Si calcola il valore dell’indice (può essere una espressione qualsiasi purchè produca un risultato di tipo integral) • Si somma il valore calcolato moltiplicato per la dimensione (in byte) del tipo base all’indirizzo della prima cella dell’array • Esempio: • Supponendo che l’array a sia allocato a partire dal byte 10000 in memoria. L’elemento a[3] corrisponde all’indirizzo 10000+3*dimInt = 10012 supponendo che un int sia rappresentato con 32 bit (4 byte) • Importante: non viene fatto alcun controllo sul rispetto dei limiti dell’array (Tipico errore) Strutture di controllo in C Informatica A – V. Perrone
Alcune precisazioni sugli array 2/2 • Le stringhe in C sono array di caratteri terminate dal carattere speciale ‘\0’ • Esempio: • char parola[20]; • scanf(“%s”, parola); /* si noti l’assenza del & */ • printf(“%c”, parola[0]); • Esercizio: ….. Strutture di controllo in C Informatica A – V. Perrone
Il costruttore puntatore (1) P Valore di tipoTipoDato • Dichiarazione di una variabile puntatore:typedef TipoDato *TipoPuntatore; • Dereferenziazione: *P indica la cella di memoria il cui indirizzo è contenuto in PtypedefTipoDato *TipoPuntatore; TipoPuntatore P; TipoDato x; Strutture di controllo in C Informatica A – V. Perrone
Il costruttore puntatore (2) • L’operatore unario & significa “indirizzo di” ed è il duale dell’operatore ‘*’.typedefTipoDato *TipoPuntatore; TipoPuntatore P, Q; TipoDato y, z;P = &y; Q = &z; P = Q; • y e z sono di tipo TipoDato mentre P e Q sono puntatori a variabili di tipo TipoDato. Strutture di controllo in C Informatica A – V. Perrone
P 14 P = 14; x 23 x = 23; P 23 *P = x; x 23 Esempi (1) Strutture di controllo in C Informatica A – V. Perrone
P 14 x 23 P 14 x = *P; x 14 Esempi (2) Strutture di controllo in C Informatica A – V. Perrone
y P 14 P = &y; z Q 23 Q = &z; Esempi (3) P = Q; • Attenzione: è vero che P = Q; *P = *Q; ?? Strutture di controllo in C Informatica A – V. Perrone
Puntatori e tipi typedef TipoDato *TipoPuntatore; typedef AltroTipoDato *AltroTipoPuntatore; TipoDato *Puntatore; TipoDato **DoppioPuntatore; TipoPuntatore P, Q; AltroTipoPuntatore P1, Q1; TipoDato x, y; AltroTipoDato z, w; istruzioni corrette:istruzioni scorrette: Puntatore = &y; P1 = P; (warning) DoppioPuntatore = &P; w = *P; (error) Q1 = &z; *DoppioPuntatore = y; (warning) P = &x; Puntatore = DoppioPuntatore;(warning) P = Q; *P1 = *Q; (error) *P = *Q; *Puntatore = x; P = *DoppioPuntatore; z = *P1; Puntatore = P; Strutture di controllo in C Informatica A – V. Perrone
Valore iniziale di un puntatore • Il valore iniziale di un puntatore dovrebbeessere NULL • NULL significa che non si riferisce ad alcuna celladi memoria • Dereferenziando NULL si ha un errore inesecuzione • Non fare MAI affidamento sulleinizializzazioni implicite delle variabili che Cpotrebbe fare (alcune implementazioni lo fannoa NULL, molte altre no) Strutture di controllo in C Informatica A – V. Perrone
Aritmetica tra puntatori 1/3 • C permette operazioni di somma e sottrazione tra puntatori • Il valore viene incrementato di un multiplo dell’ingombro (sizeof) del tipo puntato • Esempio: • int i; • IntRef p = &i; • p = p + 5; • Se supponiamo che i sia allocata alla cella 1000 allora l’assegnamento p = &i assegna a p il valore 1000 e l’assegnamento p = p + 5 assegna a p il valore 1020 (si suppone che sizeof(int) sia 4) Strutture di controllo in C Informatica A – V. Perrone
Aritmetica tra puntatori 2/3 • Sia: • int a[5]; • int i; • int * p; • Allora: • – a[i] è equivalente a *(a+i) • – p = a è equivalente a p = &a[0] • – p = a+1 è equivalente a p = &a[1] • – a = p errore, a è puntatore costante • – a = a + 1 errore, a è puntatore costante • – p = p + 1 corretto Strutture di controllo in C Informatica A – V. Perrone
Aritmetica tra puntatori 3/3 • Se p e q puntano a due diversi elementi di un array • p – q dà la distanza nell’array tra gli elementi puntati • Questo in generale non coincide con la differenza “aritmetica” tra il valore dei puntatori • Esempio: Se p e q sono puntatori a int e sizeof(int) è 4 e p è 1000 e q è 1040 allora: • p – q è 10 e non 40 Strutture di controllo in C Informatica A – V. Perrone
Array e puntatori (1) • L’operatore sizeof produce il numero di byte occupati da ciascun elemento di un array o da un array nel suo complesso. • Se si usano quattro byte per la memorizzazione di un valore int: • inta[5]; • Allora: • sizeof(a[2]) • Restituisce il valore 4 e: • sizeof(a) • Restituisce il valore 20. • Il nome di una variabile di tipo array viene considerato in C come l’indirizzo della prima parola di memoria che contiene il primo elemento della variabile di tipo array (lo 0-esimo …). • Se ne deduce: • a “punta” a una parola di memoria esattamente come un puntatore; • a punta sempre al primo elemento della variabile di tipo array (è un puntatore “fisso” al quale non è possibile assegnare l’indirizzo di un’altra parola di memoria). Strutture di controllo in C Informatica A – V. Perrone
Array e puntatori (2) • Il C consente di eseguire operazioni di somma e sottrazione su puntatori. • Se p e a forniscono l’indirizzo di memoria di elementi di tipo opportuno, p+i e a+i forniscono l’indirizzo di memoria dell’i-esimo elemento successivo di quel tipo • Se iè unavariabile intera: la notazione a[i] è equivalente a *(a+i) • Analogamente, se p è dichiarato come puntatore a una variabile di tipo int:la notazione p[i] è equivalente a *(p+i). • Ne segue che: • p = a è equivalente ap = &a[0]; • p = a+1 è equivalente ap = &a[1]; • Mentre non sono ammessi assegnamenti ad a del tipo: • a = p; • a = a +1; Strutture di controllo in C Informatica A – V. Perrone
Array e puntatori (3) • Se p e q puntano a due diversi elementi di un array, • p–q restituisce un valore intero pari al numero di elementi esistenti tra l’elemento cui punta p e l’elemento cui punta q. • Non la differenza tra il valore dei puntatori. • Supponendo che il risultato di p–q sia pari a 3 e supponendo che ogni elemento dell’array sia memorizzato in 4 byte, la differenza tra l’indirizzo contenuto in p e l’indirizzo contenuto in q darebbe 12. Strutture di controllo in C Informatica A – V. Perrone
I tipi strutturati:2.Il costruttore struct • Tipo impiegato: nome, cognome, codice fiscale, indirizzo, numero di telefono, eventuali stipendio, data di assunzione e via di seguito. • Tipo famiglia: un certo insieme di persone, un patrimonio, costituito a sua volta da un insieme di beni, ognuno con un suo valore, un reddito annuo, spese varie, … • Queste strutture informative sono eterogenee: l’array non si presta a questo tipo di aggregazione. • Il costruttore di record (parola chiave struct in C) è la risposta a questo tipo di esigenze. Strutture di controllo in C Informatica A – V. Perrone
Esempi (1) typedef charString[50]; typedef struct{ int Giorno; int Mese; int Anno; } Data; typedef struct{ String Destinatario; intImporto; Data DataEmissione; } DescrizioneFatture; Strutture di controllo in C Informatica A – V. Perrone
Esempi (2) typedef enum{On, Off}AccType; typedef struct {intCanale; AccType Accensione; double CursoreLuminosita,CursoreColore,CursoreVolume; } CanaliTV; Strutture di controllo in C Informatica A – V. Perrone
Esempi (3) typedef enum{Dirigente, Impiegato, Operaio} CatType; typedefstruct{ String Nome; String Cognome; int Stipendio; char CodiceFiscale[16]; Data DataAssunzione; CatType Categoria; } Dipendenti; Strutture di controllo in C Informatica A – V. Perrone
Dichiarazione di variabili • La dichiarazione di variabili procede poi come al solito:Dipendenti Dip1, Dip2; • Oppure è possibile definire il nuovo tipo in forma anonima e nello stesso tempo dichiarare le variabili:struct {String Nome; String Cognome; intStipendio; charCodiceFiscale[16]; Data DataAssunzione; CatType Categoria; }Dip1, Dip2; Strutture di controllo in C Informatica A – V. Perrone
Accesso alle componenti del record • Per accedere alle singole componenti del record, si usa una notazione detta dot notation: • Dip1.Stipendio = Dip1.Stipendio + (Dip1.Stipendio*10) / 100; • Dip1.DataAssunzione.Giorno = 3; • Dip1.DataAssunzione.Mese = 1; • Dip1.DataAssunzione.Anno = 1993; • if (Dip1.Cognome[0] == 'A') … • DichiarazioneFatture ArchivioFatture[1000]; • if (ArchivioFatture[500].DataEmissione.Anno <= 2000) • printf("%d", ArchivioFatture[500].Importo); • else • printf("La fattura in questione è stata emessa dopo il 2000\n"); Strutture di controllo in C Informatica A – V. Perrone
Una tipica abbreviazione del C... • Definiamo un record e dichiariamo una variabile puntatore: • typedef struct{int PrimoCampo; char SecondoCampo; • } TipoDato; TipoDato x, *P; P = &x; • Accesso al campo PrimoCampo di x, attraverso il puntatore P, usando la dot notation:(*P).PrimoCampo = 12; /* Inserisce 12 nel campo PrimoCampo di x */ • Esiste una sistassi abbreviata: • P–>PrimoCampo = 12; /* Inserisce 12 nel campo PrimoCampo di x */ Strutture di controllo in C Informatica A – V. Perrone
Assegnamento tra record • Una stranezza del C: come abbiamo visto, non è permesso scrivere un assegnamento tra arrayArray2 = Array1; • Invece:Dip1 = Dip2; • E’ lecito e fa esattamente ciò che ci si aspetta: copia l’intera struttura Dip1 in Dip2, comprese le sue componenti che sono costituite da array! • Il perché di questa stranezza risiede nel modo in cui in C sono realizzati gli array e potrà essere capito tra breve Strutture di controllo in C Informatica A – V. Perrone
Programma Dirigenti (1) /* Programma Dirigenti */ #include <stdio.h> main() { typedef enum{ dirigente, impiegato, operaio CatLav; typedef struct{ char Nome[30]; char Cognome[30]; CatLav Categoria; int Stipendio; char CodiceFiscale[16]; } Lavoratore; Lavoratore DatiLavoratori[300]; Lavoratore *Management[10]; ... Strutture di controllo in C Informatica A – V. Perrone
Programma Dirigenti (2) /* Programma Dirigenti (continuazione) */ ... i = 0; while (i < 10) { if (Management[i]–>Stipendio > 5000000) { j = 0; while (j < 30) { printf("%c", Management[i]–>Cognome[j]); j = j + 1; } printf("%d \n", Management[i]–>Stipendio); } } i = i + 1; } Strutture di controllo in C Informatica A – V. Perrone
Attenzione ai “rischi” dei puntatori • Effetti collaterali (side effects): • *P = 3; • *Q = 5; • P = Q; • /* a questo punto *P = 5 */ • *Q = 7; • A questo punto*Q = 7, ma anche*P = 7 • Un assegnamento esplicito alla variabile puntata daQdetermina un assegnamento nascosto alla variabile puntata daP. • Caso particolare di aliasing, ovvero del fatto che uno stesso oggetto viene identificato in due modi diversi. Strutture di controllo in C Informatica A – V. Perrone
Riassumendo e completando • Operazioni applicabili a variabili puntatori: • assegnamento dell’indirizzo di una variabile tramite l’operatore unario &; • assegnamento del valore di un altro puntatore; • assegnamento del valore speciale NULL. Se una variabile puntatore ha valore NULL, *P è indefinito: P non punta ad alcuna informazione significativa. • l’operazione di dereferenziazione, indicata dall’operatore *; • il confronto basato sulle relazioni ==, !=, >, <, <=, >=; • operazioni aritmetiche • l’assegnamento di indirizzi di memoria a seguito di operazioni di allocazione esplicita di memoria (gli ultimi due casi verranno trattati in seguito); Strutture di controllo in C Informatica A – V. Perrone