I record - contiriccardo
Transcript
I record - contiriccardo
Record in C: il costruttore struct. Le variabili di tipo record e i nuovi tipi record si dichiarano in C tramite il costruttore di tipo struct:. <var-record> ::= <costr-struct> <identif> ; <costr-struct> ::= struct {<seq-campi>} <seq-campi> ::= <seq-campi-omog> | <seq-campi-omog> ; <seq-campi> <seq-campi-omog> ::= <tipo> <seq-nomi-campi> <seq-nomi-campi> ::= <identif> | <identif> , <seq-nomi-campi> struct { int Giorno; int Mese; int Anno; } Data; /* variabile Data come record di tre campi: Giorno Mese e Anno, tutti di tipo intero */ Data Data.Giorno 15 Data.Mese 10 Data.Anno 1919 /* DICHIARAZIONE ALTERNATIVA : */ struct { int Giorno, Mese, Anno; } Data; 1 • Inizializzazione di una variabile record struct { int Giorno, Mese, Anno; } Data = {15,10,1919}; • è possibile accedere ad una variabile di tipo record nel suo insieme, come se fosse una variabile semplice oppure campo per campo, rispettando tutte le regole previste per il tipo associato a ciascun campo. struct { int Giorno, Mese, Anno; } DataEsame; struct { int Giorno, Mese, Anno; } DataOrale; /* accesso alle variabili campo per campo */ DataOrale.Anno = DataEsame.Anno; DataOrale.Mese = DataEsame.Mese; DataOrale.Giorno= DataEsame.Giorno + 1; /* accesso alle variabili nel loro insieme */ DataOrale = DataEsame; 2 struct { int Matr; char Sesso; int Età; } Stud; /* variabile Stud */ Stu d Stud.Mat r Stud.Sess o Stud.Et à 15 'F' 20 Modifichiamo Stud, aggiungendo un campo Nome come una stringa struct { int Matr; char Nome[21]; char Sesso; int Età; } Stud; /* variabile Stud */ Stu d Stud.Mat r Stud.Nom e Stud.Sess o Stud.Et à 15 "Paola" 'F' 20 Questo è un primo esempio in cui un tipo strutturato (Nome di tipo stringa) è usato all’interno di un altro tipo strutturato (Stud di tipo record) : composizione di tipi strutturati. • una variabile di tipo record deve essere letta da input campo per campo, rispettando tutte le regole previste per il tipo associato a ciascun campo: printf("Inserire Matricola Studente "); scanf("%d",&Stud.Matr); printf("Inserire Nome Studente "); scanf("%20s", Stud.Nome); Il campo Nome di Stud è una stringa, quindi non ci vuole &! 3 COMPOSIZIONE DI TIPI STRUTTURATI Modifichiamo Stud, aggiungendo un campo DataDiNascita come record struct { int Matr; char Nome[21]; struct { int Giorno; int Mese; int Anno; } DataDiNascita; char Sesso; int Età; } Stud; /* variabile Stud */ printf("Inserire Data di Nascita dello Studente \n"); printf("Giorno : "); scanf("%d",&Stud.DataDiNascita.Giorno); printf("Mese : "); scanf("%d",&Stud.DataDiNascita.Mese); printf("Anno : "); scanf("%d",&Stud.DataDiNascita.Anno); • è possibile utilizzare come componenti dei tipi strutturati, costruendo così delle matrici di record, dei record di matrici, … 1 Corso Persona 1 Persona Persona Persona MaxStud Persona Nome NumCar Parola DataDiNascita Data Giorno Mese Anno struct { char Nome[NumCar]; struct{int Giorno; int Mese; int Anno; } DataDiNascita; } Corso[MaxStud]; 4 NOTA Consideriamo le seguenti dichiarazioni struct { int Giorno, Mese, Anno; } DataEsame; struct { int Giorno, Mese, Anno; } DataOrale; Non tutti i compilatori (compreso DEV-C++) accettano l’assegnamento DataOrale=DataEsame; in quanto i tipi delle due variabili sono considerati incompatibili . Se invece viene utilizzata la seguente dichiarazione: struct { int Giorno, Mese, Anno; } DataEsame,DataOrale; Allora l’assegnamento DataOrale=DataEsame; viene considerato corretto! Nello stesso modo, se considero struct { char Nome[NumCar]; struct{ int Giorno; int Mese; int Anno; } DataDiNascita; } Corso[MaxStud]; struct { char Nome[NumCar]; struct{ int Giorno; int Mese; int Anno; } DataDiNascita; } MAX; Non tutti i compilatori (compreso DEV-C++) accettano l’assegnamento MAX=Corso[0]; In questo caso si dovrebbe effettuare struct { char Nome[NumCar]; struct{ int Giorno; int Mese; int Anno; } DataDiNascita; } MAX, Corso[MaxStud]; Allora l’assegnamento MAX=Corso[0]; viene considerato corretto. Questi problemi non si presentano con l’uso del typedef. 5 Quando lo stesso tipo strutturato (array o record) deve essere usato in più di una dichiarazione di variabili, è bene dichiarare tale tipo esplicitamente con typedef: Ad esempio, nel caso di struct { char Nome[NumCar]; struct{ int Giorno; int Mese; int Anno; } DataDiNascita; } MAX, Corso[MaxStud]; si usa due volte lo stesso tipo strutturato, sia per dichiarare MAX che per Corso. Allora si definisce esplicitamente tale tipo tramite typedef: typedef struct { char Nome[NumCar]; struct{int Giorno; int Mese; int Anno; } DataDiNascita; } TipoStudente; e il nuovo tipo TipoStudente è quindi usato per dichiarare le due variabili: TipoStudente MAX; TipoStudente Corso[MaxStud]; In questo modo l’assegnamento MAX=Corso[0]; viene considerato corretto. Nel seguito viene riportato l’esempio completo “Studente più giovane”, ovvero studente con Data di Nascita maggiore utilizzando typedef. #include <stdio.h> #define NumCar 25 #define MaxStud 4 main(){ typedef struct { } TipoStudente TipoStudente char Nome[NumCar]; struct{ int G; int M; int A; } DataDiNascita; TipoStudente; MAX; Corso[MaxStud]; int I; 6 /* lettura degli studenti */ for(I=0;I<MaxStud;I++){ printf("Inserire studente n. %d\n",I); printf("Nome : "); scanf("%20s",Corso[I].Nome); printf("Data di Nascita \n "); printf("Giorno : "); scanf("%d",&Corso[I].DataDiNascita.G); printf("Mese : "); scanf("%d",&Corso[I].DataDiNascita.M); printf("Anno : "); scanf("%d",&Corso[I].DataDiNascita.A); } /* stampa degli studenti inseriti */ printf("\n\n stampa degli studenti inseriti \n\n"); for(I=0;I<MaxStud;I++){ printf("\nStudente n. %d\n",I); printf("Nome = %-20s",Corso[I].Nome); printf("Nato il %d-%d-%d: \n",Corso[I].DataDiNascita.G, Corso[I].DataDiNascita.M,Corso[I].DataDiNascita.A); } /* Calcolo del MAX. cioe’ studente con DataDiNascita piu' grande*/ MAX=Corso[0]; for(I=1;I<MaxStud;I++) if(Corso[I].DataDiNascita.A > MAX.DataDiNascita.A || Corso[I].DataDiNascita.A == MAX.DataDiNascita.A && Corso[I].DataDiNascita.M > MAX.DataDiNascita.M || Corso[I].DataDiNascita.A==MAX.DataDiNascita.A && Corso[I].DataDiNascita.M == MAX.DataDiNascita.M && Corso[I].DataDiNascita.G > MAX.DataDiNascita.G ) MAX=Corso[I]; printf("\nLo studente piu' giovane e' \n"); printf("Nome = %-20s",MAX.Nome); printf("Nato il %d-%d-%d: \n",MAX.DataDiNascita.G, MAX.DataDiNascita.M,MAX.DataDiNascita.A); } Ovviamente il precedente programma è corretto se c’e’ un solo studente con la massima DataDiNascita. Per considerare il caso in cui ci siano più studenti con la stessa data di nascita e quindi la possibilità di avere due o più studenti con la massima DataDiNascita, dopo aver caalcolato MAX, si scandisce di nuovo Corso e si stampano tutti gli studenti la cui data di nascita è quella di MAX. 7 Si noti che per controllare l’uguaglianza di due record (in questo caso le due date) non possiamo confrontare i due record con == ma si deve usare il confronto elemento per elemento: infatti l’operatore == si applica solo ai tipi semplici. In altre parole, è sbagliato scrivere if(Corso[I].DataDiNascita == MAX.DataDiNascita) ma si deve scrivere if(Corso[I].DataDiNascita.A Corso[I].DataDiNascita.M Corso[I].DataDiNascita.G == MAX.DataDiNascita.A && == MAX.DataDiNascita.M && == MAX.DataDiNascita.G ) Riportiamo il ciclo for che ci consente di stampare tutti gli studenti più giovani for(I=0;I<MaxStud;I++) if( Corso[I].DataDiNascita.A == MAX.DataDiNascita.A && Corso[I].DataDiNascita.M == MAX.DataDiNascita.M && Corso[I].DataDiNascita.G == MAX.DataDiNascita.G ) { printf("\n Nome = %-20s",Corso[I].Nome); printf("Nato il %d-%d-%d: \n", Corso[I].DataDiNascita.G, Corso[I].DataDiNascita.M, Corso[I].DataDiNascita.A); } 8