35
Septième Partie
Les structures, les unions et les
énumérations
36
Les structures, les unions et les énumérations
1. Les structures
a. Notion de Structure
Une structure est une organisation de données non forcement de mêmes types dans le but d’une manipulation et traitement plus simples. Ces données se regroupent sous un nom qui désigne la structure entière.
Les données composantes (membres ou champs) de la structure sont repérées aussi par un nom.
b. Exemples :
• La structure complexe (pour les nombres complexes) est composée de deux données simples de type réel : une partie réelle et une partie imaginaire.
• La structure personne est composée de trois données : le nom (une chaîne de caractères), le prénom (une chaîne de caractères), l’âge (un entier).
• La structure vecteur est composée de trois données simples de type réel : une abscisse x, une ordonnée y et une cote z.
c. Définition d’un type structure La définition d’une structure se réalise comme suit :
struct nomdelastructure {
nomdutype1 nomduchamp1;
nomdutype2 nomduchamp2;
... ...
nomdutypen nomduchampn;
};
Exemple :
Notation algorithmique Langage C type article = enregistrement
nom : chaine prix : réel fin type
struct article{
char nom[15];
double prix;
};
d. Déclaration d’une variable de type structure
La déclaration d’un variable de type structure se réalise comme suit : struct nomdelastructure nomdelavariable ; Exemples :
struct article{
char nom[15];
double prix;
};
struct complexe{
double re ; double im ; } ;
struct article art1, art2 ; struct complexe C1, C2 ;
37 e. Accès à un membre d’une structure
L’accès aux membres d’une structure qu’on nomme champ en utilise l’écriture suivante : nom_variable.nom_membre
Exemple :
article a; // a variable de type article
a.nom = "crayon"; // modification du membre nom a.prix = 1.1; // modification du membre prix
Remarque :
Une variable d’une structure peut être initialisée au moment de sa déclaration.
La syntaxe est alors la suivante :
struct nomdelastructure nomdelavariable = { val1,val2,... } ;
où val1,val2,.. sont les valeurs à affecter aux champs de la structure.
Exemples :
struct article art1={"gomme",0.75} ; struct complexe C1={0.24,-3.0} ;
f. Affectation de structures
On peut, aussi, faire l’affectation de structures sans passer par l’affectation de membres séparément :
article a, b;
a.nom = "gomme";
a.prix = 0.75;
b = a; // affectation globale d’une structure
2. Les unions
Certaines données manipulées par nos programmes peuvent :
• avoir un type qui dépend du contexte, autrement dit la même variable peut être d’un type T1 ou d’un type T2 selon le contexte.
• avoir plusieurs représentations possibles chacune d’elle étant utile dans une partie du programme.
Prenons quelques exemples :
• La valeur retournée par une fonction calculant la racine carrée d’un réel est soit de type réel soit de type complexe.
• La note attribuée à un étudiant peut être un entier compris entre 0 et 20 ou une lettre comprise entre A et E.
C’est pour répondre à ce double besoin que le langage C met à la disposition des
programmeurs les unions. Une union est une donnée définie à partir de plusieurs champs -une superposition de plusieurs champs- où un seul champ est utile à la fois.
La définition d’une union se fait selon la syntaxe suivante : union nomdelunion
{
nomdutype1 nomduchamp1;
nomdutype2 nomduchamp2;
... ...
nomdutypen nomduchampn;
};
38
La déclaration des variables d’une union se fait de la manière suivante : struct nomdelunion nomdelavariable ;
L’accès à un champ d’une variable d’une union se fait de la manière suivante : nomdelavariable.nomduchamps
Prenons un exemple de manipulation des unions.
...
...
/*Définition de l’union UNote */
union UNote {
int nZeroVingt ; char nAE ; };
...
...
/*Déclaration d’une variable de l’union UNote */
union UNote manote;
...
int typenote;
...
/*Lecture du type de la note puis de la note */
printf (”Voulez vous saisir \n(1) Une note 0..20\n(2) Une marque A-E: ”);
scanf (”%d”,&typenote);
if (typenote == 1) {
printf (”Saisir la note (0..20):”);
scanf (”%d”,&manote.nZeroVingt);
} else {
printf (”Saisir la marque (A..E):”);
scanf (”%c”,&manote.nAE);
} ...
...
La difficulté dans la manipulation des unions : comment savoir quel champs une variable donnée d’une union utilise-t-elle (puisque rappelons le un seul champ est utilisé à la fois)?
Comment savoir -pour prendre un exemple- si la variable manote du programme ci-dessus affecte une valeur au champ nAE ou au champ nZeroVingt ?
La solution est d’inclure l’union dans une structure. Autrement dit :
• Définir une structure ayant deux champs.
• Le deuxième champ ch2 est la donnée de l’union.
• Le premier champ ch1 est un entier pouvant prendre autant de valeur qu’il y a de champs dans l’union. Ch1 prendra la valeur 1 lorsque c’est le premier champ de l’union qui est affecté, 2 lorsque c’est le deuxième.
Autrement dit la manipulation des unions suit souvent le schéma suivant : ...
39 ...
/*Définition de l’union*/
union MonUnion {
type1 ch1 ; type2 ch2 ; ... ... ; };
...
...
/*Définition de la structure englobant l’union*/
struct MaStructure {
int n;
union MonUnion u;
};
...
Prenons l’exemple précédent union UNote
{
int nZeroVingt ; char nAE ; };
struct SNote {
int n ;
UNote Note ; };
...
/*Déclaration d’une variable de la structure SNote */
struct SNote MaNote ;;
...
int typenote ; ...
/*Lecture du type de la note puis de la note */
printf (”Voulez vous saisir \n(1) Une note 0..20\n(2) Une marque A-E: ”);
scanf (”%d”,&typenote);
if (typenote == 1) {
MaNote.n=1 ;
printf (”Saisir la note (0..20):”);
scanf (”%d”,&MaNote.note.nZeroVingt);
} else {
Manote.n=2 ;
printf (”Saisir la marque (A..E):”);
scanf (”%c”,&MaNote.note.nAE);
}
40
3. Les types énumérés
Il y a des cas où, les données ne peuvent prendre qu’un nombre fini et précis de valeurs, on dit que ces données sont de type énuméré. En C, la définition de ces types se fait de la
manière suivante :
enum nomdutype { val1,val2,... } ;
où val1, val2, ... sont les valeurs pouvant être prises par les données de ce type.
Ces valeurs sont des constantes entières qui sans précision contraire valent 0, 1, 2, ... La valeur constante de chacune des autres valeurs (par exemple val5) se déduit de la valeur de la constante qui la précède dans la liste (val4 dans notre exemple) par incrémentation (elle vaudra donc val4+1).
Exemples : ...
/*Définition du type énuméré EBooleen dans lequel nous n’avons pas donné*/
/* de valeurs aux constantes entières FAUX et VRAI. Ces deux constantes*/
/* vaudront donc respectivement 0 et 1. */
enum EBooleen {FAUX, VRAI};
...
...
/*Définition du type énuméré EJourDeLaSemaine. Valeurs des constantes : 0, 1, ... */
enum EJourDeLaSemaine {Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi, Dimanche};
...
...
/*Définition du type éuméré EPuissanceDeDeux. Valeurs des constantes : choisies explicitement par le programmeur*/
enum EPuissanceDeDeux {Un=1, Deux=2, Quatre=4, Huit=8, Seize=16};
...
...
/*Définition du type énuméré ECouleur dans lequel nous avons donné*/
/* des valeurs à certaines couleurs. Nos 7 couleurs valent respectivement*/
/* 0, 10, 11, 12, 100, 101, 102. */
enum ECouleur {Blanc, Rouge=10, Vert, Orange, Bleu=100, jaune, Noir};
...
La déclaration des variables d’un type énuméré comme vu précédemment, se fait de la manière suivante :
enum nomdutype nomdelavariable ;
Prenons un exemple de manipulation d’une variable d’un type énuméré.
...
/*Définition du type énuméré EBooleen */
enum EBooleen {FAUX, VRAI};
...
/*Déclaration d’une variable du type énuméré EBooleen */
enum EBooleen bl;
...
/*Affectation d’une valeur à une variable du type énuméré EBooleen */
bl = FAUX;
...
...
41
4. La déclaration de type personnalisé
L’utilisation des structures, des unions et des énumérations passe presque toujours par la définition d’un type personnalisé permettant ainsi de ne pas reprendre à chaque fois le mot struct et d’utiliser le nouveau type facilement.
La déclaration d’un type personnalisé, en C, se réalise par le mot typedef selon la syntaxe : typedef struct nomdelastructure {
typechamp1 nomchamp1 ; typechamp2 nomchamp2 ;
…
typechampn nomchampn ; } ;
Remarque : L’utilisation du mot struct avec des variables de ce type devient facultative.
Exemple :
typedef struct Article{
char nom[15] ; double Prix ; }
typedef Complexe{
double re ; double im ; } ;
La déclaration de variable peut se faire ainsi :
Complexe C1,C2 ; // on pouvait utiliser la déclaration suivantes : struct Complexe C1,C2 ; Article art0, art1, art2 ; // le mot struct est facultatif.
De même, on peut définir un type énumération comme suit : typedef enum { val1,val2,... } nomdunouveautype ; Exemple :
/*Définition du type Booleen */
typedef enum {FAUX, VRAI} Booleen;