Vous êtes sur la page 1sur 31

Département d’Informatique

Module I33 :
Structures de données
Prof : Badr HSSINA
badr.hssina@univh2c.ma
Parcours MIP (S3)
2020-2021

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 1


Plan
 Rappel : Le type structure
 Déclaration
 Manipulation

 L’allocation de la mémoire
 Les outils de base de la gestion dynamique : malloc et free
 La fonction malloc
 La fonction free

 D’autres outils de gestion dynamique : calloc et realloc


 La fonction calloc
 La fonction realloc

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 2


Rappel : Le type structure

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 3


Introduction
 Les tableaux permettent de désigner sous un seul nom un ensemble
de valeurs de même type, chacune repérée par un indice.
 Les structures permettent de désigner sous un seul nom un ensemble
de valeurs pouvant être de types différents;
 Le type structure (struct) en C est une collection des champs qui
peuvent être de types différents.
 Supposons qu'on désire déclarer deux variables pers1 et pers2 de type
structure et que chaque personne dispose de quatre informations :
 numéro : un entier
 taille et poids : deux réels
 sexe : un caractère.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 4


Déclarer une structure
1. Déclaration directe sans le nom du type structure.

struct
{
int numero ;
float taille, poids ;
char sexe ;
} pers1, pers2 ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 5


Déclarer une structure
1. Déclaration directe sans le nom du type structure.

 Le désavantage de cette manière de faire est qu‘elle n'est pas


flexible pour la déclaration de nouvelles variables de même type
structure que nous aimerions utiliser ailleurs dans un même
programme.
 Schéma d'une telle structure :

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 6


Déclarer une structure
2. Déclaration directe avec le nom du type structure.
 On déclare d'abord le type :
struct personne
{ int numero ;
float taille, poids ;
char sexe ;
} ;
 On déclare après les variables : struct personne pers1, pers2 ;
 Si on veut déclarer d'autres informations de ce type, il suffit de se référer
au type "struct personne " .

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 7


Déclarer une structure
3. Déclarer en même temps le type et les variables

struct personne
{
int numero ;
float taille, poids ;
char sexe ;
} pers1, pers2 ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 8


Déclarer une structure
4. Déclarer en utilisant « typedef »

typedef struct {
int numero ;
float taille, poids ;
char sexe ;
} Personne ; /* personne est le nom du type */
Personne pers1, pers2 ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 9


Remarques
1. Pour le cours « algorithme et programmation III » on vous
suggère fortement d'utiliser la 4ème méthode pour déclarer une
structure.
2. Avec la 4ème méthode pour déclarer une structure :
 Personne est le nom du type structure disposant de 4 champs
d'information :
 numéro est le nom d'un champ de type entier.
 taille et poids sont deux champs de type réels.
 sexe est un champ de type caractère.
 pers1 et pers2 sont deux variables de type structure dont le
nom est Personne.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 10


Accès à un champ d'une structure
 Le langage C utilise le point "." pour accéder à un champ d'une variable
de type structure : variable_de_type_structure.champ
 Écrire les instructions pour donner à la "pers1" les informations
suivantes : C'est un homme qui mesure 1.67 mètre et pèse 67.8 kg. Son
numéro d'identification est 7234.
pers1.numero = 7234 ;
pers1.sexe = 'M' ;
pers1.taille = 1.67 ;
pers1.poids = 67.8 ;

 Écrire les instructions pour afficher les informations de "pers1" à l'écran :


printf("Son numéro : %d\n", pers1.numero);
printf("Son sexe : %c\n", pers1.sexe);
printf("Son poids : %.2f kgs\n", pers1.poids);
printf("Sa taille : %.2f m\n", pers1.taille);

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 11


Cas spécial : Pointeur vers le type structure
 Avec la déclaration : Personne * P ;
 P est un pointeur vers le type Personne.
 *P est une variable de type Personne.

 On peut accéder à n'importe quel champ de *P :


 (*P).taille, (*P).poids, …
 Le langage C permet de simplifier l'écriture en utilisant l'opérateur ->

(*P).champ <======> P->champ


Équivalent à

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 12


Application
 On veut manipuler les informations des salariés (personnes) d’une
entreprise sous forme de structure avec les champs suivants :
 numero : entier
 nom : chaîne de caractères.
 salaire : réels.

1) Donner la déclaration de la structure personne.


