Vous êtes sur la page 1sur 31

Structures de données

en C

Azzeddine Mazroui
Licence SMI S4
2022-2023
Plan du cours
 Chapitre 1 : Concepts de base
 Chapitre 2 : Listes chainées
 Chapitre 3 : Piles
 Chapitre 4 : Files
 Chapitre 5 : Arbres
 Chapitre 6 : Graphes
Structures de données - A. Mazroui 2
Chapitre1
Concepts de base

Structures de données - A. Mazroui 3


Plan du premier chapitre

 Pointeurs
 Chaines de caractères
 Fonctions

Structures de données - A. Mazroui 4


Définition d’un pointeur

 Un pointeur est une variable qui contient l’adresse d’une


autre variable.
 La syntaxe pour déclarer un pointeur est :
Type *NomPointeur ;
 Exemple :
int n = 20; ✔ L’opérateur & fournit comme
int *p ; résultat l’adresse de son opérande.
p = &n ; ✔ Donc, l’instruction p = &n; place
*p = 30; dans la variable p l’adresse de la
variable n.

Structures de données - A. Mazroui 5


Définition d’un pointeur
On peut schématiser ainsi la situation au début de la
déclaration comme suit :
mémoire
p
int n ;
int *p ; &n = 23443 20 30
n = 20 ; 23444

p = &n ; 23445
*p = 30 23446

*p=30 ; affecte la valeur 30 à la variable


pointée par p, c’est à dire n = 30 ;

Structures de données - A. Mazroui 6


Utilité des pointeurs

 Il y a trois utilisations majeures des pointeurs en C :


 L’allocation dynamique de mémoire.
 Le passage de paramètres par adresse à des
fonctions.

 La manipulation des structures de données non


primitives (listes, files, piles, …).

Structures de données - A. Mazroui 7


Chaines de caractères
 Pour stocker et manipuler des caractères, le langage C
fournit un type spécial de données. Ce type est appelé char,
qui est l'abréviation du mot «character».
Syntaxe : char c;
 Dans le langage C, les chaines de caractères sont traitées
sous-forme de tableaux de caractères.
 Dans la déclaration
char prenom [50];
on peut stocker jusqu’à 50 caractères dans la variable prenom.

Structures de données - A. Mazroui 8


Chaines de caractères
char prenom[10]; // Déclare un tableau de 10 caractères
prenom[0] = ‘M’; // Initialisation
prenom[1] = ‘o’;
prenom[2] = 'h';
prenom[3] = 'a';
prenom[5] = 'm';
prenom[6] = 'e';
prenom[7] = 'd';
prenom[8] = '\0';
puts (prenom); // Affichage de la chaine de caractères

 Pour indiquer la fin de la chaine en langage «C», on utilise


