Académique Documents
Professionnel Documents
Culture Documents
Département d’Informatique
Programmation en Langage C
SMA-SMI 3
J. Alami Chentoufi 1
Table des matières
I. Introduction au langage C ------------------------------------------------------------------------------------------------ 5
I.1. Caractéristiques du langage C ------------------------------------------------------------------------------------- 5
I.2. Définitions -------------------------------------------------------------------------------------------------------------- 5
I.3. Premier programme en C ------------------------------------------------------------------------------------------- 6
I.4. Commentaires --------------------------------------------------------------------------------------------------------- 7
II. Les variables ---------------------------------------------------------------------------------------------------------------- 7
II.1. Déclaration d’une variable ---------------------------------------------------------------------------------------- 8
II.1.1. Syntaxe ------------------------------------------------------------------------------------------------------- 8
II.1.2. Types de base ----------------------------------------------------------------------------------------------- 8
II. 1. 3. Exemples de déclaration de variables --------------------------------------------------------------- 9
II. 2. Les constantes ----------------------------------------------------------------------------------------------------- 10
II.2.1. Constantes entières ------------------------------------------------------------------------------------- 10
II.2.2. Constantes réelles --------------------------------------------------------------------------------------- 10
II.2.3. Constantes caractères ---------------------------------------------------------------------------------- 11
II.2.4. Constantes chaînes de caractères ------------------------------------------------------------------- 11
II.2.5. Les constantes nommées ------------------------------------------------------------------------------ 11
II. 3. Les opérateurs standards en C --------------------------------------------------------------------------------- 12
II.3.1. L’opérateur d’affectation = ---------------------------------------------------------------------------- 12
II.3.2. Les opérateurs arithmétiques------------------------------------------------------------------------- 12
II.3.3. Les opérateurs de comparaison ---------------------------------------------------------------------- 13
II.3.4. Les opérateurs logiques -------------------------------------------------------------------------------- 13
II.3.5. Autres opérateurs particuliers ----------------------------------------------------------------------- 14
II. 4. Les conversions de types (Casting) --------------------------------------------------------------------------- 15
II. 5. Priorité des opérateurs ------------------------------------------------------------------------------------------ 15
III. Écriture et lecture des données ------------------------------------------------------------------------------------- 16
III. 1. Écriture formatée des données ------------------------------------------------------------------------------- 16
III. 2. Lecture formatée des données ------------------------------------------------------------------------------- 17
III. 3. Autres fonctions particulières de lecture et écriture ---------------------------------------------------- 19
IV. Instructions de contrôle ---------------------------------------------------------------------------------------------- 20
IV.1. Structures de choix ----------------------------------------------------------------------------------------------- 20
IV.1.1. L’instruction if…else ------------------------------------------------------------------------------------ 20
IV.1.2. L’instruction de branchement multiple switch -------------------------------------------------- 21
IV.2. Structures répétitives -------------------------------------------------------------------------------------------- 22
J. Alami Chentoufi 2
IV.2.1. La boucle for---------------------------------------------------------------------------------------------- 22
IV.2.2. La boucle while ------------------------------------------------------------------------------------------ 24
IV.2.3. La boucle do … while ----------------------------------------------------------------------------------- 25
IV.3. L’instruction break------------------------------------------------------------------------------------------------ 26
IV.4. L’instruction continue ------------------------------------------------------------------------------------------- 27
V. Les tableaux -------------------------------------------------------------------------------------------------------------- 28
V.1. Tableaux à une dimension--------------------------------------------------------------------------------------- 28
V.1.1. Déclaration ------------------------------------------------------------------------------------------------ 28
V.1.2. Initialisation d’un tableau ------------------------------------------------------------------------------ 29
V.1.3. Accès aux éléments d’un tableau -------------------------------------------------------------------- 29
V.1.4. Lecture des éléments du tableau -------------------------------------------------------------------- 29
V.1.5. Affichage des éléments du tableau ------------------------------------------------------------------ 30
V.2. Tableaux multidimensionnels ---------------------------------------------------------------------------------- 31
VI. Les chaînes de caractères -------------------------------------------------------------------------------------------- 32
VI.1. Déclaration et mémorisation d’une chaîne de caractères ---------------------------------------------- 32
VI.1.1. Déclaration ----------------------------------------------------------------------------------------------- 32
VI.1.2. Espace mémoire à réserver--------------------------------------------------------------------------- 32
VI.1.3. Mémorisation -------------------------------------------------------------------------------------------- 33
VI. 2. Initialisation de chaînes de caractères ---------------------------------------------------------------------- 33
VI.3. Déclaration, initialisation et mémorisation d’un tableau de chaînes de caractères ------------- 33
VI.4. Manipulation de chaînes de caractères --------------------------------------------------------------------- 34
VI.4.1. Fonctions de lecture et écriture --------------------------------------------------------------------- 34
VI.4.2. Autres fonctions de manipulation de chaînes de caractères -------------------------------- 35
VII. Les pointeurs------------------------------------------------------------------------------------------------------------ 36
VII.1.Introduction -------------------------------------------------------------------------------------------------------- 36
VII.2. Définition de pointeurs ----------------------------------------------------------------------------------------- 36
VII.3.Intérêts des pointeurs ------------------------------------------------------------------------------------------- 36
VII. 4. Déclaration et initialisation d’un pointeur ---------------------------------------------------------------- 37
VII.5. Opérations élémentaires sur les pointeurs ---------------------------------------------------------------- 37
VII.5.1. Opérateurs * et & -------------------------------------------------------------------------------------- 37
VII.5.2. Autres Opérations possibles ------------------------------------------------------------------------- 37
VII.6. Pointeurs et tableaux ------------------------------------------------------------------------------------------- 37
VII.7. Pointeurs et chaînes de caractères -------------------------------------------------------------------------- 39
VII.8. Allocation, Réallocation et libération dynamique de la mémoire ----------------------------------- 40
J. Alami Chentoufi 3
VII.8.1. Allocation dynamique de la mémoire ------------------------------------------------------------- 40
VII.8.2. Réallocation dynamique de la mémoire ---------------------------------------------------------- 41
VII.8.3. Libération de mémoire allouée --------------------------------------------------------------------- 42
VIII. Les fonctions ----------------------------------------------------------------------------------------------------------- 43
VIII.1. Définition de fonctions ---------------------------------------------------------------------------------------- 43
VIII.2. Retour d’une fonction ----------------------------------------------------------------------------------------- 44
VIII. 3. Déclaration et appel de fonctions -------------------------------------------------------------------------- 45
VIII. 4. Visibilité des variables ----------------------------------------------------------------------------------------- 46
VIII.4.1. Les variables globales -------------------------------------------------------------------------------- 46
VIII.4.2. Les variables locales ---------------------------------------------------------------------------------- 47
VIII. 5. Passage des paramètres de fonctions --------------------------------------------------------------------- 48
VIII. 5. 1. Passage des paramètres par valeur ------------------------------------------------------------- 48
VIII. 5. 2. Passage des paramètres par adresse ----------------------------------------------------------- 49
VIII. 6. Récursivité ------------------------------------------------------------------------------------------------------- 50
IX. Les structures ------------------------------------------------------------------------------------------------------------ 51
IX.1. Définition, declaration at accès aux champs d’une structure ------------------------------------------ 51
IX. 2. Rédéfinition de type avec typedef --------------------------------------------------------------------------- 52
IX.3. pointeurs et structures ------------------------------------------------------------------------------------------ 53
J. Alami Chentoufi 4
I. Introduction au langage C
Le langage C a été créé au début des années 70 par Dennis Ritchie et Brian Kernighan. Le
Langage C reste encore aujourd'hui un des langages les plus utilisé au monde.
Ce langage de programmation est à la base des systèmes d’exploitation ou au moins du
noyau de ces systèmes comme par exemple Unix/Linux. Le Langage C a justement été créé
pour un seul et unique but au départ, développer un système d'exploitation (Unix) mais au fil
du temps, grâce à sa puissance, il a été adopté par une large communauté de développeurs
ce qui a permis au langage d'évoluer et surtout d'être standardisé.
Le langage C fait partie des langages de programmation procédurale pour lesquels le
programme est divisé en blocs qui peuvent contenir leurs propres variables ainsi que
d’autres blocs.
I.2. Définitions
Un programme C est un ensemble d'instructions qui se saisit dans un fichier dont
l’extension est .c à l'aide d'un éditeur, ce type de fichier s'appelle fichier source. Les
instructions qui y sont écrites s'appellent du code ou encore le code source.
Un compilateur est un logiciel qui lit le code source et le convertit en un code exécutable,
c'est-à-dire un ensemble d'instructions compréhensible par le processeur. La compilation
d'un code source se fait en deux étapes (figure 1): la compilation proprement dite et le
linkage (ou bien édition de liens). On utilise en général le terme compilation en englobant
les deux étapes précédemment citées.
J. Alami Chentoufi 5
Figure 1. Différentes phases de la programmation en C
J. Alami Chentoufi 6
L'exécution d'un programme C entraîne automatiquement l'appel de la fonction main. Elle
constitue la fonction principale des programmes en C ; elle doit se trouver obligatoirement
dans chaque fichier source (.c).
#include<stdio. h>
int main ( )
{
printf ( "Bonjour, ceci est mon premier programme en C !!" ) ;
return 0 ;
}
Remarque :
En C, toute instruction simple est terminée par un point virgule (;). Dans le programme ci-
dessus, printf( "Bonjour, ceci est mon premier programme en C !!" ) est une instruction
simple qui correspond à un appel de la fonction d’affichage.
I.4. Commentaires
Pour rendre un programme plus compréhensible, on peut utiliser des commentaires. Un
commentaire est une séquence de caractères ignorée par le compilateur, on s'en sert pour
expliquer des portions de code.
J. Alami Chentoufi 7
II.1. Déclaration d’une variable
Déclarer une variable, c'est prévenir le compilateur qu'un nom va être utilisé pour désigner
un emplacement de la mémoire.
Toute variable doit être déclarée avant les instructions et son type doit être spécifié dès la
déclaration.
II.1.1. Syntaxe
Pour déclarer une variable appelée var d’un type donné Type on utilise la syntaxe
suivante :
Type var ;
Remarque :
1. Un type définit l'ensemble des valeurs que peut prendre une variable, le nombre
d'octets à réserver en mémoire et les opérateurs que l'on peut appliquer dessus.
2. L’identificateur d’une variable peut être composé de lettres et de chiffres (le
caractère souligné _ est considéré comme une lettre). Le premier caractère d’un
identificateur doit être forcément une lettre.
3. Un identificateur d’une variable ne doit pas être l’un des mots réservés au
compilateur C. Ces mots réservés sont : auto, break, case, char, const, continue,
default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return,
short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile,
while.
4. Le compilateur C fait la différence entre minuscule et majuscule : VAR et Var sont
deux identificateurs différents
a. Les entiers :
Trois types de base servent à représenter les entiers selon la taille mémoire nécessaire
pour stocker la variable :
Type Taille en octet Valeur Valeur
1. entiers courts : short int, minimale maximale
2. entiers longs : long int short int 1 -128 127
3. entiers standards : int int 2 -32678 32677
long int 4 -2147483647 2147483648
J. Alami Chentoufi 8
Remarque :
Si l’on ajoute le préfixe unsigned à l’un de ces types cités ci-dessus, alors on manipule des
entiers non signés (positifs).
b. Les caractères :
c. Les flottants :
Les flottants servent à représenter les réels. Leur nom vient du fait qu'on les représente de
façon scientifique : un nombre décimal (à virgule) muni d'un exposant (un décalage de la
virgule). Trois types de base servent à représenter les flottants :
J. Alami Chentoufi 9
int a, b; /* déclaration de deux variables a et b de type int */
char car_1, car_2 ; /* déclaration de deux variables car_1 et car_2 de type char (des
caractères) */
float r; /* déclaration de la variable r de type float */
double d_1, d_2; /* déclaration de deux variables réels d_1 et d_2 de type double */
Remarque:
1. Constantes entières
2. Constantes réelles
3. Constantes caractères
4. Constantes chaîne de caractères
Remarque :
Les constantes réelles sont par défaut de type double. Pour forcer le compilateur à
considérer la constante réelle comme étant un float on ajoute le suffixe f ou F, de même
pour utiliser une constante comme étant un long double on ajoute le suffixe l ou L.
J. Alami Chentoufi 10
II.2.3. Constantes caractères
Une constante caractère s'écrit entourée du signe apostrophe (‘). Par exemple, la
constante caractère correspondant au caractère C s'écrit 'C'.
Pour distinguer certains caractères spéciaux (les caractères de contrôle ou caractères non
imprimables), on utilise le signe \ (antislash).
Constante Signification
'\'' une apostrophe
'\"' un guillemet
'\\' un back slash (anti slash)
'\a' un bip sonore
'\b' un retour arrière (backspace)
'\f' saut au début de la page suivante
'\n' saut de ligne (new line)
'\r' un retour chariot
'\t' une tabulation horizontale
'\v' une tabulation verticale
'\0' Caractère nul
J. Alami Chentoufi 11
#define PI 3.14159 et dans la suite du programme on pourra utiliser le nom PI pour désigner
la constante 3.14159.
<variable> = <expression> ;
o Le membre à droite (c'est-à-dire expression) doit être une valeur ou une expression
calculée.
o Le membre à gauche (c'est-à-dire variable) doit être impérativement un élément
modifiable comme par exemple une variable on dit qu'il s'agit d'une « lvalue »
(contraction de left value).
Exemple:
Exemple :
int a, b, c, d ;
b=2, c=1, d=4;
a = b * c + d + 8; // a= 2*1+4+8 =14
On ajoute les opérateurs parenthèses ( ) pour fixer l'ordre des calculs.
Exemple :
int a, b, c, d ;
b=2, c=1, d=4;
J. Alami Chentoufi 12
a = b * (c + d + 8); // a= 2*(1+4+8)=26
L'opérateur de division / retourne un quotient entier si les deux opérandes sont des entiers
et retourne un réel si l’un des deux opérandes est un réel.
Exemple:
24/6= 4
10/3= 3 (retourne un entier car les 2 opérandes sont des entiers)
10/4.0= 2.5 (retourne un réel, car l’un des opérandes est en notation réelle)
L'opérateur modulo, noté %, donne le reste de la division entière d'un entier par un autre.
Exemple :
10 % 5= 0, 22 % 7= 1, 25 % 19= 6
= = : l'opérateur d’égalité
!= : l'opérateur différent de
< (resp. <=) : plus petit (resp. plus petit ou égal)
> (resp. >=) : plus grand (resp. plus grand ou égal)
Exemple :
x = 3, y = 0
x<y renvoie 0 (faux) et x > y renvoie 1(vrai)
x <= y renvoie 0 et x >= y renvoie 1
x != y renvoie 1 (vrai, x est différent de y)
x == y renvoie 0 (faux, x n’est pas égal à y)
Remarque : Il ne faut surtout pas confondre l'opérateur d'égalité == avec l'opérateur d'affectation =
Opérateur Signification
! NON logique (négation)
&& ET logique
|| OU logique
Ces opérateurs logiques s'appliquent à des expressions booléennes (0 si faux et valeur non
nulle si vrai)
Le ET logique (&&) retourne la valeur 1 si les deux opérandes sont non nuls, et 0 si l’un des
opérandes est nul.
Le OU logique (||) retourne la valeur 1 si au moins un des opérandes est non nul, et 0 si tous les
opérandes sont nuls.
J. Alami Chentoufi 13
Table de vérité des 3 opérateurs logique :
X Y X&&Y X || Y ! X ! Y
1 0 0 1 0 1
0 1 0 1 1 0
1 1 1 1 0 0
0 0 0 0 1 1
i = i + 1; <==> i++;
j = j - 1; <==> j--;
++ est :
–un opérateur de pré-incrémentation si la variable est placée à droite (++ i). Dans ce cas, la
valeur de la variable <i> est incrémentée, puis utilisée.
–un opérateur de post-incrémentation si la valeur est placée à gauche ( i++). Dans ce cas,
La valeur de la variable <i> est d'abord utilisée telle qu’elle, puis incrémentée.
Exemple
int m , n , p, q;
m =1 ; p=0 ;
n = m++ ; /* on passe d'abord la valeur de m à n et on incrémente après m */
/* Après cette instruction m vaut 2 et n vaut 1 */
Le langage C autorise des écritures simplifiées lorsqu’une même variable est utilisée de
chaque côté de l’opérateur = d’affectation.
Exemple:
J. Alami Chentoufi 14
c. L’opérateur sizeof:
(<type>) <expression>
Exemple 1:
int a = 2;
float s, c = 89.9;
char d = (char)c; d = 89, d= ‘Y’
s=(float) a; s= 2.0
Exemple 2:
int a = 49;
int b = 4 ;
float c ;
c = a / b; c = 12
c = (float) a/b c = 12.25
J. Alami Chentoufi 15
Dans ce tableau, les opérateurs sont classés par priorité décroissante (même priorité pour
les opérateurs d'une même ligne). Les opérateurs les plus prioritaires seront évalués en
premier. L'associativité définit l'ordre d'évaluation des opérandes. La plupart se font de
gauche à droite (par exemple 20/2/5 donne (20/2)/5 donc 2 (et pas 20/(2/5))).
Exemples:
Dans une expression, les parenthèses forcent la priorité, car c’est l’opérateur qui a la
priorité la plus grande (tableau ci-dessus).
J. Alami Chentoufi 16
Remarque :
1. Il est possible de faire l’écriture de plusieurs variables en utilisant une seule chaîne de
caractères contenant plusieurs descriptions de formats.
2. Il devra y avoir autant de variables dans la fonction printf qu'il y a de spécificateurs
de format.
3. Les spécificateurs de format commencent toujours par le symbole %.
Le tableau suivant présente les différents spécificateurs de format :
Spécificateurs de format
Exemple1 :
int jour = 7, mois = 10, annee = 2011;
printf (" On est le: \n \t%d / %d / %d" , jour, mois, annee);
Résultat:
On est le:
7 / 10 / 2011
Exemple 2:
int a = 5, b =2;
float d= (float) a/b;
printf (" La division de %d par %d est %f", a, b, d);
Résultat:
La division de 5 par 2 est 2.5
J. Alami Chentoufi 17
Où :
"<format>" : format de lecture des données,
<&Var1>,... : adresses des variables auxquelles les données seront attribuées.
Remarque :
1. Les spécificateurs de format de scanf sont identiques à ceux de printf, sauf qu'au lieu
de fournir comme arguments des variables à scanf, ce sont les adresses de ces
variables que l'on transmet.
2. L'adresse d'une variable est indiquée par le nom de la variable précédé du signe &.
Exemple1 :
#include <stdio.h>
int main ( )
{
int j, m, a; // déclaration de 3 variables de type entier
//printf affiche un message qui invite l’utilisateur à saisir des entiers
printf("Donner 3 entiers : \n ");
/*cette instruction lit 3 entiers séparés par des espaces, tabulations ou interligne.
Les valeurs sont attribuées respectivement aux 3 variables : j, m et a*/
scanf("%d %d %d", &j, &m,&a);
// Affichage des valeurs lues par scanf
printf("Voici les 3 valeurs lues : \n j : %d \n m : %d\n a : %d",j,m,a) ;
return 0 ;
}
Résultat :
Si on tape sur le clavier les valeurs suivantes : 7 ^10 ^2011
^ : est un espace entre les valeurs saisies au clavier
Le programme affichera :
Voici les 3 valeurs lues :
j:7
m : 10
a : 2011
Exemple 2:
#include <stdio.h>
int main ( )
{
int a,b;
float d;
char c;
/* printf affiche un message qui invite l’utilisateur à saisir des données de
différents type dans l’ordre */
printf("Donner 2 entiers, un réel et un caractère : \n ");
/*Cette instruction lit 2 entiers suivis d’un réel puis un caractère. Les valeurs sont
attribuées respectivement aux variables : a, b, d et c*/
scanf("%d %d %f %c", &a, &b,&d, &c);
// Affichage des valeurs lues par scanf
printf("Voici les différentes valeurs lues : \n a : %d \n b : %d\n d : %f \n c : %c",a,b,d,c) ;
return 0 ;
}
J. Alami Chentoufi 18
Résultat :
Si on saisit au clavier les valeurs : 1^2^2.5^A
On aura :
Voici les différentes valeurs lues :
a:1
b:2
d : 2.5
c:A
Soit car une variable de type char: putchar( car) est équivalente à printf(" %c " , c). La
forme générale de putchar est: putchar (<caractere>);
Exemple :
#include <stdio.h>
int main()
{
char car1 = ‘A’;
putchar(car1); // affiche la lettre A
putchar (‘L’); // affiche la lettre L
putchar(65); //affiche le caractère dont le code ASCII = 65 ç-à-d la lettre A
return 0;
}
#include <stdio.h>
int main()
{
char c;
c=getchar(); // Lecture d’un caractère
putchar(c); //Affichage du caractère lu
return 0;
}
J. Alami Chentoufi 19
IV. Instructions de contrôle
Les instructions de contrôle servent à contrôler le déroulement de l’enchaînement des
instructions à l’intérieur d’un programme. Ces instructions peuvent être des instructions
conditionnelles (de choix) ou itératives.
if(condition)
instruction; /* ou un bloc d'instructions */
Exemple :
#include <stdio.h>
int main( ) {
int note = 16 ;
if (note> 14)
printf("Mention très bien ") ;
return 0 ;
}
if peut être aussi utilisée avec else (qui est optionnelle) et ainsi si la condition est
vérifiée l'instruction (ou le bloc d'instructions) directement après le if sera éxécutée
sinon (condition fausse) l'instruction (ou le bloc d'instructions) après le else sera
exécutée. La syntaxe complète de l'instruction if-else sera alors:
if(condition)
instruction1;
else // si condition n’est pas vérifiée
instruction2;
Exemple:
#include <stdio.h>
int main( ) {
int a = 1 ;
if (a> = 0)
printf("l’entier %d est positif ", a) ;
else
printf("l’entier %d est négatif ", a) ;
return 0 ;
}
J. Alami Chentoufi 20
Les instructions if…else peuvent être imbriquées l'une dans l'autre. Lors d'une telle situation
un else se rapporte toujours au premier if qui le précède.
Exemple:
if(condition1)
if(condition2)
instruction1;
else instruction2;
instruction3;
Lorsque condition1 n'est pas vérifiée c'est instruction3 qui est éxécutée sinon condition2
est testée si elle est vraie instruction1 est éxécutée et si elle est fausse instruction2 est
exécutée. Le else se rapporte ainsi au second if.
switch(expression)
{
case cas1: i nstructions1;
case cas2: instructions2;
.
.
.
case casN: instructionsN;
default: instructions_par_défaut; /* le cas "default" étant facultatif */
}
Remarque :
Le type de ‘expression’ ne peut être qu’entier (char, int, long). L'expression est évaluée,
puis on passe directement au "case" correspondant à la valeur trouvée. Le cas default est
facultatif, mais s’il est prévu il doit être le dernier cas.
J. Alami Chentoufi 21
Remarque:
Lorsqu'il y a un branchement réussi à un ‘case’, toutes les instructions qui le suivent sont
exécutées, jusqu’à la fin du bloc ou jusqu’à une instruction de rupture (break).
Exemple :
En langage C, les structures répétitives peuvent être exprimées par les 3 boucles suivantes:
1. La boucle for
2. La boucle while
3. La boucle do … while
J. Alami Chentoufi 22
for ( expression1 ; expression2 ; expression3 )
{
liste d’instructions;
}
Le for s’utilise avec trois expressions, séparées par des points virgules, qui peuvent être
vides :
1. l’expression ‘expression1’ est réalisée une seule fois lors de l’entrée dans la boucle,
elle est appelée expression d’initialisation ;
2. l’expression ‘expression2’ est la condition d’exécution de la liste d’instructions. Elle
est testée à chaque itération, y compris la première. Si l’expression ‘expression2’
prend la valeur vraie la liste des instructions de la boucle for est exécutée, sinon la
boucle se termine ;
3. l’expression ‘expression3’ contrôle l’avancement de la boucle. Elle permet de
manière générale de calculer la prochaine valeur avec laquelle la condition de
passage va être testée, elle est exécutée après la liste des instructions à chaque
itération avant le nouveau test de passage.
Initialisation Expression 1
Faux
Expression 2
Test
Vrai
Liste d’instructions
Expression 3
Remarque:
J. Alami Chentoufi 23
Exemple 1: Exemple 2:
Exemple 3:
Faux
condition
Vrai
Liste d’instructions
J. Alami Chentoufi 24
L’exemple suivant affiche tous les nombres de 1 à 5 dans l'ordre croissant :
int main( ){
int i = 1 ;
while ( i <= 5 )
{
printf ( "%d " , i ) ;
i ++;
}
return 0 ;}
Ce programme initialise i à 1 et tant que la valeur de i ne dépasse pas 5, cette valeur est
affichée puis incrémentée. Les instructions se trouvant dans le corps de la boucle sont donc
exécutées 5 fois de suite. La variable i s'appelle un compteur, on gère la boucle par
incrémentations successives de i et on sort de la boucle une fois que i a atteint une certaine
valeur (dans l’exemple la valeur 6).
Remarque :
do
{
instructions;
} while(condition vraie );
A l’inverse du while, le do… while place son test en fin d’exécution des instructions, d’où la
boucle do … while s’exécute au moins une seule fois même si la condition n’est pas vérifiée.
L’organigramme de la figure 4 représente le fonctionnement de la boucle do … while :
Liste d’instructions
Faux
condition
Vrai
Figure 4. Organigramme de la boucle do … while
J. Alami Chentoufi 25
Exemple 1:
Ce programme affiche les nombres de 0 à 9 :
int main( )
{
int i = 0;
do
{
printf("%d\n", i);
i = i + 1;
} while (i < 10);
return 0;
}
Exemple 2 :
Dans l’exemple suivant, la variable c est initialisée dans la boucle. On doit tester sa valeur à
la fin de l'itération. Tant que l'utilisateur n'a pas encore tapé la lettre ‘o’, le programme
redemandera de taper la lettre.
int main( )
{
char c;
do
{
printf("Veuillez taper la lettre 'o'\n");
scanf("%c", &c);
} while (c != 'o');
return 0;
}
J. Alami Chentoufi 26
printf("%f", (float)1/n) ;
}
Exemple 2:
Dans une instruction for, while ou do while, l'instruction continue provoque l'arrêt de
l'itération courante, et le passage au début de l'itération suivante.
Exemple :
Dans cet exemple, La boucle for s'effectue pour "i = 0,1,2,3,4,5,6,7,8,9". Si i est un multiple
de 3, c'est-à-dire que " (i%3) ==0 ", alors on effectue l'instruction « continue », qui permet
d’abandonner l’itération courante et de passer à l’itération suivante. Et donc, cette boucle
n'affiche pas les multiples de 3.
int main( )
{
int i;
for (i=0; i<10;i++)
{
if ((i%3)==0) continue;
printf("i = %d\t ",i);
}
printf("\nsortie : ");
printf("\n\ti = %d ",i);
return 0;
}
L’exécution de ce programme donne :
i=1 i=2 i=4 i=5 i=7 i=8
Sortie:
i = 10
J. Alami Chentoufi 27
V. Les tableaux
Les tableaux permettent de gérer un ensemble de variables de même type. Un tableau est
une zone mémoire constituée de cases contiguës où sont rangées des données de même
type. Les cases ont donc une taille identique. Un tableau possède un nombre fixé de cases
qui doit être connu quand il est créé. La zone mémoire possède donc un début et une fin.
V.1.1. Déclaration
Où :
« type » est le type de variable contenu dans de chaque case du tableau.
« identificateur » est le nom donné au tableau.
«nombre_d'éléments » est une valeur entière qui donne le nombre total de cases du
tableau.
Par exemple : int Tab [10] ; déclare un tableau appelé Tab qui contient 10 entiers. Cette
déclaration alloue donc en mémoire pour l'objet Tab un espace de 10 × sizeof(int)
consécutifs (sizeof retourne la taille d'un objet en octets).
Comme le montre la figure 5, le nom du tableau seul est une constante dont la valeur est
l’adresse du début du tableau.
J. Alami Chentoufi 28
V.1.2. Initialisation d’un tableau
L’initialisation d’un tableau se fait en mettant une accolade ouvrante, la liste des valeurs
servant à initialiser le tableau, et une accolade fermante. La figure 6 montre l’espace
mémoire correspondant à la définition d’un tableau de dix entiers avec une initialisation
selon la ligne :
int tab[10] = {9,8,7,6,5,4,3,2,1,0};
J. Alami Chentoufi 29
int main()
{
int i ;
float Tab [10] ;
printf("Saisie des elements du tableau\n") ;
for (i = 0 ; i < 10 ; i ++)
{
printf("\ndonner l’élément d’indice %d : ", i) ;
scanf(" %f ", &Tab[ i ]);
}
return 0 ; }
« tab[i] » est une variable de type flottante et &tab[i] est l’adresse mémoire du ième
élément du tableau.
Remarque :
Il est conseillé d'employer le plus possible des constantes dans les programmes (en
utilisant #define), notamment pour la taille des tableaux. Le code ci-dessus peut s'écrire
ainsi :
#include <stdio.h>
# define N 10
int main()
{
int i ;
int Tab [N] ;
J. Alami Chentoufi 30
printf("Saisie des elements du tableau\n") ;
for (i = 0 ; i < N ; i ++)
{
printf("\ndonner l’élément d’indice %d : ", i) ;
scanf(" %d ", &Tab[ i ]);
}
printf("Affichage des elements du tableau\n") ;
for (i = 0 ; i < N ; i ++)
printf("\n Tab [ %d]=%d ", i, Tab[ i ]) ;
return 0 ;
}
Par exemple : int Tab[3][4] est un tableau bidimensionnel, est en fait un tableau
comportant 3 éléments, chacun d'entre eux étant un tableau de 4 éléments comme le
montre la figure 7 :
Exemple 1 :
#define M 2
#define N 3
/* Déclaration et initialisation d’un tableau d’entiers à deux dimensions*/
int tab[M][N] = {{1, 2, 3}, {4, 5, 6}};
/*Affichage du tableau*/
for (i = 0 ; i < M; i++)
{
for (j = 0; j <N; j++)
printf("tab[%d][%d]=%d\n",i,j,tab[i][j]);
printf("\n");
}
J. Alami Chentoufi 31
Exemple 2 :
#define M 2
#define N 3
/* Déclaration d’un tableau d’entiers à deux dimensions*/
int tab[M][N],i,j ;
/*Saisie des éléments du tableau */
for(i =0 ; i< M ;i++)
for(j =0 ; j< N ; j++)
{
printf("donner tab[%d][%d]: \n",i,j);
scanf("%d",&tab[i][j]);
}
/*Affichage du tableau*/
for (i = 0 ; i < M; i++)
{
for (j = 0; j <N; j++)
printf("tab[%d][%d]=%d\t",i,j,tab[i][j]);
printf("\n");
}
VI. Les chaînes de caractères
Il n'existe pas de type spécial chaîne de caractères ou string en C. Une chaîne de caractères
est traitée comme un tableau à une dimension de caractères (vecteur de caractères). Il
existe quand même des notations particulières et une bonne quantité de fonctions spéciales
pour le traitement de tableaux de caractères.
VI.1.1. Déclaration
Exemples :
J. Alami Chentoufi 32
Attention, il ne faut pas confondre le caractère de fin de chaîne de caractères ‘\0 ‘ avec
le caractère ’0’ dont le code ASCII est 48!
Malheureusement, le compilateur C ne contrôle pas si nous avons réservé un octet pour
le symbole de fin de chaîne; l'erreur se fera seulement remarquer lors de l'exécution du
programme.
VI.1.3. Mémorisation
Le nom d'une chaîne est le représentant de l'adresse du premier caractère de la chaîne.
Pour mémoriser une variable qui doit être capable de contenir un texte de N caractères,
nous avons besoin de N+1 octets en mémoire.
Exemple:
En général, les tableaux sont initialisés par l'indication de la liste des éléments du tableau
entre accolades:
char CHAINE[] = {'H','e','l','l','o','\0'};
Pour le cas spécial des tableaux de caractères, nous pouvons utiliser une initialisation plus
confortable en indiquant simplement une chaîne de caractère constante sans préciser la
dimension du tableau:
char CHAINE[] = "Hello";
J. Alami Chentoufi 33
La déclaration char JOUR[7][9]; réserve l'espace en mémoire pour 7 mots contenant 9
caractères (dont 8 caractères significatifs+ ‘\0’).
Lors de la déclaration il est possible d'initialiser toutes les composantes du tableau par des
chaînes de caractères constantes:
J. Alami Chentoufi 34
b. Lecture d’une chaîne de caractères
scanf avec le spécificateur %s permet de lire un mot isolé à l'intérieur d'une suite de
données du même ou d'un autre type.
scanf avec le spécificateur %s lit un mot du fichier d'entrée standard stdin (clavier)et le
Effet:
mémorise à l'adresse qui est associée à %s.
Exemple
char LIEU[25];
int JOUR, MOIS, ANNEE;
printf("Entrez lieu et date de naissance : \n");
scanf("%s %d %d %d", LIEU, &JOUR, &MOIS, &ANNEE);
gets est idéal pour lire une ou plusieurs lignes de texte (p.ex. des phrases) terminées par un
retour à la ligne.
J. Alami Chentoufi 35
VII. Les pointeurs
VII.1.Introduction
Toute variable manipulée dans un programme est stockée quelque part en mémoire
centrale. Cette mémoire est constituée d'octets qui sont identifiés par un numéro qu'on
appelle adresse.
Pour retrouver une variable, il suffit donc de connaître l'adresse de l'octet où elle est
stockée (ou, s'il s'agit d'une variable qui recouvre plusieurs octets contigus, l'adresse du
premier de ces octets : cas d’un tableau).
Pour des raisons évidentes de lisibilité, on désigne souvent les variables par des
identificateurs, et non par leur adresse. C'est le compilateur qui fait alors le lien entre
l'identificateur d'une variable et son adresse en mémoire. Toutefois, il est parfois très
pratique de manipuler directement une variable par son adresse.
Remarque :
1. A la déclaration d’un pointeur p, il ne pointe a priori sur aucune variable précise : p
est un pointeur non initialisé. Toute utilisation de p devrait être précédée par une
initialisation.
2. Pour un pointeur sur une variable de type char, la valeur donne l’adresse de l’octet
où cette variable est stockée.
3. Pour un pointeur sur une variable de type float, la valeur donne l’adresse du
premier des 4 octets où la variable est stockée.’.
J. Alami Chentoufi 36
VII. 4. Déclaration et initialisation d’un pointeur
Déclaration : Un pointeur est une variable dont la valeur est égale à l’adresse d’une autre
variable. En C, on déclare un pointeur par l’instruction :
type *nom_du_pointeur ;
Où type est le type de la variable pointée, l’identificateur nom_du_pointeur est le nom de la
variable pointeur et * est l.opérateur qui indiquera au compilateur que c.est un pointeur.
Initialisation : Pour initialiser un pointeur, le langage C fournit l’opérateur unaire &. Ainsi
pour récupérer l’adresse d.une variable A et la mettre dans le pointeur P (P pointe vers A) :
P=&A
On peut bien entendu affecter l’adresse d’un objet du bon type à un pointeur.
Tous les opérateurs de comparaison sont utilisables avec les pointeurs, qui ne
peuvent toutefois être comparés qu’à un autre pointeur où à la constante NULL.
Seules l’addition, la soustraction d’une valeur entière et la soustraction de deux
pointeurs sont des opérations arithmétiques sensées.
Un entier, additionné ou soustrait à un pointeur est d’abord multiplié par la taille du
type pointé de façon à correspondre à un déplacement en nombre d’éléments de ce
type.
Réciproquement, la soustraction de deux pointeurs sur un même type retourne le
nombre d’éléments de ce type situés entre les deux pointeurs.
J. Alami Chentoufi 37
- un pointeur doit toujours être initialisé, soit par une allocation dynamique, soit par
affectation d'une expression adresse, par exemple p = &i ;
- un tableau ne peut pas figurer à gauche d'un opérateur d'affectation. En particulier, un
tableau ne supporte pas l'arithmétique (on ne peut pas écrire tab++;).
Exemple
En déclarant un tableau Tab de type int et un pointeur P sur int :
int tab[10];
int *P;
l'instruction:
P = tab; est équivalente à P = &tab[0];
Si P pointe sur une composante quelconque d'un tableau, alors P+1 pointe sur la
composante suivante. Plus généralement, nous avons :
P+i : pointe sur la ième composante du tableau elle est équivalente à &tab[i], avec i varie de
0 à9 dans l’exemple.
*(P + i) : est le contenu du ième élément du tableau tab c'est-à-dire tab[i].
Exemple :
#include <stdio.h>
main()
{
int T[6] = { 2, 6, 4, 5, 10, 8 }; //déclaration et initialisation d’un tableau de 6 entiers
int *p; //on déclare un pointeur sur int
p = T; // p pointe sur le premier élément de T (&T[0])
printf("%d\n", *p); // affiche 2
p++;
printf("%d\n", *p); // affiche 6
p += 4;
printf("%d\n", *p); // affiche 8
}
J. Alami Chentoufi 38
VII.7. Pointeurs et chaînes de caractères
Les chaînes constantes de caractères sont, comme on l’avait déjà vu, un cas particulier de
tableaux de type char et possèdent une adresse mémoire. L’affectation suivante :
char *p= "Hello world"; (équivalente à char *p; p="Hello world";) : signifie que
l’on définit une variable pointeur ‘p’ de type char* à laquelle on affecte, comme valeur
initiale, non pas la chaîne "Hello world", mais l’adresse de cette dernière.
Le pointeur p peut être représenté par ce graphique:
Remarque :
Si ‘p’ change de valeur, le tableau de départ ne sera plus accessible, et donc la mémoire
qu'il occupait serait perdue.
Exemple :
char * p = "Hello world";
p= "Salut";
while (*p != '\0'){
printf("%c ", *p++); // Affiche : S a l u t
}
Voici un autre exemple où l’affectation d’une nouvelle valeur à un pointeur sur une chaîne
de caractères constante, fait perdre la chaîne constante initiale. D'autre part, un pointeur sur
char a l'avantage de pouvoir pointer sur des chaînes de n'importe quelle longueur:
J. Alami Chentoufi 39
Les affectations discutées ci-dessus ne peuvent pas être effectuées avec des tableaux de
caractères. En effet, les chaînes de caractères déclarées comme pointeurs peuvent être
initialisées avec “=”, affectées avec “=”. Par contre, lorsqu’elles sont déclarées comme
tableaux de caractères, elles peuvent être initialisées avec “=”, mais pas affectées avec “=”.
Les instructions suivantes provoquent une erreur à la compilation :
char tab[] = "Hello world";
tab= "Salut"; // erreur
Dans ce cas, le compilateur alloue un tableau de 11 caractères qu'il initialise avec les
caractères H, e, l, l, o, ‘ ‘, w, o, r, l, d, et \0.
L’affectation dans ce cas doit être effectuée par la fonction déjà vue ‘’strcpy‘’. Le code
suivant corrige l’erreur précédente:
char tab[] = "Hello world";
strcpy(tab,"Salut");
Cette fonction prend en paramètre la quantité de mémoire, en octets, que l'on souhaite
allouer, et retourne, en cas de succès, un pointeur générique vers la zone mémoire qui nous
est nouvellement réservée. En cas d'échec, c'est un pointeur NULL qui nous est renvoyé.
J. Alami Chentoufi 40
Remarque :
Un pointeur générique est capable de pointer vers n'importe quel type d'objet. Il importe
alors de définir le type de donnée qui sera contenu dans cet espace mémoire. Cela est spécifié
devant l’appel de la fonction. Par exemple :
int *Tab = (int *) malloc(30 * sizeof(int));
La conversion est réalisée ici grâce à la mention (int *) qui transforme la valeur retournée
par malloc (void *)en une adresse vers un int. Cette instruction permet une ‘réservation
dynamique’ d'un espace mémoire de 30* sizeof(int)octets.
En plus de la fonction malloc, il existe d’autres fonctions pour réserver de la mémoire. Il
s’agit de la fonction calloc:
void * calloc( unsigned N, unsigned taille_type);
Elle réserve N éléments de taille_type octets chacun. Elle retourne un pointeur sur le
premier octet ainsi alloué ou NULL si l’allocation n’a pu être satisfaite. Les cases de l'espace
mémoire alloué par la fonction calloc contiennent des valeurs nulles.
Le premier paramètre que prend cette fonction correspond à un pointeur vers un espace
mémoire qui avait été dynamiquement alloué au préalable, via la fonction malloc ou une
fonction équivalente. Si ce pointeur est nul, la fonction realloc agira de la même manière
que la fonction malloc, que nous avons étudié plus haut.
Le second paramètre correspond à la nouvelle taille que nous souhaitons pour notre bloc
mémoire. Celle-ci peut être inférieure, ou supérieure, selon vos besoins, à la taille d'origine.
En cas de succès, la fonction realloc retourne un pointeur sur la nouvelle zone mémoire, qui
peut ou non être la même que celle qui était déjà à votre disposition, selon l'état dans lequel
la mémoire se trouvait. En cas d'échec à la réallocation, la fonction retourne NULL ; notez
que, dans ce cas, vous ne devez pas considérer que les données pointées par le pointeur que
vous aviez passé en premier paramètre soient toujours valides !
A titre d'illustration, voici un petit exemple de réallocation de l'espace mémoire que nous
avons alloué un peu plus haut :
tab = realloc(tab, 60*sizeof(unsigned long));
if(tab != NULL){
// Utilisation de l'espace mémoire ré-alloué
}
else
{
J. Alami Chentoufi 41
// Echec de la ré-allocation mémoire
}
J. Alami Chentoufi 42
VIII. Les fonctions
Jusqu'à cette partie, nous n’avons utilisé que des fonctions prédéfinies dans des librairies
standard (printf, scanf, …) et une seule fonction nouvelle: la fonction principale main().
Un programme C bien conçu contient en général de nombreuses petites fonctions plutôt
que peu de grosses fonctions. Chaque fonction contient une série d'instructions qui seront
exécutées à chaque fois que cette fonction sera appelée.
Cette façon de programmation par fonctions (programmation modulaire) permet de
rendre facile la compréhension de longs programmes, d'éviter les séquences d'instructions
répétitives et permet le partage d'outils communs qu'il suffit d'avoir écrits et mis au point
une seule fois.
Exemple :
Considérons une nouvelle fonction ‘’Affiche‘’, qui a pour rôle d’afficher les paramètres
passés en argument de la fonction. Sa définition peut se faire en C comme suit:
void Affiche( int x, int y) //En-tête de la fonction
{
printf("\nLes valeurs des parametres sont %d et %d", x, y) ;
}
J. Alami Chentoufi 43
Type_retourné : void,
nom_fonction : Affiche,
liste_paramètres_typés : int x, int y,
return : pas de return car Type_retourné : void.
J. Alami Chentoufi 44
Type de retour : int,
Nom de la fonction : Somme,
Liste des paramètres typés : int x, int y,
return: x+y.
Le corps de la fonction dans, cet exemple, ne contient que la fonction ‘’return‘’.
La valeur retournée est une expression suivant le mot-clé return (ici : x+y).
Remarque :
Une fonction possède un seul point d'entrée, mais éventuellement plusieurs points de
sortie (à l'aide du mot return). L’instruction return met fin à l’exécution des instructions
d’une fonction et rend le contrôle du programme à l’instance appelante.
Exemple :
int Pas_print(int x, int y)
{
if (x>y)
return x;
else
return y;
printf("\x= %d, y=%d ", x, y) ;
}
Cette fonction possède deux points de sortie. Soit en retournant x si (x>y), soit en
retournant y dans le cas contraire. Notons que l’instruction ‘ printf ’ ne sera jamais exécutée.
En effet, comme nous venons de le dire, return met fin à l’exécution des instructions d’une
fonction et rend le contrôle à la fonction appelante.
J. Alami Chentoufi 45
Exemple de définition e t d'utilisation d'une fonction:
/ /Version1 / /Version 2
#include <stdio.h>
//Déclaration de la fonction Somme(prototype) #include <stdio.h>
int Somme (int x, int y); //Définition de la fonction Somme
void main(void) int Somme(int x, int y)
{ {
int i,s; return (x+y);
for (i=0; i<=10; i++) }
//Appel de la fonction Somme void main(void)
s= Somme(i,i)) ; {
} int i,s;
//Définition de la fonction Somme for (i=0; i<=10; i++)
int Somme(int x, int y) s= Somme(i,i)) ; //Appel de la fonction
{ Somme
return (x+y); }
}
Selon l'endroit où on déclare une variable, celle-ci pourra être accessible (visible) de
partout dans le code ou bien que dans un bloc d’instructions (à l'intérieur d'une fonction ou
d’une boucle par exemple), on parle alors de portée (ou visibilité) d'une variable.
En langage C, une variable peut être visible uniquement dans une fonction ou un bloc
d’instruction, on parle alors de variables locales. Lorsqu'une variable est déclarée dans le
code même, c'est-à-dire à l'extérieur de toute fonction ou de tout bloc d'instruction, elle est
accessible de partout dans le code (n'importe quelle fonction du programme peut faire
appel à cette variable). On parle alors de variables globales.
Les variables globales existent pendant toute la durée de l'exécution du programme. Elles se
déclarent en dehors des blocs et des fonctions et sont visibles dans toutes les fonctions du
programme. On peut lire et modifier leur valeur n'importe où dans le programme.
J. Alami Chentoufi 46
main()
{
int i;
for (i = 0; i < 5; i++)
fonction();
}
La variable n est initialisée à zéro et il s'agit d'une variable à durée de vie permanente. En
effet, le programme affiche :
Appel numéro 1
Appel numéro 2
Appel numéro 3
Appel numéro 4
Appel numéro 5
On appelle variable locale une variable déclarée à l'intérieur d'une fonction (ou d'un bloc
d'instructions) du programme. Par défaut, les variables locales sont temporaires.
Les variables locales n'ont en particulier aucun lien avec des variables globales de même
nom. Par exemple, le programme suivant :
#include<stdio.h>
int n = 10; // n est une variable globale
void Affiche()
{
int n = 0; // n est une variable locale à la fonction Affiche
n++;
printf("Appel numéro %d\n",n);
}
main()
{
int i;
for (i = 0; i < 5; i++)
fonction();
}
Affichera :
Appel numéro 1
Appel numéro 1
Appel numéro 1
Appel numéro 1
Appel numéro 1
J. Alami Chentoufi 47
VIII. 5. Passage des paramètres de fonctions
Il n'y a théoriquement pas de limite au nombre de paramètres (ou arguments) que peut
prendre une fonction. Chaque paramètre de la liste des paramètres doit être défini par son
type suivi de son nom. Comme pour le type du résultat, le type d'un paramètre peut être
soit un type de base soit un type composé comme par exemple une structure.
Donc, les paramètres d'une fonction sont à considérer comme des variables locales qui
sont initialisées automatiquement par les valeurs indiquées lors d'un appel. A l'intérieur de
la fonction, nous pouvons donc changer les valeurs des paramètres sans influencer les
valeurs originales dans les fonctions appelantes.
Exemple :
#include <stdio.h>
void Modifier(int a)
{
a += 5; // Modifie la copie de a
printf("à l’intérieur de la fonction: a= %d \n", a);
}
main()
{
int a = 5; // a est une variable locale à main
Modifier(a); // Appel de la fonction Modifier
printf("dans main: a = %d\n", a); /* Affiche la valeur de a après
appel à la fonction Modifier*/
}
L’exécution de ce programme s’effectue de la manière suivante :
1. le programme commence son exécution par la fonction main(),
2. la variable a est initialisée à 5 puis injectée dans la fonction ‘Modifier’ que l’on
appelle,
3. la copie de la variable a est modifiée dans la fonction a+=5,
4. à l’intérieur de ‘Modifier’ on affiche : à l’intérieur de la fonction: a=10,
5. on retourne à la fonction main() juste après l’appel de la fonction, le programme
affiche : dans main: a = 5
Ceci montre que le changement effectué sur la variable ‘a’ à l’intérieur de la fonction
‘Modifier’ (a=10) est resté local à cette fonction. Lorsqu’on retourne dans la fonction main(),
la variable a récupéré sa valeur originale (5). L’opération d’addition dans la fonction
J. Alami Chentoufi 48
‘Modifier’ n’a aucune influence sur cette variable. Cela montre bien que la fonction n’a
manipulé qu’une copie de la variable.
Remarque :
Rappelons qu'un tableau est un pointeur (sur le premier élément du tableau). Lorsqu'un
tableau est transmis comme paramètre à une fonction, ses éléments sont donc modifiés par
la fonction.
Exemple :
#include <stdlib.h>
void init (int *tab, int n)
{
int i;
for (i = 0; i < n; i++)
tab[i] = i;
}
main()
{
int i, n = 5;
int *tab;
tab = (int*)malloc(n * sizeof(int));
init(tab,n);
}
J. Alami Chentoufi 49
VIII. 6. Récursivité
Toute fonction récursive possède une condition d'arrêt et comporte dans sa définition au
moins un appel à elle-même.
Par exemple pour le calcul d'une factorielle nous avons ceci: n! = nxn-1x…x1. Dans cette
situation, nous pouvons déjà déterminer notre règle de sortie de notre fonction récursive: la
valeur 1 qui symbolise la fin de la récursivité.
Exemple de la factorielle :
int fact (int n ) {
if ( n < 0) return –1; //code d'erreur
else if ( n == 0 ) return 1; // 0! = 1
else
return n*fact( n-1 ); // n! = n*(n-1)!
}
J. Alami Chentoufi 50
IX. Les structures
IX.1. Définition, déclaration et accès aux champs d’une structure
Une structure est un ensemble de variables (de types éventuellement différents),
définissant un nouveau type sous un seul nom, adapté à une gestion spécifique et à une
manipulation facile des données.
Contrairement aux tableaux qui contiennent uniquement des valeurs de même type, une
structure peut comporter des variables de type long, char, int, double à la fois. Chaque
élément de la structure, appelé membre ou champ, est désigné par un identificateur.
Une structure se définit par un identificateur suivant le mot-clé struct, ainsi que par une
liste de champs ou membres définis par un identificateur d'un type donné. On distingue la
définition d'un modèle de type structure de celle de la déclaration d'un objet de type
structure correspondant au modèle défini.
La définition d'un modèle de structure dont l'identificateur est modele suit la syntaxe
suivante :
struct modele {
type-1 membre1;
type-2 membre2;
...
type-n membren;
};
L’accès aux différents champs des structures s’effectue en utilisant l’opérateur point
‘. ’ : objet.membre, objet.membre2, etc.
Exemples :
L’exemple suivant définit une structure d'objet d'un nouveau type Date, composé d'un
champ entier JOUR, un champ MOIS de 3 caractères, e.g. "jan" "fev" etc., et d'un champ
ANNEE qui est entier aussi.
J. Alami Chentoufi 51
struct Date {
int JOUR;
char MOIS[3];
int ANNEE;
};
La structure Date peut éventuellement être utilisée pour des champs d’une autre
structure. On peut donc imbriquer les structures les unes dans les autres. Par exemple la
structure suivante utilise la structure Date pour l’un de ses champs : Date_Nais. Ce dernier
est composé de JOUR, MOIS et ANNEE. Pour que cela fonctionne, comme pour les fonctions,
il faut déclarer la structure Date au-dessus de la déclaration de la structure Etudiant :
struct Etudiant{
char nom[30];
char prenom[30];
int numero;
struct Date Date_Nais;
};
Pour déclarer des variables de type Etudiant, on peut écrire par exemple :
struct Etudiant E1, E2 ;
Pour accéder aux champs de la variable E1, on peut écrire :
E1.nom ; // représente la chaîne de caractères nom
E1.prenom ; //représente la chaîne de caractères prenom
E1.num ; // l’entier num
E1.Date_Nais.JOUR ; // représente le JOUR de la date de naissance de E1
E1.Date_Nais.MOIS ;
E1.Date_Nais.ANNEE ;
Pour déclarer un tableau de type Etudiant, on peut écrire : struct Etudiant Tab[20] ;
J. Alami Chentoufi 52
main()
{
Com z; /* au lieu du struct complexe z ; */
...
}
Exemple :
typedef struct Adresse{
int num_rue, code_postale ;
char ville[30],avenue[30] ;
} Adress ;
J. Alami Chentoufi 53