2) Ecrire une fonction qui permet de saisir les informations des employés.
3) Ecrire la fonction qui permet calculer la somme des salaires de tous les
employés.
4) Ecrire une fonction qui permet de calculer une augmentation de 10% des
salaires pour tous les employés.
5) Ecrire une fonction qui permet d’afficher les noms et les salaires des
employé.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 13


Solution
#include<stdio.h>
#define NMAX 10
typedef struct{ int numero;
char nom[20];
float salaire;
}personne;

void lecture (personne p[], int n )


{ int i;
for(i=0;i<n;i++){
printf("donner numéro\n"); scanf("%d",&p[i].numero);
printf("donner nom\n"); scanf("%s",p[i].nom);
printf("donner salaire\n"); scanf("%f",&p[i].salaire);
}}

float somme (personne p[], int n)


{ int i;float somme=0;
for(i=0;i<n;i++){
somme+=p[i].salaire;
}
return somme;
}

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 14


Solution
personne * augmentation (personne p[], int n)
{ int i; personne *P1 ;
P1=(personne *)malloc(n*sizeof(personne));
for(i=0;i<n;i++){
P1[i].numero=P[i].numero;
strcpy(P1[i].nom,p[i].nom);
P1[i].salaire=p[i].salaire+0.1*p[i].salaire;}
return P1;
}
void afficher (personne p[], int n)
{ int i;
for(i=0;i<n;i++){
printf("nom=%s\n",p[i].nom);
printf("salaire=%f\n",p[i].salaire);
}
}
int main ()
{ personne p1[10],*p2; float s=0;
lecture (p1,3);
s=somme(p1,3);
afficher(p1,3);
p2=augmentation(p1,3);
afficher(p2,3);
system("pause");
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 15
Remarques
 Pour modifier le contenu d’un paramètre d’une fonction, utiliser un
passage par adresse.
 Si on utilise un tableau statique dans le paramètre d’une fonction
cela signifie qu’on utilise un passage par adresse car le nom du
tableau c’est un pointeur.

Exemple :

float somme (personne p[], int n)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 16


Remarques
 Si vous voulez récupérer plusieurs valeurs en résultat de traitement
d’une fonction, utiliser comme déclaration de votre fonction la
syntaxe suivants :
 type_de_retour * nom_de_fonctions (paramètres )

Exemple :

personne * augmentation (personne p[], int n)

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 17


Allocation de la mémoire

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 18


Allocation de mémoire : Types de données
 L’allocation de mémoire en programmation est très importante pour
stocker des valeurs lorsque vous les affectez à des variables.
 L’attribution est faite avant et/ou au moment de l’exécution du
programme.
 Cela alloue finalement de la mémoire pour les variables déclarées
par un programmeur via le compilateur.
 Les données statiques occupent un emplacement parfaitement défini
lors de la compilation.
 Les données dynamiques n’ont pas non plus de taille définie a priori.
Leur création ou leur libération dépend, cette fois, de demandes
explicites faites lors de l’exécution du programme.
 La mémoire peut être allouée de deux manières soit statiquement
ou dynamiquement.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 19


Allocation statique
 La mémoire allouée est fixe. Une fois la mémoire allouée, elle ne
peut plus être changée.
 Si le programmeur écrit int T[10]; T est un tableau pouvant stocker
une séquence de données du même type. Il peut stocker 10
éléments entiers. Il ne peut pas stocker plus de dix éléments.
 Dans la plupart des cas, c'est un gaspillage de mémoire si on utilise
une petite partie de l'espace réservé.

Exemple : Pour créer un tableau d’étudiants


#define MAX_ETUD 1000;
......
Etudiant Etud[MAX_ETUD] ;
 Si le nombre d'étudiants lus est 465 par exemple, on gaspille de la
mémoire réservée pour le tableau d'étudiants.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 20


Allocation statique : Désavantages
 Soit un programme qui contient les déclarations suivantes :

#define MAX_EMP 2000


#define LONG_NOM 30
typedef struct
{ char nom[LONG_NOM] ;
int numero ;
float taille, salHebdo ;
}Employe ;
Employe emp [MAX_EMP] ;

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 21


Allocation statique : Désavantages
 L'espace mémoire "statique" est allouée dès la compilation.
 On demande de l'espace pour mémoriser 2000 employés.
Avec l'opérateur "sizeof", on a : sizeof(Employe) vaut =

30 : Pour nom
+4 : Pour numéro, un entier
+4 : Pour taille, un réel
+4 : Pour SalHebdo, un réel
= 42 Octets
 emp, qui mémorise 2000 employés, occupera :
 2000 x 42 = 84000 octets > 64 Ko
 Conclusion : Avant d'utiliser des tableaux pour gérer les informations d'un
problème à programmer, il faut examiner la taille des données.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 22


Allocation dynamique
 Parfois, il est nécessaire de changer la taille de la mémoire. Donc, la
mémoire peut être allouée dynamiquement.
 L’allocation dynamique consiste à réserver un espace mémoire pour
stocker l’objet pointé.
 En fonction d’ajout et de suppression, la mémoire peut être
augmenté ou diminuée.
 On utilise souvent la fonction "malloc" (memory allocation) qui est
déclarée dans le fichier d'en-tête <stdlib.h>.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 23


La fonction malloc
void * malloc(nombre_octets) ; (stdlib.h)

 Demande au système d’exploitation la permission d’utiliser


de la mémoire.
 Cette allocation est effectuée en trois étapes :
1) Appeler malloc pour demander de la mémoire
2) Vérifier la valeur retournée par malloc pour savoir si le S.E a bien
réussi à allouer la mémoire.
3) Une fois qu’on a fini d’utiliser la mémoire, on doit la libérer avec free

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 24


