La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

2000 Prentice Hall, Inc. All rights reserved. Capitolo 10 (Deitel) Strutture, unioni ed enumerazioni Sommario 10.1 - Introduzione 10.2 - Definire le strutture.

Presentazioni simili


Presentazione sul tema: "2000 Prentice Hall, Inc. All rights reserved. Capitolo 10 (Deitel) Strutture, unioni ed enumerazioni Sommario 10.1 - Introduzione 10.2 - Definire le strutture."— Transcript della presentazione:

1 2000 Prentice Hall, Inc. All rights reserved. Capitolo 10 (Deitel) Strutture, unioni ed enumerazioni Sommario Introduzione Definire le strutture Dichiarare e inizializzare le strutture Accedere ai membri delle strutture Usare le strutture con le funzioni Ridenominazione di tipi con typedef Caso di studio: un efficiente mescolatore/distributore di carte Le Unioni Le costanti di Enumerazione

2 2000 Prentice Hall, Inc. All rights reserved Introduzione I vettori –Permettono di memorizzare una serie di dati omogenei in tipo –Si può accedere ad ogni singolo dato specificandone lindice/posizione –Ma come memorizzare una serie di dati non necessariamente omogenei? Ad esempio, come memorizzare i dati di una persona (nome, indirizzo, età,..)? Si deve davvero dichiarare una variabile per ogni tipo di dato della persona e duplicarla N volte per il numero di persone da memorizzare? Le strutture –Sono raggruppamenti di variabili correlate (aggregati) sotto un unico nome Tale nome indica il tipo di struttura, che è definito dal programmatore Possono contenere variabili eterogenee in tipo (in genere tra quelli base del C) Numero/tipo di variabili che definiscono una struttura è dato dal programmatore Sono come vettori senza vincolo di avere elementi tutti dello stesso tipo e i cui elementi non sono identificati da un indice, ma da un nome –Sono usate comunemente per definire i record da salvare nei file –Se combinate con i puntatori, permettono di creare liste concatenate ed altre strutture dati dinamiche complesse (come pile, code e alberi)

3 2000 Prentice Hall, Inc. All rights reserved Definire le strutture (1/2) Sintassi struct nome_struttura{ tipo_base1 nome_membro1; tipo_base2 nome_membro2;... }; –La parola chiave per definire una struttura dati è struct, seguita dal nome della struttura, che sarà poi il tipo delle variabili/istanze di tale struttura –La definizione della struttura descrive il modello dati che essa implementa, costituito da un insieme di variabili dette membri della struttura –Esempio: struct carta{ char *figura; char *segno; }; struct introduce la definizione della struttura carta carta è il nome della struttura che verrà poi usato per dichiarare variabili aventi questo tipo di struttura carta contiene due membri di tipo char * (figura e segno)

