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