toujours le caractère nul '\0' (prenom[8] = '\0’).
9
Chaines de caractères
Autre méthode :
char prenom[10] ={'M','o','h','a','m','e','d','\0'};
printf ("%s", prenom); // équivalente à puts(prenom);
ou bien :
char prenom[10]="Mohamed";
puts(prenom);
ou bien :
char prenom[]="Mohamed";
printf ("%s", prenom);

NB : Dans les deux dernières méthodes, le caractère '\0' est


ajouté automatiquement.
Structures de données - A. Mazroui 10
Chaines de caractères

 Pour stocker une chaine dans une variable, on peut


utiliser un pointeur de type char * :
char *prenom;
prenom = "Mohamed";
printf ("%s", prenom);
 La variable prenom est de type pointeur dynamique
(contrairement au nom du tableau qui est statique).

Structures de données - A. Mazroui 11


Chaines de caractères

 Autre solution pour stocker une chaine dans une


variable est d’utiliser la fonction strcpy :
char prenom[10];
strcpy(prenom, "Mohamed");
printf ("%s", prenom);
 strcpy (STRing CoPY) est une fonction prédéfinie qui
effectue une copie caractère par caractère.
 strcpy copie la chaîne "Mohamed" à l'emplacement
indiqué par la variable prenom.

Structures de données - A. Mazroui 12


Chaines de caractères
 Il est aussi également possible d’affecter une valeur par
la fonction scanf ou la foction puts :
char prenom[20]; // ou char *prenom;
scanf("%s", &prenom);
printf ("%s", prenom);
ou bien
char prenom[20]; // ou char *prenom;
gets(prenom);
puts(prenom);

Structures de données - A. Mazroui 13


Fonctions
 Plusieurs raisons poussent à créer des fonctions en C :
 Première raison : si un fragment particulier du code apparait à
plusieurs endroits, alors il faut envisager la possibilité de le
transformer en une fonction.
 Deuxième raison (Code volumineux) : si l'algorithme à
implémenter est long, alors il est recommandé de le diviser en
morceaux qui seront programmés sous forme de fonctions.
 Troisième raison : si le problème est complexe et ne puisse
pas être attribué à un seul développeur, alors il doit être réparti
entre plusieurs développeurs de manière à garantir leur
coopération. Chacun d'eux écrit un ensemble de fonctions qui,
une fois combinées, donneront le produit final.
14
Fonctions
 Nous avons rencontré des fonctions à plusieurs reprises
en les utilisant comme des outils pour simplifier les
tâches longues et fastidieuses.

 Pour copier une chaîne, nous avons utilisé la


fonction strcpy.

 Pour afficher la valeur d'une variable, nous avons


utilisé la fonction printf.

 Ces deux fonctions sont déjà prédéfinies dans C.

Structures de données - A. Mazroui 15


Fonctions

 Lorsqu’on utilise des fonctions déjà prédéfinies, il faut


inclure au début du programme la bibliothèque qui les
contient en utilisant la directive #include.

 #include<stdio.h> contient les définitions des


fonctions printf et scanf.

 #include<string.h> contient les définitions des


fonction puts, gets et strcpy.

Structures de données - A. Mazroui 16


Fonctions
 La création d’une fonction se fait en 2 étapes :
 Déclaration de la fonction : elle est souvent appelée
prototype de la fonction, et représente la partie du
code qui contient les trois informations clés (nom,
paramètres, type). Les paramètres qui apparaissent
dans la définition de la fonction sont appelés
paramètres formels.
 Définition de la fonction : elle correspond au code
contenant l’implémentation complète de la fonction.
Structures de données - A. Mazroui 17
Fonctions
 Exemple : La fonction factorielle
int factorielle(int); // Déclaration de la fonction
int factorielle(int n) { // Définition de la fonction
int i; // n est le paramètre formel
if(n==0)
return 1 ;
else {
int resultat = 1 ;
for(i=1 ; i<=n ; i++)
resultat = resultat*i ;
return resultat;
}
} Structures de données - A. Mazroui 18
Appel de fonctions
 L’appel de la fonction se fait en remplaçant les
paramètres formels par des paramètres réels.
 Par exemple, l’appel de la fonction factorielle dans la
fonction main se fait selon la syntaxe suivante :
int factorielle(int); // Déclaration de la fonction
int factorielle(int n){ // Définition de la fonction
...
}
int main() {
int f = factorielle(6); // Appel de la fonction
printf (" factorielle de 6 = %d",f);
getch(); }
Structures de données - A. Mazroui 19
Passage de paramètres à une
fonction
 Lors de l’appel de la fonction, la valeur du paramètre
réel est copiée dans le paramètre formel et la relation
entre eux se termine à ce stade.

 Ce type de coopération entre les paramètres est appelé


passage de paramètres par valeur.

Structures de données - A. Mazroui 20


Passage de paramètres à une
fonction
 Exemple 1 :
#include <stdio.h>
void incrementerPar100(int v) {
v= v+ 100;
}
int main() {
int i = 100;
printf("i = %d\n", i); // Il affichera i=100
incrementerPar100(i);
printf("i = %d\n", i ); // Il affichera i=100
return 0;}

Structures de données - A. Mazroui 21


Passage de paramètres à une
fonction
 Nous pouvons gérer cette limitation en utilisant un
passage par adresse du paramètre réel.
 Le paramètre formel doit être un pointeur
#include <stdio.h>
void incrementerPar100(int *pntr)
{*pntr = *pntr + 100; }
int main() {
int i = 100;
printf("i = %d\n", i); // Il affichera i=100
incrementerPar100(&i); // Passage par adresse
printf("i = %d\n", i ); // Il affichera i=200
return 0;}
Structures de données - A. Mazroui 22
Passage de paramètres à une
fonction
Exemple 2 : Nous voulons échanger les valeurs de deux
variables à l’aide d’une fonction.
void Echange(int a , int b) {
int temp;
temp = a;
a=b;
b = temp;
}

Structures de données - A. Mazroui 23


Passage de paramètres à une
fonction
Programme principal :
int main() {
int x=10 , y=15 ;
printf("Avant l’échange dans le programme principal \n");
printf("x=%d et y=%d \n",x,y); // x=10 et y=15
Echange(x,y);
printf("Après l’échange dans le programme principal \n");
printf("x=%d et y=%d \n",x,y); // x=10 et y=15
getch() ;
}

 L’échange des valeurs se fait uniquement sur la fonction


Echange et par conséquent, cet échange n’a pas d’influence
sur le programme principal. 24
Passage de paramètres à une
fonction
 Pour remédier à ce problème, nous allons utiliser les
pointeurs comme indiqué ci-dessous :
void Echange(int *a , int *b) {
int temp;
temp = *a;
*a = *b ;
*b = temp;
}

Structures de données - A. Mazroui 25


Passage de paramètres à une
fonction
Programme principal :
int main() {
int x=10 , y=15 ;
printf("Avant l’échange dans le programme principal \n");
printf("x=%d et y=%d \n",x,y); // x=10 et y=15
Echange(&x,&y) ;
printf("Après l’échange dans le programme principal \n");
printf("x=%d et y=%d \n",x,y); // x=15 et y=10
getch() ;
} Structures de données - A. Mazroui 26
Passage de paramètres à une
fonction
 Les pointeurs jouent pour le langage C un rôle
primordial dans la définition des fonctions.
 Ils permettent d’échanger le contenu de variables
passées en paramètres d’une fonction.
 D'une manière générale, si on veut qu'une fonction
puisse modifier la valeur d'une variable de type x, il
suffit de passer l'adresse de cette variable à la fonction
via un pointeur sur x.

Structures de données - A. Mazroui 27


Passage de tableaux en paramètres
d’une fonction
 Pour le langage C, le nom d’un tableau, lorsqu’il est
employé seul sans indice à sa suite, désigne en fait
l’adresse de son premier élément. Ainsi,

tab = &tab[0] = &tab;

 Lorsqu'un tableau est passé en paramètre réel, c’est en


fait l’adresse du tableau qui est passée.

 Ainsi, le paramètre formel correspondant devra être


déclaré comme étant de type pointeur.
Structures de données - A. Mazroui 28
Passage de tableaux en paramètres
d’une fonction
Exemple : La fonction afficher_tab est chargée d’afficher
un tableau d'entiers qui lui est passé en paramètre.
void afficher_tab(int *t, int n) {
int i;
for (i = 0; i < n; i++)
printf("%d ",*(t + i)); }
int main() {
int t[2] = {1,9};
int taille_t = sizeof(t)/sizeof(int);
afficher_tab(t, taille_t);
getch(); }

sizeof(x) renvoie le nombre d'octets nécessaires pour le


coder x dans la mémoire. 29
Passage d’une chaine de caractères
en paramètre d’une fonction
 Une chaîne de caractères est un tableau de caractères,
donc les pointeurs vont pouvoir aussi être utilisés pour
manipuler les chaînes de caractères.
 Exemple: conversion en majuscules d’une chaîne de
caractères
int main() {
char str[]={'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0’};
// ou char str[] = "Hello World";
printf( "%s\n", str); // Affiche Hello World
toUpperCase(str);
printf( "%s\n", str); // Affiche HELLO WORLD
return 0;} Structures de données - A. Mazroui 31
Passage d’une chaine de caractères
en paramètre d’une fonction
 Code de la fonction toUpperCase :
void toUpperCase( char *chaine ) {
while ( *chaine != '\0' ) {
if ( *chaine >= 'a' && *chaine <= 'z' )
*chaine -= 32;
chaine++; // On déplace le pointeur sur le
// caractère suivant
}
}
 Dans la table ASCII : 'A' == 65 et 'a' == 97
 Il y a un écart de 32 entre les deux plages de caractères.
32

Vous aimerez peut-être aussi