Les Structures en Langage C: Déclaration, Manipulation et Applications

Page 1 sur 12Lecteur de document UniversityLib

Les Structures en Langage C: Déclaration, Manipulation et Applications

Programming, C Language · notes

Voir tous les documents en programmation

Ecole Sup rieure de Technologie et dInformatique

Ann e universitaire : 2011-2012

Module : Programmation 2

TD N 1

Les structures

Mme BELKADHI CHELBI H.

[email protected]

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);

}