Ecole Sup rieure de Technologie et dInformatique
Ann e universitaire : 2011-2012
Module : Programmation 2
TD N 1
Les structures
Mme BELKADHI CHELBI H.
1. Notion d enregistrement ou de structure
Contrairement aux tableaux qui sont des structures de donn es dont tous les l ments sont de
m me type, les enregistrements sont des structures de donn es dont les l ments peuvent tre
de type diff rent.
Le langage C poss de le concept d'enregistrement avec cependant un probl me de vocabulaire :
Ce que tout le monde appelle
Enregistrement
Champs de lenregistrement
Le langage C appelle
Structure
Membre de la structure
Avant de d clarer une variable structure, il faut avoir au pr alable d finit son type, c'est dire le
nom et le type des membres qui le composent. Le type d'une structure est appel type structur .
1.1. Syntaxe
On d sire d clarer l'identificateur "personne" comme tant le nom d'un type de structure
compos e de trois membres, dont le premier est un tableau de 20 caract res nomm "nom", le
second un tableau de 20 caract res nomm "prenom", et le dernier un entier nomm
"no_employe".
Il existe plusieurs m thodes possibles pour ce faire.
Premi re m thode
struct personne
{
char nom[20];
char prenom[20];
int no_employe;
};
Dans le jargon du langage C, l'identificateur "personne" est une tiquette de structure. On peut
ensuite utiliser ce type structure pour d clarer des variables, de la mani re suivante :
struct personne p1,p2;
qui d clare deux variables de type struct personne de noms p1 et p2.
Deuxi me m thode
On peut d clarer des variables de type structure sans utiliser d' tiquette de structure, par
exemple :
struct
{
char nom[20];
char prenom[20];
int no_employe;
} p1,p2;
Ceci d clare deux variables de noms p1 et p2 comme tant deux structures de trois membres,
mais elle ne donne pas de nom au type de la structure.
L'inconv nient de cette m thode est qu'il sera par la suite impossible de d clarer une autre
variable du m me type.
En effet, si plus loin on crit :
struct
{
char nom[20];
char prenom[20];
int no_employe;
} p3;
les deux structures ont beau avoir le m me nombre de champs, avec les m mes noms et les
m mes types, elles seront consid r es de types diff rents. Il sera impossible en particulier d' crire
p3 = p1;.
Troisi me m thode
On peut combiner d claration d' tiquette de structure et d claration de variables, comme ceci :
struct personne
{
char nom[20];
char prenom[20];
int no_employe;
} p1,p2;
Ceci d clare deux variables p1 et p2 et donne le nom personne la structure.
L aussi, on pourra utiliser ult rieurement le nom struct personne pour d clarer d'autres variables
qui seront du m me type que p1 et p2.
struct personne pers1, pers2, pers3;
De ces trois m thodes, c'est la premi re qui est recommand e, car elle permet de bien s parer la
d finition du type structure de ses utilisations.
Quatri me m thode
Lorsqu'on donne un nom un type structure par typedef, l'utilisation est beaucoup plus ais e.
En effet, si on d clare :
struct personne
{
...
};
les d clarations de variables se feront par : struct personne p1,p2;
Alors que si on d clare :
typedef struct
{
...
} PERSONNE;
les d clarations de variables se feront par :
Publicité
PERSONNE p1,p2;
On voit que la seconde m thode permet d' viter d'avoir r p ter struct.
Application 1
On caract rise chaque plan te dun syst me plan taire par :
-
-
-
-
son nom (20 caract res au maximum),
sa densit (float),
la distance moyenne de l toile autour de laquelle elle gravite (float) en 10E6 km,
son nombre de satellites (int).
D finissez un type structur permettant de repr senter une plan te.
//D finition de la structure plan te
struct planete
{
char nom[20] ;
float densite ;
float distance ;
int nbSatellites ;
};
Initialisation dune structure
Une structure peut tre initialis e par une liste d'expressions constantes la mani re des
initialisations de tableau.
Par exemple :
struct personne p = {"Jean", "Dupond", 7845};
Application 2
D clarez et initialisez la d claration les plan tes suivantes :
Nom
Mercure
Venus
Terre
Densit
5.42
5.25
5.52
Distance moyenne
58
108.2
149.6
Nombre de satellites
0
0
1
//Initialisation de 3 plan tes
struct planete p1={"Mercure", 5.42, 58, 0};
struct planete p2={"Venus", 5.25, 108.2, 0};
struct planete p3={"Terre", 5.52, 149.6, 1};
1.2. Op rateurs sur les structures
a. Acc s aux membres de la structure
Pour d signer un membre d'une structure, il faut utiliser l'op rateur de s lection de membre qui
se note "." (point).
Par exemple, si p1 et p2 sont deux variables de type struct personne, on d signera le membre
nom de p1 par p1.nom et on d signera le membre no_employe de p2 par p2.no_employe.
Les membres ainsi d sign s se comportent comme n'importe quelle variable et par exemple, pour
acc der au premier caract re du nom de p2, on crira : p2.nom[0].
b. Affectation de structures
On peut affecter une structure une variable structure de m me type, gr ce l'op rateur
d'affectation :
struct personne p1,p2;
...
p1 = p2;
c. Comparaison de structures
Aucune comparaison n'est possible sur les structures, m me pas les op rateurs == et !=
Application 3
D clarez trois variables structur es de type struct planete et leur affecter les plan tes pr c dentes.
D clarez une quatri me plan te p, demandez lutilisateur de remplir les diff rents champs de
cette plan te et enfin lafficher.
Modifier la plan te Mercure en multipliant sa densit par 1.2 et en lui rajoutant 3 satellites.
//Affectation des 3 plan tes 3 nouvelles plan tes
struct planete p4=p1;
struct planete p5=p2;
struct planete p6=p3;
//D claration d'une nouvelle plan te
struct planete p;
//Lecture des champs de la plan te
printf ("\nLe nom de la planete: ");
gets(p.nom);
printf ("La densite de la planete: ");
scanf("%f",&(p.densite));
printf ("La distance (10E6 km): ");
scanf("%f",&(p.distance));
printf ("Le nombre de ses satellites: ");
scanf("%d",&(p.nbSatellites)) ;
//Affichage de la plan te
printf ("\n\nLa planete est: ") ;
puts(p.nom);
printf ("Sa densite est: %.2f", p.densite);
Publicité
printf ("\nSa distance : %.2f * 10E6 km", p.distance);
printf ("\nElle possede %d satellites.", p. nbSatellites);
//Modification de param tres de Mercure
p4.densite=p4.densite*1.2;
p4.nbSatellites+=3;
1.3. Passage de structure en param tre
Supposons que l'on ait fait la d claration suivante :
struct date
{
int jour, mois, annee;
};
Une fonction de comparaison de deux dates pourra s' crire :
enum {AVANT, EGAL, APRES};
int cmp_date( struct date d1, struct date d2)
{
if (d1.annee > d2.annee)
return(APRES);
if (d1.annee < d2.annee)
return(AVANT);
... //comparaison portant sur mois et jour
}
Une utilisation de cette fonction pourra tre :
struct date d1,d2;
if (cmp_date(d1,d2) == AVANT)
&
Application 4
Vous remarquez que le nombre de lignes de code augmente pour chaque saisie et chaque
affichage de plan te. Comme vous lavez appris, nous allons crire des fonctions permettant de
structurer notre application :
1. Ecrire une fonction en C, struct planete creerPlanete() qui invite la saisie une plan te au
clavier et la retourne (par lutilisation de return).
2. Ecrire une fonction en C, void afficherPlanete(), qui affiche clairement les caract ristiques
de la plan te re ue en param tre.
3. Ecrire une fonction en C, int egales(struct planete p1, struct planete p2) qui compare les
caract ristiques des plan tes p1 et p2. La fonction retourne 0 (signifie false en C) si les
plan tes ont des caract ristiques diff rentes, et 1 (signifie true en C) si les deux plan tes
ont les m mes caract ristiques.
//Fonction de cr ation de plan te
struct planete creerPlanete()
{
struct planete p;
printf ("\nLe nom de la planete: ");
gets(p.nom);
printf ("\nLa densite de la planete: ");
scanf("%f",&(p.densite));
printf ("\nLa distance (10E6 km): ");
scanf("%f",&(p.distance));
printf ("\nLe nombre de ses satellites: ");
scanf("%d",&(p.nbSatellites)) ;
return p;
}
//Proc dure d'affichage d'une plan te
void afficherPlanete(planete p)
{
printf ("\n\nLa planete est: ");
puts(p.nom);
printf ("Sa densite est: %.2f", p.densite);
printf ("\nSa distance : %.2f * 10E6 km", p.distance);
printf ("\nElle possede %d satellites.", p.nbSatellites);
}
//Test d' galit de 2 plan tes
int egales(struct planete p1, struct planete p2)
{
if (strcmp(p1.nom, p2.nom)==0 && p1.densite==p2.densite &&
p1.distance==p2.distance && p1.nbSatellites==p2.nbSatellites )
else
return 1;
return 0;
}
1.4. Tableaux de structures
Une d claration de tableau de structures se fait selon le m me mod le que la d claration d'un
tableau dont les l ments sont de type simple.
Supposons que l'on ait d j d clar la structure personne, si on veut d clarer un tableau t de 100
personnes, on crira :
struct personne t[100];
Pour r f rencer le nom de la personne qui a l'index i dans t on crira : t .nom
Application 5
Ecrire une proc dure ...initSysteme(...) qui initialise un syst me plan taire comportant n plan tes
Ecrire une proc dure ...afficherSysteme(...) qui affiche les n plan tes contenues dans un tableau
de plan tes
Ecrire une fonction ... nbMoy(..) qui renvoie le nombre moyen de satellites par plan te ainsi que
la densit moyenne des plan tes dun syst me de n plan tes
//Proc dure d'initialisation de syst me plan taire
void initSysteme(struct planete systeme[ ], int n)
{
int i;
for (i=0; i<n; i++)
{
Publicité
systeme = creerPlanete( );
}
}
//Proc dure d'affichage de syst me plan taire
void afficheSysteme(planete systeme[ ], int n)
{
int i;
for (i= 0; i<n; i++)
{
afficherPlanete (systeme );
}
}
//Proc dure de calcul de moyennes
void nbMoyen(struct planete s[ ],int n, float pnb, float pdens)
{
int i ;
int sommeNombreSatellites = 0 ;
float sommeDensite = 0;
for (i= 0 ; i < n ; i++)
{
nombreSatellites = nombreSatellites + systeme . nbSatellites ;
sommeDensite = sommeDensite + systeme .densite ;
}
*pnb = (float) nombreSatellites/n;
*pdens = sommeDensite/n;
}
2. Pointeurs vers une structure
Supposons que l'on ait d fini la structure personne l'aide de la d claration :
struct personne
{
...
};
On d clarera une variable de type pointeur vers une telle structure de la mani re suivante :
struct personne *p;
On pourra alors affecter p des adresses de structure personne. Par exemple :
struct personne
{
...
};
int main()
{
struct personne pers; //pers est une variable de type struct personne
struct personne *p; //p est un pointeur vers une struct personne
p = &pers;
&
}
Utilisation de typedef
En ce qui concerne les pointeurs, il est plus difficile d' crire et de comprendre :
struct personne
{
...
};
struct personne p1,p2; // p1 et p2 pointeurs vers des struct
que la version suivante qui donne un nom parlant au type pointeur vers struct
typedef struct
{
...
} PERSONNE;
typedef PERSONNE *P_PERSONNE; //P_PERSONNE type pointeur vers struct
P_PERSONNE p1,p2; //p1 et p2 pointeurs vers des struct
2.1. Acc s aux l ments d'une structure point e
Supposons que nous ayons d clar p comme tant de type pointeur vers une structure personne,
comment crire une r f rence un membre de la structure point e par p ?
Etant donn que p d signe la structure, on serait tent d' crire p.nom pour r f rencer le
membre nom. Mais il faut savoir que les op rateurs d'indirection (*) et de s lection (.), tout
comme les op rateurs arithm tiques, ont une priorit . Et il se trouve que l'indirection a une
priorit inf rieure celle de la s lection. Ce qui fait que *p.nom sera interpr t comme signifiant
*(p.nom). Cela aurait un sens si p tait une structure dont un des membres s'appelait nom et
tait un pointeur.
Dans notre cas, il faut crire (*p).nom pour forcer l'indirection se faire avant la s lection.
Cette criture tant assez lourde, le langage C a pr vu un nouvel op rateur not -> qui r alise la
fois l'indirection et la s lection : p->nom est identique (*p).nom.
Par exemple : si p est de type pointeur vers la structure personne d finie pr c demment, pour
affecter une valeur au membre no_employe de la structure point e par p, on peut crire :
p->no_employe = 123456;
2.2. Structures dont un des membres pointe vers une structure du
m me type
Une des utilisations fr quentes des structures, est de cr er des listes de structures cha n es. Pour
cela, il faut que chaque structure contienne un membre qui soit de type pointeur vers une
structure du m me type. Cela se fait de la fa on suivante :
struct personne
{
... //les diff rents membres
struct personne *suivant;
};
Le membre de nom suivant est d clar comme tant du type pointeur vers une struct personne.
La derni re structure de la liste devra avoir un membre suivant dont la valeur sera le pointeur
NULL.
Publicité
3. D termination de la taille allou e un type
Pour conna tre la taille en octets de l'espace m moire n cessaire pour une variable, on dispose de
l'op rateur sizeof. Cet op rateur est un op rateur unaire pr fix que l'on peut employer de deux
mani res diff rentes : soit sizeof expression ou sizeof (nom-de-type).
Exemple 1
int i,taille;
taille = sizeof i;
taille = sizeof (short int);
taille = sizeof (struct personne);
Exemple 2
int t[10];
if (sizeof(t) / sizeof(int) != 10)
printf("sizeof mal impl ment \n");
else printf("sizeof ok\n");
3.1. Allocation et lib ration d'espace pour les structures
Nous allons voir dans ce paragraphe trois fonctions de la biblioth que standard permettant
d'allouer et de lib rer de l'espace.
3.1.1.
Allocation d'espace : fonctions malloc et calloc
Quand on cr e une liste cha n e, c'est parce qu'on ne sait pas la compilation combien elle
comportera d' l ments l'ex cution (sinon on utiliserait un tableau).
Pour pouvoir cr er des
dynamiquement. On dispose pour cela de deux fonctions : malloc et calloc.
il est donc n cessaire de pouvoir allouer de
l'espace
listes,
a. Allocation d'un l ment : fonction malloc
La fonction malloc admet un param tre qui est la taille en octets de l' l ment d sir et elle rend
un pointeur vers l'espace allou .
Utilisation typique :
#include <stdlib.h>
struct personne *p;
p = malloc(sizeof(struct personne));
b. Allocation d'un tableau d' l ments : fonction calloc
Elle admet deux param tres :
-
-
le premier est le nombre d' l ments d sir s ;
le second est la taille en octets d'un l ment.
Son but est d'allouer un espace suffisant pour contenir les l ments demand s et de rendre un
pointeur vers cet espace.
Utilisation typique :
#include <stdlib.h>
struct personne *p;
int nb_elem;
... / init de nb_elem /
p = calloc(nb_elements, sizeof(struct personne));
On peut alors utiliser les l ments p[0], p[1], ... p .
3.2. Lib ration d'espace : proc dure free
On lib re l'espace allou par malloc ou calloc au moyen de la proc dure free qui admet un seul
param tre : un pointeur pr c demment rendu par un appel malloc ou calloc.
Utilisation typique :
#include <stdlib.h>
struct personne *p;
p = malloc(sizeof(struct personne));
... / utilisation de la structure allou e /
free(p);
Application 6
Refaire le m me exemple pr c dent en utilisant les tableaux dynamiques
On doit ajouter la biblioth que stdlib.h
#include <stdlib.h>
//Proc dure d'initialisation de syst me plan taire
void initSysteme(struct planete* systeme, int n)
{
int i;
for (i=0; i<n; i++)
*(systeme+i) = creerPlanete();
}
//Proc dure d'affichage de syst me plan taire
void afficherSysteme(struct planete* systeme, int n)
{
struct planete *i;
for (i=systeme; i<systeme+n; i++)
afficherPlanete(*i);
}
//Programme principal
void main()
{
int n;
printf("\nEntrer la taille du tableau:");
scanf("%d",&n);
struct planete s=(struct planete) calloc(n,sizeof(struct planete));
initSysteme(s,n);
afficherSysteme(s,n);
free(s);
}