La fonction malloc
Exemple 1 :
char * nomPre ;
nomPre = (char *) malloc (30) ;
 On demande d'allouer 30 octets pour mémoriser un nom
et un prénom.
Exemple 2 :
int * p ;
p = (int *) malloc (sizeof(int));
 On demande d'allouer 4 octets (sizeof(int) vaut 4)
pour mémoriser *p qui est de type entier.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 25


La fonction malloc
Exemple 3 :
typedef struct
{

......

} Etudiant ;
Etudiant * p ;
p = (Etudiant *) malloc ( sizeof(Etudiant)) ;

 On demande d'allouer le nombre d'octets nécessaires pour


mémoriser *p qui est de type Etudiant.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 26


La fonction malloc : Cas général
 Soit T le nom d'un type prédéfini (int, char, etc ...) ou inventé
par le programmeur (comme Etudiant, Employe, Personne,
etc ...).
 Avec la déclaration : T * p ;
 p est un pointeur qui pointe vers un élément de type T.
 *p est une variable de type T.
 p contient alors l'adresse de *p
 ( on dit aussi que p "pointe vers" *p )
 Il existe une constante NULL pour spécifier qu'un pointeur
pointe vers rien (p = NULL ).

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 27


La fonction malloc : Cas général
 Allocation dynamique se fait par l'affectation suivante :

p = (T *) malloc (sizeof(T));
 sizeof(T) donne la taille de T en nombre d'octets (de Bytes).
 On demande l'espace de mémoire pour stocker *p et on dépose
l'adresse de *p dans p.
 Cette affectation est représentée par le schéma suivant:

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 28


La fonction calloc
void * calloc(size_t number, size_t taille); (stdlib.h)
 Cette fonction a quasiment le même comportement que la
fonction malloc.
 calloc se charge aussi d'initialiser la zone mémoire allouée en y mettant
tout les octets à la valeur 0 (ce qui n'est pas le cas de malloc).
 number: permet de déterminer le nombre de blocs
consécutifs à allouer.
 taille : permet de fixer la taille (en nombre d'octets) d'un
des blocs de mémoire. Au final, la zone de mémoire
allouée occupera donc number * taille octets.
Exemple :
#define INT_NUMBER 10
int * pointer = (int *) calloc( INT_NUMBER, sizeof(int) );

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 29


La fonction realloc
void * realloc (void * pointeur, size_t taille ) (stdlib.h)

 realloc permet de modifier la taille d’une zone préalablement


allouée (par malloc, calloc ou realloc).
 Le pointeur doit être l’adresse de début de la zone dont on veut
modifier la taille.
 Quant à taille, de type size_t, elle représente la nouvelle taille
souhaitée.
 Cette fonction restitue l’adresse de la nouvelle zone ou un pointeur
NULL dans le cas où l’allocation a échoué.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 30


La fonction free
 La fonction free() est utilisée pour libérer la mémoire allouée.

 Si nous n'avons plus besoin d'un bloc de mémoire que nous avons
réservé, alors nous pouvons le libérer à l'aide de la fonction free de
la bibliothèque <stdlib.h>.
 free( <Pointeur> )
 libère le bloc de mémoire désigné par le <Pointeur>; n'a pas d'effet
si le pointeur a la valeur NULL.
 Si nous ne libérons pas explicitement la mémoire à l'aide free, alors
elle est libérée automatiquement à la fin du programme.

Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 31

Vous aimerez peut-être aussi