4 2000 Prentice Hall, Inc. All rights reserved Definire le strutture (2/2) Regole e vincoli inerenti le strutture –La definizione dichiara un tipo di dato ma non alloca spazio in memoria –Una struttura non può avere come membri variabili che hanno come tipo la struttura stessa, ma può tuttavia contenere puntatori a tali variabili Ovvero puntatori a variabili che hanno come tipo la struttura stessa –Si possono annidare strutture differenti (come membri di altre) struct nome_struttura1{ tipo_base1 nome_membro1; struct nome_struttura2 nome_membro2; //OK struct nome_struttura1 nome_membro3; //Errore!!! struct nome_struttura1 * nome_membro4; //OK }; Operazioni valide/permesse –Assegnare variabili struct ad altre variabili aventi lo stesso tipo di struct –Rilevare lindirizzo di memoria (&) di una variabile/istanza di struttura –Accedere ai valori dei membri/campi di unistanza di struttura –Determinare la dimensione in memoria della struttura ( sizeof )

5 2000 Prentice Hall, Inc. All rights reserved Dichiarare e inizializzare le strutture Dichiarazione (alloca spazio in memoria) –Una variabile struct si dichiara come tutte le altre struct carta unaCarta, mazzo[ 52 ], *cPtr; –Si può anche unire dichiarazione di variabile e definizione della struct struct carta { //Dichiara una variabile di tipo struct carta, char *figura; //un vettore di elementi di tipo struct carta char *segno; //e un puntatore a variabili di tipo struct carta } unaCarta, mazzo[ 52 ], *cPtr; Inizializzazione –Puè essere fatta all-in-one tramite una lista di inizializzatori struct carta treCuori = { "Tre", Cuori" }; –Oppure tramite assegnamento di variabili struct struct carta unaCarta = { "Tre", Cuori" }; struct carta treCuori = unaCarta; –Oppure separando dichiarazione e inizializzazioni di ogni membro struct carta treCuori; treCuori.figura = Tre; treCuori.segno = Cuori;

6 2000 Prentice Hall, Inc. All rights reserved Accedere ai membri delle strutture Accesso diretto –Per accedere al valore dei membri delle strutture (istanze) in modo diretto tramite la variabile/istanza stessa, si usa loperatore punto (. ) –Loperatore punto va applicato alla variabile struct e deve essere seguito dal nome del membro di cui si vuole reperire il valore struct carta miaCarta; printf( "%s", miaCarta.segno ); Accesso via puntatore –Per accedere al valore dei membri tramite un puntatore allistanza di struttura dati, si usa loperatore freccia ( -> ) –Loperatore freccia va applicato al puntatore alla variabile struct e deve essere seguito dal nome del membro di cui si vuole reperire il valore struct carta *miaCartaPtr = &miaCarta; printf( "%s", miaCartaPtr->segno ); –I due tipi di accesso sono equivalenti Ovvero miaCartaPtr->segno è alias di (*miaCartaPtr).segno

7 2000 Prentice Hall, Inc. All rights reserved Usare le strutture con le funzioni Passare le strutture come parametri alle funzioni –Si può passare una struttura interamente oppure solo i singoli membri –In entrambi i casi, il passaggio di default è per valore –Nel primo caso, nel corpo della funzione si accede ai membri usando (.) Passare le strutture per riferimento –Si deve passare lindirizzo della variabile struct (&) –La funzione riceve per parametro un puntatore alla variabile struct –Nel corpo della funzione si accede ai membri usando ( -> ) Con le strutture si può passare un intero vettore per valore –Si crea una struttura dati che ha come unico membro un vettore –Si dichiara una variabile struct che ha per tipo la struttura appena definita –Si passa direttamente la variabile struct per intero alla funzione –In questo modo anche il vettore è automaticamente passato per valore –Viceversa, si può passare una struct per riferimento creando e passando un vettore di struct con un solo elemento, la variabile struct da passare

8 2000 Prentice Hall, Inc. All rights reserved Ridenominazione di tipi con typedef typedef –Crea sinonimi (alias) per tipi di dato strutturato già definiti in precedenza –In genere si usa typedef per abbreviare i nomi dei certi tipi di struttura –typedef non crea un nuovo tipo di dato, ma solo un alias –Funziona anche con i tipi di dato classici del C (int, float,..) Sintassi typedef nome_struttura nome_alias_tipo –Esempio: typedef struct carta Carta; typedef Carta * CartaPtr; Definisce un nuovo nome di tipo CartaPtr come un sinonimo per il tipo Carta * (che è il tipo puntatore a struttura dati Carta) Da ora per creare puntatori a variabili struct di tipo Carta, si può usare in modo equivalente struct carta * nomePointer oppure CartaPtr nomePointer

9 2000 Prentice Hall, Inc. All rights reserved Caso di studio: un efficiente mescolatore/distributore di carte (1/4) 1/* Fig. 10.3: fig10_03.c 2 Il programma per mescolare e distribuire carte usando strutture */ 3#include 4#include 5#include 6 7struct carta{ 8 const char *figura; 9 const char *segno; 10}; 11typedef struct carta Carta; 12 13void creaMazzo( Carta * const, const char *[], const char *[] ); 14void mischiaMazzo( Carta * const ); 15void daiCarte( const Carta * const ); 16 17int main(){ 18 Carta mazzo[ 52 ]; 19 const char *figura[] = { "Asso", "Due", "Tre", Quattro", 20 Cinque", "Sei", "Sette", Otto", "Nove", 21 Dieci", "Jack", Regina", Re"}; 22 const char *segno[] = { Cuori", Quadri", Fiori", Picche"}; 1. Definisce la struttura carta composta da due stringhe (come array di caratteri) 2. Rinomina il tipo carta in Carta 3. Prototipi di funzioni 4. Dichiara il vettore mazzo, i cui elementi sono istanze del tipo strutturato Carta 5. Inizializza i vettori di stringhe figura e segno

10 2000 Prentice Hall, Inc. All rights reserved Caso di studio: un efficiente mescolatore/distributore di carte (2/4) creaMazzo( mazzo, figura, segno ); 26 mischiaMazzo( mazzo ); 27 daiCarte( mazzo ); 28 return 0; 29} 30 31void creaMazzo( Carta * const wMazzo, const char * wFigura[], 32 const char * wSegno[] ){ 33 int i; for ( i = 0; i <= 51; i++ ) { 36 wMazzo[ i ].figura = wFigura[ i % 13 ]; 37 wMazzo[ i ].segno = wSegno[ i / 13 ]; 38 } 39} 24 srand( time( NULL ) ); Chiama in sequenza le funzioni per creare e mischiare il mazzo e per distriuire le carte: mazzo, figura e segno sono vettori e passano quindi per riferimento 7. Inizializza il vettore mazzo assegnando figura/segno ai membri di ogni suo elemento 8. I parametri formali di mazzo, figura e segno sono vettori e possono quindi esser dichiarati come vettori o come puntatori al tipo di dato dei vettori stessi Mette tutte le 52 carte nel mazzo in modo ordinato. Le 12 figure e i 4 segni vengono determinati da divisione/resto progressivi per 13. Si va dellasso fino al re per ogni segno, finite le carte di un segno si ripete per gli altri segni rimasti.

11 2000 Prentice Hall, Inc. All rights reserved Caso di studio: un efficiente mescolatore/distributore di carte (3/4) 41void mischiaMazzo( Carta * const wMazzo ){ 42 int i, j; 43 Carta temp; for ( i = 0; i <= 51; i++ ){ 46 j = rand() % 52; 47 temp = wMazzo[ i ]; 48 wMazzo[ i ] = wMazzo[ j ]; 49 wMazzo[ j ] = temp; 50 } 51} 52 53void daiCarte( const Carta * const wMazzo ){ 54 int i; for ( i = 0; i <= 51; i++ ) 57 printf( "%5s of %-8s%c", wMazzo[ i ].figura, 58 wMazzo[ i ].segno, ( i + 1 ) % 2 ? '\t' : '\n' ); 59} Seleziona un numero casuale tra 0 e 51. Scambia lelemento i con quellelemento. 9. Mischia il mazzo che inizialmente era stato creato ordinato 10. Per ogni posizione allinterno del mazzo genera un numero casuale tra 0 e 51 che indica unaltra posizione nel mazzo e scambia la carta in posizione corrente con quella nellaltra posizione casuale 11. Distribuisce le carte del mazzo in modo analogo allesempio già visto, ma figura e segno sono presi dai membri degli elementi del vettore mazzo Fa il ciclo utilizzando gli array e visualizza i 2 mazzi distribuiti

12 2000 Prentice Hall, Inc. All rights reserved Caso di studio: un efficiente mescolatore/distributore di carte (4/4) Otto di Quadri Asso di Cuori Otto di Fiori Cinque di Picche Sette di Cuori Due di Quadri Asso di Fiori Dieci di Quadri Due di Picche Sei di Quadri Sette di Picche Due di Fiori Fante di Fiori Dieci di Picche Re di Cuori Fante di Quadri Tre di Cuori Tre di Quadri Tre di Fiori Nove di Fiori Dieci di Cuori Due di Cuori Dieci di Fiori Sette di Quadri Sei di Fiori Regina di Picche Sei di Cuori Tre di Picche Nove di Quadri Asso di Quadri Fante di Picche Cinque di Fiori Re di Quadri Sette di Fiori Nove di Picche Quattro di Cuori Sei di Picche Otto di Picche Regina di Quadri Cinque di Quadri Asso di Picche Nove di Cuori Re di Fiori Cinque di Cuori Re di Picche Quattro di Quadri Regina di Cuori Otto di Cuori Quattro di Picche Fante di Cuori Quattro di Fiori Regina di Fiori Visualizzazione del Programma

13 2000 Prentice Hall, Inc. All rights reserved Le Unioni(1/2) union –Sono locazioni di memoria che contengono diversi tipi di dato nel tempo Tutti i membri di una union condividono lo stesso spazio di memoria –Quando viene dichiarata una union, di fatto viene allocato uno spazio di memoria pari all'elemento più grande della union stessa –A run-time, la memoria contiene il valore di un solo membro alla volta Si può accedere/usare solo lultimo membro assegnato (a cui si è dato un valore), tutti quelli precedenti si perdono perché lo spazio è condiviso –Le operazioni sulle union sono simili a quelle delle struct Assegnamenti tra union di pari tipo di struttura, recupero dei loro indirizzi (&), accesso ai membri direttamente con (..) o tramite puntatore ( -> ) Dichiarare una union –Si dichiara nello stesso modo delle struct union Numero{ int x; float y; }; union Numero valore;

14 2000 Prentice Hall, Inc. All rights reserved Le Unioni (2/2) 1/* Fig. 10.5: fig10_05.c - Un esempio di unione */ 3#include 4 5union numero{ int x; double y; }; 6 7int main(){ 8 union numero valore; 9 10 valore.x = 100; 11 printf( "%s\n%s%d\n%s%f\n\n", Inserisci un valore nel membro 12 intero e visualizza entrambi i membri., 13 "int: ", valore.x, "double: ", valore.y ); 14 valore.y = 100.0; 15 printf( "%s\n%s%d\n%s%f\n", Inserisci un valore nel membro 16 decimale e visualizza entrambi i membri.", 17 "int: ", valore.x, "double: ", valore.y ); 18 return 0; 19} 1. Definizione della union 2. Assegnamento del primo membro della union (un intero) 3. Visualizzazione del membro intero 4. Assegnamento del secondo membro (un double) che di fatto sostiuisce il primo Inserisci un valore nel membro intero e visualizza entrambi i membri. int: 100 double: Inserisci un valore nel membro decimale e visualizza entrambi i membri. int: 0 double: Visualizzazione del Programma

15 2000 Prentice Hall, Inc. All rights reserved Le costanti di Enumerazione (1/2) Enumerazione ( enum ) –E un tipo di dato che può assumere solo valori allinterno di un insieme di costanti intere rappresentate da identificatori –Sono come delle costanti simboliche i cui valori vengono impostati automaticamente I loro valori partono per default da 0 e sono incrementati di 1 I loro valori possono anche essere assegnati esplicitamente con loperatore = E necessario usare nomi di costanti unici, mai ripeterli nellenumerazione –Sintassi (esempio): enum Mesi { GEN = 1, FEB, MAR, APR, MAG, GIU, LUG, AGO, SET, OTT, NOV, DIC} mese; Crea un nuovo tipo enum Mesi dove gli identificatori sono impostati a interi da 1 a 12, dove lenumerazione inizia da 1 e incrementa di 1 ogni volta Dichiara una variabile mese di tipo enum, che potrà valere GEN, FEB, … –Il vantaggio è dato dalluso del nome di costante al posto del valore che intero che essa rappresenta (frequente luso nei cicli) –Alle variabili di tipo enum si possono assegnare solamente valori pari agli identificatori dellenumerazione (mai i rispettivi interi corrispondenti) Quando invece vengono lette, viene restituito il rispettivo valore intero

16 2000 Prentice Hall, Inc. All rights reserved Le costanti di Enumerazione (2/2) 1/* Fig : fig10_18.c - Usare il tipo enumerazione */ 2#include 3 4enum Mesi{ GEN = 1,FEB,MAR,APR,MAG,GIU,LUG,AGO,SET,OTT,NOV,DIC }; 5 6int main(){ 7 enum Mesi mese; 8 const char *nomeMese[] = { "", Gennaio", Febbraio", "Marzo", 9 "Aprile", "Maggio", Giugno", "Agosto", "Settembre", 10 "Ottobre", Luglio", "Novembre", "Dicembre" }; for (mese=GEN; mese<=DIC; mese++) 13 printf( "%2d%11s\n", mese, nomeMese[mese] ); 14 return 0; 15} 1 Gennaio 2 Febbraio 3 Marzo 4 Aprile 5 Maggio 6 Giugno 7 Luglio 8 Agosto 9 Settembre 10 Ottobre 11 Novembre 12 Dicembre 1. Definizione della enumerazione 2. Inizializzazione delle variabili 3. Ciclo di stampa della enumerazione Visualizzazione del programma


Scaricare ppt "2000 Prentice Hall, Inc. All rights reserved. Capitolo 10 (Deitel) Strutture, unioni ed enumerazioni Sommario 10.1 - Introduzione 10.2 - Definire le strutture."

Presentazioni simili


Annunci Google