You are on page 1of 121

Université Sidi Mohamed Ben Abdellah

Faculté des Sciences et Techniques Fès


Département Informatique

IEEA-TELECOM

Programmation en langage C

Zahi, Azeddine

2005-2006
1

Table des matières


Chapitre 0 : Introduction à l’algorithmique............................................... 6

1. Introduction .................................................................................................... 6

1.1. Définition ............................................................................................. 6


1.2. Structure d’un algorithme................................................................. 6
1.3. Démarche méthodologique ................................................................ 7

2. Objets d’un algorithme ................................................................................. 8

2.1. Identificateur....................................................................................... 8
2.2. Types prédéfinis .................................................................................. 9
2.3. Déclaration........................................................................................... 9
2.4. Expressions ........................................................................................ 10

3. Instructions d’un algorithme...................................................................... 11

3.1. Affectation ......................................................................................... 11


3.2. Lecture /écriture ............................................................................... 12
3.3. Bloc d’instructions ............................................................................ 13
3.4. Choix .................................................................................................. 13
3.4.1. Choix sans alternative __________________________ 13
3.4.2. Choix avec alternative __________________________ 15
3.4.3. Choix imbriqué ________________________________ 17
3.4.4. Choix multiple_________________________________ 20
3.5. Répétition........................................................................................... 22
3.5.1. Présentation des boucles ________________________ 22
3.5.2. Boucle tant que ________________________________ 22
3.5.3. Boucle répéter _________________________________ 26
3.5.4. Boucle pour ___________________________________ 29

Chapitre 1: Eléments du langage C.......................................................... 32

1. Eléments lexicaux......................................................................................... 32

1.1. Identificateurs ................................................................................... 32


1.2. Mots clés............................................................................................. 32

2. Structure d’un programme C..................................................................... 32

2.1. Les commentaires ............................................................................. 33


2.2. Instructions........................................................................................ 33

A.Zahi/DI/FSTF
2

2.2.1. Instructions directement exécutables ______________ 33


2.2.2. Instructions du préprocesseur____________________ 34
2.3. Fonctions............................................................................................ 34
2.4. Compilation d’un programme C .................................................... 36

3. Variables et Types de base.......................................................................... 36

3.1. Types de base..................................................................................... 36


3.1.1. Les caractères _________________________________ 37
3.1.2. Les entiers ____________________________________ 37
3.1.3. Les réels ______________________________________ 37
3.2. Variables ............................................................................................ 38
3.2.1. Déclaration ___________________________________ 38
3.2.2. Initialisation __________________________________ 38

4. Les constantes............................................................................................... 39

4.1. Constantes littérales.......................................................................... 39


4.1.1. Constantes réels _______________________________ 39
4.1.2. Constantes entières_____________________________ 39
4.1.3. Constantes caractères___________________________ 40
4.1.4. Constantes chaînes de caractères _________________ 40
4.2. Constantes symboliques ................................................................... 41
4.2.1. Pseudo-constantes______________________________ 41
4.2.2. Constantes variables____________________________ 41

5. Fonctions standards d’entrée/sortie........................................................... 42

5.1. Fonction printf .................................................................................. 42


5.2. Fonction sacnf ................................................................................... 43
5.3. Fonctions getchar() et putchar() ..................................................... 43

6. Expressions et Opérateurs .......................................................................... 44

6.1. Opérateurs arithmétiques................................................................ 44


6.2. Affectation ......................................................................................... 45
6.3. Incrémentation décrémentation...................................................... 46
6.4. Opérateurs Logique.......................................................................... 47
6.5. Opérateur conditionnel .................................................................... 47
6.6. Expression.......................................................................................... 48

7. Structures de contrôle ................................................................................. 48

7.1. Le choix .............................................................................................. 48


7.1.1. if sans else ____________________________________ 48
7.1.2. if avec else ____________________________________ 49

A.Zahi/DI/FSTF
3

7.1.3. Imbrication des tests____________________________ 50


7.1.4. Switch _______________________________________ 52
7.2. Boucles................................................................................................ 53
7.2.1. Boucle while __________________________________ 53
7.2.2. Boucle do while ________________________________ 55
7.2.3. Boucle for ____________________________________ 56
7.3. Instructions d’échappement ............................................................ 58
7.3.1. Instruction break ______________________________ 58
7.3.2. Instruction continue ____________________________ 58
7.3.3. Instruction return______________________________ 59
7.3.4. Instruction exit ________________________________ 60

8. Les Pointeurs ................................................................................................ 60

8.1. Mémoire de l’ordinateur.................................................................. 60


8.2. Notion de pointeur ............................................................................ 61
8.3. Déclaration......................................................................................... 62
8.4. Initialisation....................................................................................... 62
8.4.1. initialisation à l’aide de l’opérateur d’adressage &___ 62
8.4.2. Initialisation à l’aide de la fonction malloc ()________ 63
8.5. Indirection ......................................................................................... 63
8.6. Libération de l’espace ...................................................................... 64

9. Les fonctions ................................................................................................. 65

9.1. Analyse descendante......................................................................... 65


9.2. Pseudo-fonction................................................................................. 66
9.3. Déclaration des fonctions utilisateur .............................................. 67
9.3.1. Prototype d’une fonction ________________________ 67
9.3.2. Corps de la fonction ____________________________ 68
9.3.3. Comment obtenir une fonction ___________________ 69
9.4. Appel d’une fonction ........................................................................ 69
9.4.1. Principe ______________________________________ 69
9.4.2. Syntaxe de l’appel______________________________ 70
9.4.3. Passage des paramètres _________________________ 71
9.4.4. Porté des variables _____________________________ 73

Chapitre 2: Tableaux et Chaînes de caractères .................................. 76

1. Tableaux uni dimensionnels ....................................................................... 76

1.1. Déclaration......................................................................................... 76
1.2 Initialisation d’un tableau................................................................ 77
1.3. Accès à un élément du tableau ........................................................ 78
1.4. Pointeurs et Tableaux....................................................................... 79
1.4.1. Le nom d’un tableau ___________________________ 79
1.4.2. Incrémentation et décrémentation ________________ 80

A.Zahi/DI/FSTF
4

1.4.3. Indexation du tableau __________________________ 81


1.4.4. Tableaux dynamiques __________________________ 81
1.5. Tableau paramètre d’une fonction................................................. 82

2. Tableaux de dimension deux ...................................................................... 84

2.1. Déclaration......................................................................................... 85
2.2. Initialisation....................................................................................... 85
2.3. Accès à un élément............................................................................ 86
2.4. Tableau de dimension deux paramètre d’une fonction ............... 87

3. Chaînes de caractères .................................................................................. 89

3.1. Déclaration......................................................................................... 89
3.2. Initialisation....................................................................................... 89
3.3. Fonctions de manipulation .............................................................. 90
3.3.1. Affichage d’une chaîne__________________________ 90
3.3.2. Saisie d’une chaîne _____________________________ 91
3.3.3. Longueur d’une chaîne _________________________ 91
3.3.4. Copie de chaînes _______________________________ 92
3.3.5. Concaténation _________________________________ 93
3.3.6. Comparaison__________________________________ 93

Chapitre 3: Structures ..................................................................................... 95

1. Le mot clé typedef ........................................................................................ 95

2. Enumérations ............................................................................................... 96

2.1. Définition d’une énumération ......................................................... 96


2.2. Opérations sur les énumérations .................................................... 97

3. Les Structures............................................................................................... 98

3.1. Définition d’une structure ............................................................... 98


3.2. Déclaration......................................................................................... 99
3.3. Opérations sur les structures......................................................... 100
3.3.1. Accès aux membres ___________________________ 100
3.3.2. Initialisation _________________________________ 101
3.3.3. Affectation___________________________________ 102
3.4. Structure paramètre d’une fonction ............................................ 102
3.5. Tableau de structures..................................................................... 104
3.6. Tableau membre d’une structure................................................. 106
3.7. Structures imbriquées .................................................................... 108

A.Zahi/DI/FSTF
5

Chapitre 4: Fichiers ....................................................................................... 110

1. Définition..................................................................................................... 110

2. Mémoire tampon........................................................................................ 110

3. Accès à un fichier ....................................................................................... 111

3.1. Le type FILE* ................................................................................. 111


3.2. Ouverture/fermeture...................................................................... 111

4. Lecture /écriture......................................................................................... 113

4.1. Lecture et écriture par caractère.................................................. 113


4.2. Lecture et écriture par chaînes de caractères ............................. 114
4.3. Lecture et écriture formatées ........................................................ 114
4.4. Lecture et écriture par blocs ......................................................... 117

5. Accès directe ............................................................................................... 118

A.Zahi/DI/FSTF
6

Chapitre 0 : Introduction à
l’algorithmique

1. Introduction
1.1. Définition

Un algorithme est une notion qui remonte à très loin, Il prend ses racines
dans le mot "Algorisme" introduit par le mathématicien Persse AlKhawarsimi
dans son livre " hisabo aljabri wa almoqabala". Ce n‘est donc pas une notion
propre à l’informatique.

Un algorithme sert dans la résolution d’un certain nombre de problèmes


tels que : chercher le plus grand commun diviseur de deux entiers, résoudre un
système linéaires, résoudre une équation différentielle, trouver le chemin
optimal dans une ville, chercher une stratégie pour attaquer un marché financier
etc. Il permet de décrire le processus résolution de façon précise et non
ambiguë ne laissant place ni à l’interprétation ni à l’intuition.

Un algorithme est considéré comme une suite finie et ordonnée d’actions


élémentaires, instructions, effectuées sur des données pour aboutir à des
résultats. En général, il y a plusieurs algorithmes (plusieurs solutions) qui
résolvent le même problème. Le meilleur algorithme (solution optimale) est celui
qui contient moins d’instructions.

Données Algorithme Résultats

Figure 1 : Schéma d’un algorithme

1.2. Structure d’un algorithme

Un algorithme est composé de deux parties :

• Partie déclaration : contient les objets (données et résultats) utilisés


pour résoudre le problème.

• Partie traitement : contient les instructions (actions) qui permettent de


résoudre le problème.

A.Zahi/DI/FSTF
7

La forme générale d’un algorithme se présente comme suit:

algorithme nom_algorithme
constantes
Déclaration des constantes

types
Déclaration des nouveaux types
Partie déclaration
variables
Déclaration des variables

début
Instructions
fin Partie traitement

Exemple
algorithme surface
constantes
PI = 3.14
rayon = 12.5

variables :
air : réel

début
air ← rayon*rayon*PI
ecrire(air)
fin

1.3. Démarche méthodologique

L’élaboration d’un algorithme se déroule selon les étapes suivantes :

• La phase d’analyse, consiste à :


Ž Identifier les paramètres qui décrivent le problème i.e., les
paramètres qui constituent les données (ce qu’on a) et les
paramètres qui constituent les résultats (ce qu’on cherche).

Ž Formuler le problème en termes, de formules, d’équations


mathématique etc., et proposer des méthodes de résolution en
termes de méthodes mathématique ou de règles de gestion.

• La phase de conception, consiste à :


Ž Représenter les paramètres du problème par des objets
algorithmiques tels que les variables, les constantes, les structures
de données etc.

Ž Exprimer les méthodes de résolution sous forme d’instructions


algorithmique tels que les opérateurs, le choix, les boucles, les
fonctions etc.

A.Zahi/DI/FSTF
8

Exemple : Calculer le pgcd de deux entiers

Analyse

• Entrées : a, b deux entiers


• Sorties : pgcd(a,b)
• Méthode : l’algorithme d’Euclide, pgcd(a,b)=pgcd(b,q)

Conception

• Variables : a,b, et pgcd : entiers


• Algorithme
r Å a mod b
tant que (r != 0) faire
a Åb
b Å a div b
r Å a mod b
fintantque

2. Objets d’un algorithme

Deux types d’objets sont utilisés pour représenter les paramètres d’un
problème dans un algorithme: les constantes et les variables. Une variable est un
objet qui peut changer de valeur au cours de l’exécution de l’algorithme, tandis
qu’une constante ne change jamais de valeur.

Un objet est caractérisé par :

• Un identificateur qui permet de désigner un objet dans l’algorithme.

• Un type qui permet de définir l’ensemble des valeurs susceptibles


d’être prises par un objet ainsi que les opérateurs qu’on peut lui
appliquer.

• Un état qui correspond à la valeur prise à un instant de l’exécution de


l’agorithme.

2.1. Identificateur

Un identificateur permet d’identifier un objet parmi les autres objets. C’est


une suite de caractères alphanumériques qui respecte les contraintes suivantes:

• Un identificateur ne doit contenir que les caractères alphabétiques, les


chiffres et le caractère souligné " _",

• Un identificateur doit toujours commencer par un caractère


alphabétique,

• Un identificateur ne doit pas contenir les caractères accentués et


spéciaux,

A.Zahi/DI/FSTF
9

• Un identificateur doit refléter l'objet auquel il est associé. Par


exemple pour représenter le salaire d'un employé, il vaut mieux
choisir l'identificateur salaire.

Exemples

Identificateur valide Identificateur non valide


Salaire1 1salaire
Etudiant étudiant
note_examen note d’examen

2.2. Types prédéfinis

Les types prédéfinis peuvent être utilisés sans qu’ils fassent l’objet d’une
déclaration. Ces types sont : les entiers, les booléens, les réels et les caractères.

• Entier : c’est l’ensemble des entiers positifs, nuls ou négatifs. Les


opérateurs applicables sont :

Ž Opérations arithmétiques: +, -, * /, div : division entière et mod :


reste de la division entière.
Ž Opérations de comparaison: =, ≠, <, ≤, > et ≥.

• Booléen, un objet de ce type ne peut prendre que deux valeurs : VRAI ou


FAUX. Les opérations possibles sont :

Ž Opérateurs logiques : et, ou et non.


Ž Opérateurs de comparaison : = et ≠.

• Réel, ce type correspond à l’ensemble des réels. Les opérations qu’on


peut appliquer sont :

Ž Opérations arithmétiques : +, -, * et /.
Ž Opérations de comparaison : <, ≤, >, ≥, = et ≠.

• Caractère, regroupe le jeu de caractère d'une machine. Il est constitué par


les lettres (a, ..., z, A, ..., Z), les chiffres (0,1,...9) et les caractères spéciaux
affichables sur l'écran et imprimable sur papier. Les opérations possibles
sont principalement les comparaisons : <, ≤, >, ≥, = et ≠.

2.3. Déclaration

La déclaration d’un objet dans un algorithme consiste à lui attribuer un


identificateur et un type.

A.Zahi/DI/FSTF
10

Déclaration d’une constante


Syntaxe
Identificateur_de_constante = valeur
Exemples
PI=3.14
TVA = 0.2
G =9.8

Déclaration d’une variable


Syntaxe
Identificateur_de_variable : type

Exemples

i,n : entier
x,y : réel
exist : booléen
rep, c : carcatère

2.4. Expressions

Une expression est une combinaison de valeurs, de constantes, de variables


et d’opérateurs. Le type de l’expression est défini par celui des objets qui la
constituent. Selon le type de l’expression on peut distinguer trois catégories
d’expressions : expression arithmétique, expression logique et expression de
chaîne de caractère.

• Expressions arithmétique, ce sont des expressions formées par des


objets (valeurs, constantes et variables) entiers ou réels et des
opérateurs arithmétiques. Le résultat de l’expression est un nombre
entier ou réel.

Exemples
n + 10 * cste /q
(a+b)*(c-d)/2
a div b
2*3.14*R

• Expressions logiques : ce sont les expressions formées par des objets


(valeurs, constantes et variables) de type élémentaire et des opérateurs
logiques et de comparaison. Le résultat de l’expression est booléen.

Exemples

• ( i<= n et exist = vraie)


• ( x != 1 ou y =0)
• Formulation de la condition d’admission, des étudiants du Deug,
dans un établissement en fonction de la moyenne générale (m) et
de l’age d’un étudiant (age).

(m > 12 et age <=24) ou (m >16 et age <26)

A.Zahi/DI/FSTF
11

3. Instructions d’un algorithme


3.1. Affectation

C'est l'une des instructions les plus importantes en algorithmique. Elle


permet de ranger une valeur, une constante, le contenu d’une variable ou le
résultat d’une expression, dans une variable.

Syntaxe

Nom_variable Å expression

Exemples

A Å 5
A Å B
A Å B+5
y ← ((n+10)*q)/t
cond_admis ← (m >= 10 et Nb_mod_val > ; avec
7)
Nb_mod_val : le nombre de module validé et m la moyenne générale.

Remarques

• A gauche du symbole d'affectation il y a toujours une variable, les


instructions suivantes sont invalides :
A+5 Å 3
15 Å C
PI Å 22/7

• La variable à gauche du symbole d'affectation et la valeur affectée


doivent être de même type, les instructions suivantes sont invalides :
A, B, C : entiers
A Å ‘T’
B Å " Bonjour"
C Å 12.5

• On peut par contre affecter une expression entière à une variable réelle.
A : entier
B, C : réels
A Å 12
B Å A div 2
C= 15
Exercices

1. Ecrire un algorithme qui permet d'échanger le contenu de deux


variables A, B.

2. Ecrire un algorithme qui permet de permuter les contenues de trois


variables A, B, C.

A.Zahi/DI/FSTF
12

3.2. Lecture /écriture

L'instruction de lecture lire permet d'alimenter le programme par des


données à partir de l'extérieur. Elle consiste à lire une valeur sur le clavier et
l’affecter ensuite à une variable.

Syntaxe

lire (var1, var2,..., varn)

Exemple

algorithm lecture
variables
X :entier
Rayon : réel
C : caractère
debut
lire(X)
lire (rayon)
lire(c)
Fin

L'instruction d'écriture écrire permet d’afficher sur un périphérique de


sortie, l’écran à priori, le résultat d’une expression. L’expression peut être
composée, une constante ou une variable.

Syntaxe
ecrire(exp1, ..., expn)

Exemples

algorithme ecriture
variables:
X :entier
Y :réel
Debut
Ecrire (" saisir la valeur de X")
Lire (X)
Y Å 2*X+1/X
Ecrire(" Valeur de Y = ", Y)
Fin

Exercices

1. Ecrire un algorithme qui permet de saisir : le prix hors taxe PHT, le


nombre d'articles NART, le taux TVA, de calculer le prix PTTC et
d’afficher :
PHT:
NBART :
TVA:
PTTC:

A.Zahi/DI/FSTF
13

2. La surface d’un triangle de côtés a , b et c est donnée par :


aire = S (S − a )(S − b )(S − c ) , avec S =
(a + b + c ) .
2

Ecrire un algorithme qui calcule l’aire. On suppose qu’on dispose


d’une fonction "racine2" qui calcule la racine carrée d’un nombre
réel.

3.3. Bloc d’instructions

Un bloc d’instructions est une suite d’instructions élémentaires délimitée


par les mots clés, Début et Fin, qui s’exécutent séquentiellement.

Exemple

Début
lire(x);
lire(y);
z ← x + y;
écrire(‘z=‘,z);
Fin

3.4. Choix

Une instruction de choix permet de choisir, suivant une condition, entre


deux ou plusieurs blocs d'instructions. Le choix peut se présenter sous plusieurs
formes: sans alternative, avec alternative, imbriquée ou multiple.

3.4.1. Choix sans alternative

Syntaxe

Instr_avant_si

si (condition) alors
Bloc_instrs
finsi

Instr_après_si

 Condition est une expression logique, si elle est vraie alors on exécute
les instructions Bloc_instrs, sinon on passe aux instructions suivantes.

 La figure 2 montre le fonctionnement de l’instruction si sans sinon.

A.Zahi/DI/FSTF
14

Instr_avant_si

vraie
Condition Bloc_instrs

fausse

Instr_après_si

Figure 2 : Organigramme de l’instruction si sans sinon

Exemples

1. Calcul de la valeur absolue d'un nombre réel.

Algorithme absolue
variables:
X, Val_X :réel
Debut
Ecrire("saisir la valeur de X :")
Lire (X)
Val_XÅ -X
si (X > 0) alors
Val_X Å X
finsi
Ecrire("valeur absolue de", X,"=", Val-X)
Fin

2. Calcul du maximum de deux entiers

Algorithme maximum
variables:
x, y, Max :entier
debut
Ecrire("saisir la valeur de X et Y :")
lire(X,Y)
Max Å x
si (x < y) alors
Max Å y
finsi
Ecrire ("Max (", X ",", Y, ")=", Max)
Fin

A.Zahi/DI/FSTF
15

Exercices

1. Ecrire un algorithme qui permet de saisir l’entier n et le réel x et


d’afficher la valeur de l’expression : (− 1)n * x .

2. Ecrire un algorithme qui saisit deux entiers et de les afficher dans l’ordre
décroissant.

3. Ecrire un algorithme qui permet de saisir trois caractères et ne les


afficher que s’ils sont dans l’ordre alphabétique.

3.4.2. Choix avec alternative

Syntaxe

Instr_avant_si

si (condition) alors
Bloc_vraie
sinon
Bloc_fausse
finsi
Instr_après_si

 Condition est une expression logique si elle est vraie alors on


exécute les instructions Bloc_vraie, sinon on exécute les
instructions Bloc_fausse, le choix d’une alternative exclue l’autre.

 La figure 3 montre le fonctionnement de l’instruction si avec sinon.

Instr_avant_si

fausse vraie
Condition

Bloc_fausse
Bloc_vraie

Instr_après_si

Figure 3 : Organigramme de l’instruction si avec sinon

A.Zahi/DI/FSTF
16

Exemples
1. Une droite est définie par deux points, A = (x1 , y1 ) et B = (x 2 , y 2 ) ,
l’algorithme ci-dessous saisit les points, A , B et P = (x , y ) , et décide si le
point P appartient à la droite ( AB ) .

Algorithme disible
variables:
x, y, xa, ya, xb, yb :réels
debut
Ecrire ("Saisir le point A")
lire(xa, ya)
Ecrire ("Saisir le point B")
lire(xb,yb)
Ecrire ("Saisir le point P")
lire(x,y)
si ((ya-y)*(xb-x) = (xa-x)*(yb-y) ) alors
ecrire("P appartient à la droite")
sinon
ecrire("P n’appartient pas à la droite")
finsi
Fin

2. L’algorithme suivant saisit deux entiers, x et y , et décide si x est divisible


par y .

Algorithme divisible
variables:
x, y :entier
debut
Ecrire("Saisir x et y")
lire(x,y)
si (x mod y == 0 ) alors
ecrire( x, "est divisible par", y)
sinon
ecrire( x, "n’est divisible par", y)
finsi
Fin

Exercices
1. Ecrire un algorithme qui saisit deux entiers, a et b , et qui affiche
l’expression b = a * q + r avec p et r le résultat de la division entière de
b par a . Il faut prendre en considération la cas où b est divisible par a .
Exemples
 15 = 7* 2 + 1
 10 = 5*2

2. La fonction caractéristique de ’un intervalle I = [a , b] est définie par :


1, si x ∈ I
χ (x ) =  . Ecrire un algorithme qui saisit un réel x et qui affiche
0, sinon
la valeur de χ (x )

3. Ecrire un algorithme qui saisit deux points, A = (x1 , y1 ) et B = (x 2 , y 2 ) ,


calcul et affiche la déviation de la droite ( AB ) par rapport à l’axe (Ox ) .

A.Zahi/DI/FSTF
17

4. Ecrire un algorithme qui saisit trois réels x , a et b et affiche l’image de


x par la fonction, définie sur (− ∞ , b] , représentée par le graphe suivant :

a b
5. Trois nombres positifs peuvent représenter les cotés d’un triangle dans
la mesure où chacun d’entre eux est inférieur à la somme des deux
autres. Ecrire un algorithme qui saisit les trois nombres et affiche si on
peut construire un triangle avec.

3.4.3. Choix imbriqué

Dans l’un des blocs d’une instruction de choix on peut avoir une
instruction qui contient une autre instruction de choix et ainsi de suite. On dit
dans ce cas que le choix est imbriqué.

Syntaxe
Instr_avant

si (condition_1) alors
si (condition_11) alors
.
.
sinon
.

finsi

sinon si (condition_2)
.
.
Sinon
.
.
finsi
finsi

Instr_après

 L’exécution de cette instruction se base sur le fait qu’un sinon


correspond au si le plus proche.

 Une représentation arborescente permet d’identifier tous les cas


possibles et aussi d’organiser les différents choix. Etant donnée un
problème dont le choix est représenté par l’arbre suivant :

A.Zahi/DI/FSTF
18

C1
F v

C5 C2
F v v
F
Bloc52 Bloc51 Bloc2 C3
v
F

Bloc3 C4
v

Bloc4

Figure 4 : Représentation graphique du choix imbriqué

La partie de l’algorithme correspondant se présente comme suit :

si (c1) alors
si (c2) alors
si (c3) alors
Bloc3
sinon
si (c4) alors
bloc4
finsi
finsi
sinon
bloc2
finsi
sinon
si ( c5) alors
bloc51
sinon
bloc52
finsi
finsi

Exemple
Calcul du maximum de trois nombres entiers a, b et c à saisir. La solution peut
être représenté par l’arbre suivant :
a>b
V F

a>c b>c

V F V F

Max=a Max= c Max=b Max= c

Figure 5 :Représentation graphique du max(a,b,c)

A.Zahi/DI/FSTF
19

algorithme maximum3
variables :
a,b,c,max : entier
debut
Ecrire (" Saisir a, b et c :")
lire(a,b,c)
si (a > b) alors
si (a > c) alors
max ← a
sinon
max ← c
finsi
sinon
si (b > c) alors
max ← b
sinon
max ← c
finsi
finsi
ecrire(max)
fin

Exercices
1. Soient a, b et c trois réels, écrire un algorithme qui permet de résoudre
dans IR l’équation: a X2 + b X + c = 0. Etudier tous les cas.

2. Ecrire un algorithme qui permet de saisir cinq réels x , a , b , c , d , et


d’afficher l’image de x par la fonction représentée par le graphe
suivant :

a b c d
3. La mention de réussite est attribuée en fonction de la moyenne de
l’étudiant selon le tableau suivant :

Moyenne Mention
18 ≤ m Très Bien
14 ≤ m <18 Bien
12 ≤ m <14 Assez Bien
10 ≤ m <12 Passable

Ecrire un algorithme qui saisit la moyenne et affiche la mention


correspondante.

4. Ecrire un algorithme qui permet de saisir deux réels, x et y , et


d’afficher le nombre complexe associé sous la forme : z = x + iy . Etudier
tous les cas.

5. Ecrire un algorithme qui permet de saisir deux droites, ( AB ) et (CD ) ,


et d’afficher si elles sont perpendiculaires, parallèles ou colinéaires.

A.Zahi/DI/FSTF
20

3.4.4. Choix multiple

Si l’instruction si- sinon finsi permet de choisir seulement entre deux


alternatives, l'instruction selon, par contre, permet de choisir entre plusieurs.

Syntaxe
Instr_avant_selon

selon (expr)
val_1 : Bloc_1
val_2 : Bloc_2

...

val_n :Bloc_n
autrement : Bloc_a
finselon

Instr_après_selon

 L'expression, expr, est évaluée, si sa valeur est identique à l'une des


valeurs val_1,...,val_n, alors le bloc d'instructions correspondant est
exécuté, sinon, c’est le bloc correspondant à la clause autrement qui
est exécuté.

 La figure 6 montre l’exécution de l’instruction selon.

Instr_avant_selon

Evaluation de l’expression

val_1 val_2 val_n autrement

Bloc_1 Bloc_2 Bloc_n Bloc_a

Instr_après_selon

Figure 6 : Organigramme de l’instruction selon

Exemple

Selon la couleur du feu de circulation, Rouge, Vert ou Jaune, un chauffeur


exécute les opérations, Arrêter, Avancer ou Ralentir, l’algorithme ci-dessous
permet de simuler le comportement du chauffeur. A chaque couleur on associe
un entier entre 0 et 2 et suivant la valeur saisie on exécute l'action appropriée.

A.Zahi/DI/FSTF
21

Algorithme Feu
variables:
Couleur: entier
debut
Ecrire (" Quel est la couleur du feu")
Lire (Couleur)
Selon (Couleur)
0 : Ecrire (" Arrêter ")
1 : Ecrire (" Avancer ")
2 : Ecrire (" Ralentir ")
autrement : Ecrire (" Feu en panne")
finselon
Fin

Exercices

1. Une exploitation agricole utilise un robot pour contrôler la température


de ses serres. Selon le temps qu’il fait, Pleut, chaud, froid, beau, le
robot exécute les opérations, Fermer la serre, Déclancher le
ventilateur, Déclancher le chauffage, Ouvrir la serre.

Ecrire un algorithme qui permet de simuler le fonctionnement d’un


robot.

2. Dans un magasin, le prix de vente d’un produit est calculé par la


formule: Prix_ttc = prix_ht + (tva * prix_ht). Cinq classes de tva sont
définies selon l’indice du produit.

Indice tva
1 0
2 0.05
3 0.1
4 0.15
5 0.2

Ecrire un algorithme qui saisit le prix hors taxe prix_ht et l’indice d’un
produit indice, calcule et affiche le prix_tcc équivalent.

3. Un garagiste utilise un code pour chaque activité du garage. CODE=1


pour la vente des voitures neuves, CODE=2 pour la vente des voitures
d’occasion, CODE=3 pour la vente des pièces détachées et CODE=4
pour la réparation des voitures. La commission d’un employé est
calculée sur chaque activité de la manière suivante : sur une voiture
neuve, 2% du prix de vente mais avec un maximum de 5000DH, sur une
voiture d’occasion, 5% du prix de vente mais avec un minimum de
500DH,sur les pièces détachées 6% du prix total et enfin sur la
réparation d’une voiture 10% du prix de la main d’œuvre.

Ecrire un algorithme qui saisit le code de l’activité et le prix


correspondant et qui affiche la commission.

A.Zahi/DI/FSTF
22

3.5. Répétition
3.5.1. Présentation des boucles

Une boucle est une instruction qui permet de décrire une répétition dans un
algorithme. Elle consiste à répéter l’exécution d’un bloc d’instructions, appelés
corps de la boucle, un certain nombre de fois, une exécution du bloc s’appelle
itération. Il existe trois formes de boucles : tant que, répéter et pour, chacune est
caractérisée par les éléments suivants :

• Le bloc d'instructions à répéter (corps),

• Une condition d’arrêt, c'est une expression logique qui permet l'arrêt de
la boucle, une fois le nombre d'itérations est achevé.

• Le nombre d'itérations, deux cas de figure sont distingués :

Ž Le nombre d'itérations est connu à l’avance,

Ž Le nombre d'itérations est inconnu à priori, dans ce cas l’arrêt


est déterminé par le corps de la boucle.

3.5.2. Boucle tant que

Syntaxe

Instr_avant

tant que (Condition)


faire

Bloc
fintantque

Instr_après

 Condition est une expression logique, le bloc d’instruction est


exécuté jusqu’à ce que la condition devienne fausse.

 La figure 7 montre l'exécution de la boucle tant que.

A.Zahi/DI/FSTF
23

Instr_avant_tantque

vraie
Condition Corps de la boucle

fausse

Instr_après_tantque

Figure 7 : organigramme de la boucle tant que

Comment réaliser une boucle tant que ?

Selon la connaissance du nombre d’itérations, trois cas se présentent pour


la réalisation d’une boucle tant que :

• Premier cas : le nombre d’itération est connu à l’avance. Dans ce cas nous
aurons besoin des éléments suivants :

Ž Un entier N qui représente le nombre d'itérations.

Ž Un entier C, appelé compteur, qui représente le numéro de l'itération en


cours.

Ž L’instruction, C Å Vin, qui permet l’initialisation du compteur avec


une valeur initiale Vin.

Ž L’instruction C Å C+1 qui permet l’incrémentation du compteur après


chaque itération. Cette instruction doit être insérée dans le corps de la
boucle.

Ž L’expression logique, (C<= N + Vin -1), qui représente la condition


d’arrêt de la boucle.

Ainsi, on obtient la partie de l’algorithme suivante:


C Å Vin
tant que (C <= N+Vin-1) faire
Bloc
C Å C+1
fintantque

A.Zahi/DI/FSTF
24

Exemples
n
1. Calculer la somme des n premiers entiers : ∑i
i =1
algorithme somme
variables :
n,s,i :entier
début
Ecrire ("Saisir n")
lire (n)
i ← 1
s ← 0
tantque(i≤n) faire
s ← s+i
i ← i+1
fintantque
écrire ("Somme=", s)
fin

2. Calcul du nombre d’entiers inférieurs à n qui sont divisibles par un


entier k donné.

algorithme combien
variables :
nb,n,k,i :entier
début
Ecrire ("Saisir n")
lire (n)
Ecrire ("Saisir k")
lire(k)
i ← 1
nb ← 0
tantque(i≤n) faire
si (i mod k = 0)
nb ← nb + 1
finsi
i ← i+1
fintantque
écrire ("le nombre est :", nb)
fin

• Deuxième cas : le nombre d’itérations n’est pas connu et l’arrêt de la boucle


est décidé par l’utilisateur de l’algorithme. Pour cela on utilise une question,
du type "voulez-vous continuez oui/non ?", qu’on affiche après chaque
itération. L'utilisateur saisit ensuite sa réponse qui permet à l’algorithme soit
de passer à l’itération suivante, soit de mettre fin à la boucle. Dans ce cas
nous aurons besoin des éléments suivants :

Ž Un caractère, Rep, qui permet de stocker la réponse de l'utilisateur

Ž L’instruction, Rep Å "O", qui permet d’initialiser la variable Rep

Ž L’instruction d’affichage, ecrire(" texte de la question O/N"), qui


affiche la question pour utilisateur.

Ž L’instruction de lecture, lire(Rep), qui saisit la réponse utilisateur.

A.Zahi/DI/FSTF
25

Ž L’expression logique, (Rep ≠ ‘N’), qui représente la condition d’arrêt.

Ainsi, on obtient la partie de l’algorithme suivante:


Rep Å "O"
tant que (Rep ≠ "N")
faire

Bloc
ecrire(" texte de la question O/N"),
lire(Rep)

fintantque

Exemple

Un client achète plusieurs produits où chaque produit est caractérisé par la


quantité achetée qa et son prix unitaire pu . Etablir l'algorithme qui calcul
et qui affiche le montant total à payer par un client. Le montant d'achat d'un
seul produit est donné par la formule mp = qa * pu .

Algorithme client
Variables
Rep : caractère
MT, mp, pu : réel
Debut
MTÅ 0
Rep Å '0'
Tant que ( Rep='O') faire
Lire(qa,pu)
Mp Å qa*pu
MT Å MT+mp
Ecrire("Un autre produit O/N")
Lire (Rep)
Fintant que
Fin

• Troisième cas: le nombre d’itérations est inconnu et l’arrêt de la boucle est


décidé par l’algorithme lui-même. Dans ce cas la condition d’arrêt est
déterminée à partir de l’énoncé du problème et de la méthode de résolution
proposée.

Exemple

Saisir une phrase caractère par caractère, la fin de la phrase est identifiée par
le caractère ‘.’

algorithme saisir_phrase
variables :
c :caractère
début
lire (c)
tantque(c ≠ ‘.’) faire
lire (c)
fintantque
fin

A.Zahi/DI/FSTF
26

Exercices
1. Ecrire un algorithme qui calcul x n , avec x et n sont donnés.

2. Ecrire un algorithme qui calcul n! , avec n donné.

3. Ecrire un algorithme qui calcul la somme de n entiers saisis au clavier.

4. Soit la suite définie par :


 x0 = 1

 1 a 
 xn = 2  xn −1 + x 
  n −1 

La suite (xn )n converge vers a , écrire un algorithme qui calcul une


valeur approchée de a.

5. Soit la suite définie par :


 F0 = 0, F1 = 1

 Fn + 2 = Fn +1 + Fn
• Ecrire un algorithme qui calcul le nème terme de la suite (Fn )n .
Fn +1
• La suite Dn = converge vers un nombre φ , appelé nombre
Fn
d’or, écrire un algorithme qui calcul une valeur approché de φ .

6. Dans un établissement, les candidats au concours d’entrée au 2ème cycle


sont sélectionnés sur la base de l’âge et de la moyenne générale du
DEUG. L’âge doit être inférieur à 24 ans et la moyenne supérieure à 12
et si l’âge est inférieur à 26 ans la moyenne doit être supérieure à 16.
Ecrire un algorithme qui calcul le nombre de candidats sélectionnés.

7. Ecrire un algorithme qui saisit un entier et qui affiche sa représentation


binaire.

3.5.3. Boucle répéter

Syntaxe
Intsr_avant

répéter

Bloc
Jusqu’à (Condition)

Instr_après

 Condition est une expression logique, le bloc d’instructions est


répété jusqu’à ce que condition devienne vraie.

 La figure 8 correspond à l'exécution de la boucle répéter.

A.Zahi/DI/FSTF
27

Instr_avant_repeter

Corps de la boucle

fausse
Condition

vraie

Instr_après_repeter

Figure 8 : Organigramme de la boucle répéter

Comment réaliser une boucle répéter ?

Selon la connaissance du nombre d’itérations, trois cas se présentent pour


la réalisation d’une boucle répéter:

• Premier cas : le nombre d’itérations est connu à l’avance. Dans ce cas nous
utilisons les mêmes éléments que ceux de la boucle tant que, seule la
condition d’arrêt est diffère, elle devient (C > N + Vin -1). Ainsi, on
obtient la partie de l’algorithme suivante:

C Å Vin
répéter
Bloc
C Å C+1
Jusqu’à (C > N+Vin-1)

Exemples
n
1. Calcul de la somme des n premiers entiers : ∑i
i =1
algorithme somme
variables :
n,s,i :entier
début
Ecrire ("Saisir n")
lire (n)
i ← 1
s ← 0
répéter
s ← s+i
i ← i+1
Jusqu’à( i>n)
écrire ("Somme = ", s)
fin

A.Zahi/DI/FSTF
28

2. Calcul du nombre d’entiers < à n qui sont divisibles par un entier k saisi.

algorithme combien
variables :
nb,n,k,i :entier
début
Ecrire ("Saisir n et k ")
lire (n, k)
i ← 1
nb ← 0
repéter
si (i mod k = 0)
nb ← nb + 1
finsi
i ← i+1
jusqu’à (i>n)
écrire ("le nombre est :", nb)
fin

• Deuxième cas : le nombre d’itérations n’est pas connu et l’arrêt de la boucle


est décidé par l’utilisateur de l’algorithme. Dans ce cas aussi nous utilisons
les mêmes éléments que ceux de la boucle tant que, seule la condition d’arrêt
diffère, elle devient (Rep = "N").

Ainsi, on obtient la partie de l’algorithme suivante:

Rep Å "O"
répépter

Bloc
ecrire(" texte de la question O/N"),
lire(Rep)

jusqu’à (Rep="N")

Exemple

Un client achète plusieurs produits où chaque produit est caractérisé par la


quantité achetée qa et son prix unitaire pu . Etablir l'algorithme qui permet
de calculer et afficher le montant total à payer par un client. Le montant
d'achat d'un seul produit est défini par mp = qa * pu .

Algorithme client
Variables
Rep : caractère
MT, mp, pu : réel
Debut
MTÅ 0
Rep Å '0'
répéter
Lire(qa,pu)
Mp Å qa*pu
MT Å MT+mp
Ecrire("Un autre produit a/N")
Lire (Rep)
Jusqu’à(Rep=’n’)
Fin

A.Zahi/DI/FSTF
29

• Troisième cas: le nombre d’itérations est inconnu et l’arrêt de la boucle est


décidé par l’algorithme lui-même. Dans ce cas également la condition
d’arrêt est déterminée à partir de l’énoncé du problème et de la méthode de
résolution proposée.

Exemple
Saisir une phrase caractère par caractère, la fin de la phrase est identifiée par
le caractère ‘.’

algorithme saisir_phrase
variables :
c :caractère
début
lire (c)
répeter
lire (c)
jusqu’( c=’.’)
fin

Exercices
Refaire les exercices de la page 23 en utilisant la boucle répéter.

3.5.4. Boucle pour

Syntaxe

Instr_avant

pour i allant de vi à vf
faire

Bloc
finpour

ou de façon générale

pour i allant de vi à vf incrément/décrément pas


faire
Bloc
finpour

Instr_après

 vi, vf : valeur initial et valeur finale du compteur de la boucle.

 Pas la valeur avec la quelle on incrémente ou on décrémente le


compteur de la boucle à chaque itération.

 Dans cette dernière forme, le nombre d'itérations doit être connu au


préalable, le compteur de la boucle est incrémenté / décrémenté
automatiquement de la valeur pas.

 La figure 9 correspond à l'exécution de la boucle Pour.

A.Zahi/DI/FSTF
30

Instr_avant_pour

I Å val_initiale

incrément

vraie
I <= val_finale Corps de la boucle

fausse

Instr_après_pour

Figure 9 : Organigramme de la boucle pour

Exemples

1. Affichage des nombres pairs inférieurs à n


algorithme pair
variables :
n,i :entiers
début
ecrire("saisir n")
lire (n)
pour i allant de 2 à n incrément pas = 2
faire
ecrire (i)
finpour
fin
n
2. Calculer la somme des n premiers entiers : ∑i i =1
algorithme somme
variables :
n,s,i :entier
début
Ecrire ("Saisir n")
lire (n)
s ← 0
pour I allant de 1 à n
faire
s ← s+i
finpour
écrire ("Somme=', s)
fin

A.Zahi/DI/FSTF
31

Exercices

1. Ecrire un algorithme qui permet de calculer n! , n est saisi au clavier.

2. Ecrire un algorithme qui permet de calculer x n , n et x sont saisis au


clavier.

3. Ecrire un algorithme qui permet d’afficher les entiers inférieurs n qui


sont divisibles par un entier k saisi au clavier. Donner les formes.

4. Ecrire un algorithme qui permet d’afficher les diviseurs d’un entier n


saisi au clavier.

5. On suppose qu’on ne dispose pas de l’opérateur *, écrire un algorithme


qui permet de calculer le produit deux entiers.

6. Un triplet ( p , q , r ) d’entiers naturels est dit pythagoricien si et seulement


si p 2 + q 2 = r 2 . Ecrire un algorithme qui permet d’afficher tous les
triplets pythagoriciens ( p , q , r ) , avec, p et q < n , n saisi au clavier.

7. Ecrire un algorithme qui permet de calculer la valeur de la fonction


i =n
x
f n (x ) = ∑ i! , x et n saisis au clavier.
i =1

A.Zahi/DI/FSTF
32

Chapitre 1: Eléments du langage C

1. Eléments lexicaux
1.1. Identificateurs

Un identificateur est une suite de caractères alphanumériques, qui permet


de désigne les objet d’un programme, plus précisément: les variables, les
constantes symboliques, les fonctions et les types construits par le
programmeur. Le choix d’un identificateur doit obier aux règles suivantes :

• Un identificateur commence toujours par une lettre,

• Un identificateur ne contient pas les caractères spéciaux et accentués, le


caractère souligné ’’_’’ est considéré comme une lettre,

• Un mot-clé n’est pas un identificateur.

• Les majuscules et minuscules sont différenciées.

• Au de là d’une certaine longueur, généralement 31 caractères, le


compilateur peut tronquer les identificateurs.

1.2. Mots clés

Un certain nombre de mots, appelés mots clés, sont réservés aux


instructions du langage. Le tableau ci-dessous contient les 32 mots clés du
langage C qu’on peut classer en plusieurs catégories :

Catégories Mots clés


spécificateurs de stockage auto, register, static, extern, typedef
char, double, enum, float, int, long, short,
spécificateurs de type signed, struct, union, unsigned, void
qualificateurs de type const, volatile
break, case, continue, default, do, else, for,
instructions de contrôle goto, if, switch, while
Divers return, sizeof

2. Structure d’un programme C

Un programme C est composé par des variables, des instructions et des


fonctions. La structure d’un programme C se présente comme suit :

A.Zahi/DI/FSTF
33

[directives de compilation]
[déclarations des variables globales]
[déclarations des fonctions]
void main()
{
déclarations des variables locales
Instructions
}

2.1. Les commentaires

Un commentaire est un texte mis entre les caractères ‘/*’ et ‘*/’. Il permet
de documenter un programme pour une meilleure lisibilité et une maintenance
facile (correction, modification etc.).

Exemples :

/* ceci est un commentaire */


/*/* ceci n’est pas un commentaire */*/

2.2. Instructions
2.2.1. Instructions directement exécutables

• Instruction élémentaire : c’est une expression terminée par un point


virgule ( ; ).

expression ;

• Instruction composée, c’est une suite d’instructions élémentaires,


délimitée par des accolades {}, appelée bloc. Elle permet de regrouper un
ensemble d’instructions sous la forme d’une seule.

Exemple

/* Permutation des valeurs de a et b*/


void main()
{
int a=2 ;
int b=5 ;
int temp;
{
temp=b ;
b=a ;
a= temp ;
}
}

Remarques

• Contrairement aux expressions, les instructions n’ont ni type ni valeur.


Lorsqu’on construit une instruction à partir d’une expression la valeur de
cette dernière est perdue.

• N’importe quelle expression peut former une instruction.

A.Zahi/DI/FSTF
34

2.2.2. Instructions du préprocesseur

Ce sont des instructions particulières appelées directives de compilation.


Elles permettent au compilateur d’effecteur un pré-traitement sur le texte du
programme avant sa compilation. Une directive de compilation commence
toujours par le caractère #, les deux directives de compilation les plus
importantes sont :

• La directive # define permet la définition des pseudo-constantes et des


pseudo-fonctions.

• La directive # include permet l’inclusion d’un fichier d’extension .h,


appelé fichier en-tête, dans le texte source du programme. Les fichiers
en-tête contiennent, généralement la déclaration des constantes et des
fonctions. On distingue deux catégories de fichiers en-tête :

Ž Les fichiers de la bibliothèque qui sont inclus à l’aide de


l’instruction #include <en_tete.h>

Ž Les fichiers construits par le programmeur qui sont inclus à


l’aide de l’instruction #include ’’en_tete.h’’

Exemple

/* Inclusion du fichier d’entrées sorties standard*/


#include <stdio.h>
#include <stdlib.h>

/* definition d’une pseudo-constante*/


#define PI 3.14

/* definition d’une pseudo-fonction*/


#define CARRE(x) ((x)*(x))
void main()
{
int n=25 ;
float rayon ;
printf(’’donner le rayon du cercle’’) ;
scanf(’’%f’’, &rayon) ;

surface = PI*rayon *rayon ;


printf(’’S = %f ’’, surface) ;

ptintf("carre de n = %d", CARRE(n)) ;


}

2.3. Fonctions

L’une des caractéristiques du langage C est qu’il est composé par une ou
plusieurs fonctions. Une fonction est une entité indépendante formée par un
ensemble d’instructions et qui effectue une tâche bien précise, on distingue
trois types de fonctions :

A.Zahi/DI/FSTF
35

• La fonction principale main():c’est une fonction obligatoire dans tout


programme C, elle constitue le point d’entrée lors de l’exécution d’un
programme.

• Les fonctions de la bibliothèque, ce sont des fonctions fournies avec le


compilateur comme printf et scanf.

• Les fonctions secondaires : ce sont des fonctions définies par le


programmeur.

Exemple : Surface d’un cercle

#include <stdio.h>
#define PI 3.14

/* fonction secondaire qui permet de calculer la surface


d’un cercle */

float calc_surface (float r)

{
float s ;
s= PI*r*r ;
return (s) ;
}

/* fonction principale */

void main()

float rayon, surface ;

/* fonctions de la bibliothèque stdio.h */


printf(’’ Rayon= ?’’) ;
scanf(’’%f’’, &rayon) ;

surface = calc_surface(rayon) ;
printf(’’ Surface = %f\n’’, surface) ;

A.Zahi/DI/FSTF
36

2.4. Compilation d’un programme C

Editeur de texte Edition du texte


source

• .cpp .c
• format ASCII

Préprocesseur Traitement des


directives de
compilation

Compilateur Compilation et
génération du code
objet

• .obj
• format binaire

• Inclusion du
code objet des
Editeur des liens fichiers inclus

• Génération du
code exécutable

• .exe
• format binaire

Figure 10 : Processus de compilation en langage C

3. Variables et Types de base


3.1. Types de base

Le langage C est un langage typé i.e. chaque objet est associé à un type qui
définit la représentation en mémoire et l’ensemble des valeurs qu’il peut prendre.
Les types de base en C concernent les caractères, les entiers et les réels.

A.Zahi/DI/FSTF
37

Un type est caractérisé par :

• Un mot clé.

• La taille de l’espace mémoire, en octets, occupée par un objet de ce type.


Elle dépend en générale de la machine utilisée.

• L’ensemble des valeurs susceptibles d’être prises par un objet.

3.1.1. Les caractères

Le type caractère est désigné par le mot clé char, les valeurs prises par les
objets de ce type sont le jeu de caractères de la machine utilisée. Chaque objet
est codé sur 1 octet.

3.1.2. Les entiers

Les entiers peuvent être affectés de deux attributs :

• Un attribut de précision, désigné par short et long, permet de préciser la


représentation interne de l’objet en termes d’espace mémoire.

• Un attribut de représentation, désigné par unsigned et signed, permet de


préciser l’utilisation ou non du bit de signe.

Ces attributs peuvent être combinés pour former plusieurs types numériques :

Mot clé Description Valeur min Valeur max Taille en octets


Int entier standard -32768 32767 2 octets
short int entier court -32768 32767 2 octets
long int entier long -2147483548 2147483547 4 octets
unsigned int entier standard non 0 65535 2 octets
signé
unsigned entier court non 0 65535 2 octets
short int signé
unsigned long entier long non 0 4294957295 4 octets
int signé

3.1.3. Les réels

Les réels sont caractérisés par leur précision (nombre de chiffre après la
virgule). Le langage C dispose de trois types de réels suivant la précision
désirée. Le tableau suivant montre leurs caractéristiques.

Mot clé Valeur min Valeur max Taille


float 3.4*10-38 3,4*1038 4 octets
double 1.7*10-308 1.7*10308 8 octets
long double 3.4*10-4932 1.1*104932 10 octets

A.Zahi/DI/FSTF
38

3.2. Variables

Une variable est un emplacement mémoire dont la valeur peut changer au


cours de l’exécution du programme.

3.2.1. Déclaration

Une variable doit faire l’objet d’une déclaration avant toute utilisation. Ce la
consiste à spécifier son type et son nom.

Syntaxe

type id1, id2,...,idn ;

 type est l’un des types de base, int, char, float, etc.

 id1, id2,...,idn : la liste des identificateurs.

Exemples
int compteur,X1,X2;
float hauteur,largeur;
double masse_atomique;
char touche;

3.2.2. Initialisation

En C il est possible d’initialiser une variable lors de sa déclaration,


l’initialisation se fait suivant la syntaxe suivante :

Syntaxe

type identi = valeur ;

Exemple
void main()
{
int compteur = 0 ;
float hauteur = 3.14 ;
char Rep = ‘O’;
}

Remarque

Une variable peut être déclarée à plusieurs niveaux d’un programme : dans
un fichier externe, dans la fonction main, dans une fonction secondaire ou dans
bloc d’instructions.

A.Zahi/DI/FSTF
39

4. Les constantes
4.1. Constantes littérales

C’est une valeur qui apparaît littéralement dans le code source d’un
programme, le type de la constante dépend de son écriture.

4.1.1. Constantes réels

Les constantes réels ou encore les constantes flottantes sont représentés par
la notation mantisse-exposant, l’exposant est désigné par la lettre e ou E.

Remarque

Une constante réelle est par défaut de type double. Pour la forcer à avoir
une représentation sous forme d’un float (resp. long double) on doit l’affecte
de l’attribut f ou f(resp. L).

Exemples
Constante type
15.25 double
15.2e-4 double
15.25f float
15.25l long double

4.1.2. Constantes entières

Les constantes entières peuvent s’exprimer dans les systèmes décimal, octal
ou hexadécimal.

• Notation décimal : la constante est une suite qui commence par un chiffre
différent de 0, suivie de chiffres entre 0 et 9.

• Notation octal : La constante est une suite qui commence par le chiffre
zéro 0, suivie de chiffres entre 0 et 7.

• Notation hexadécimal : la constante est une suite de caractères qui


commence par les caractères 0x et 0X, suivie de chiffres entre 0 et 9 et
de lettres entre a et f.

Remarque

Une constante entière est par défaut de type int. Pour forcer la constante à
avoir une représentation sous forme d’un entier long : long int (resp court) on
doit l’affecter de l’attribut l ou L (resp. de u ou U).

A.Zahi/DI/FSTF
40

Exemples
Constante type
2001 int
02589 int /*octal*/
0x4D7 int /*héxadécimal*/
12458798L long int
1247U unsigned int
12458798UL Unsigned long int

4.1.3. Constantes caractères

Les constantes de type caractère sont assimilées à un entier sur un octet dont
la valeur correspond à la position du caractère dans la table ASCII.

• Les caractères imprimables : il suffit de mettre le caractère entre


apostrophes, par exemple ‘a’, ‘A’, ‘c’, ‘$’. Les seuls caractères
imprimables qui ne s’écrivent pas de cette manière sont : l’antislash \ et
l’apostrophe ’, qui s’écrivent : \\ et \’.

• Les caractères non imprimables: la constante est constituée de deux


caractères entre guillemets dont le premier est \, dans ce cas on l’appelle
séquence d’échappement. Le tableau ci-dessous présente la liste des
séquences d’échappement les plus utilisées.

Constante Nom
\n Retour à la ligne
\t Tabulation horizontale
\v Tabulation verticale
\b Retour arrière
\r Retour chariot
\f Saut de page
\a Signal d’alerte

4.1.4. Constantes chaînes de caractères

Une constante chaîne de caractères est une suite de caractères entre


guillemets. En mémoire cette suite se termine par le caractère NULL ’\0’.

Exemple

’’quoi qu’on dise quoi qu’on face’’


’’Les malheurs sont la ponctuation de la vie’’

Remarque

Il ne faut pas confondre ’a’ qui est une constante caractère et ’’a’’ qui est
une constante chaîne de caractères.

A.Zahi/DI/FSTF
41

4.2. Constantes symboliques

Une constante symbolique est un objet dont la valeur ne change pas au cours
de l’exécution du programme. Elle est représentée par un nom qu’on peut
utiliser chaque fois qu’on a besoin de la constante. Deux types de constantes
symboliques peuvent être distinguées.

4.2.1. Pseudo-constantes

C’est une constante dont le nom est attribué par la directive #define. Le
préprocesseur remplace chaque occurrence du nom par la valeur de la constante
sans aucune vérification de type.

Syntaxe
#define IDENF val_subst

 IDENF : Identificateur qui représente le nom de la constante.

 val_subst: représente la valeur de la constante.

Exemple

#define PI 3.14159
#define G 9.81
void main()
{
float s,r =12.5;
float m=15;
s = PI*r*r ;
P = G * m ;
}

Remarque

• Il est préférable d’utiliser des noms en majuscules pour désigner les


constantes symboliques afin de les différentier des autres objets (variables
et fonctions).

• La définition d’une constante n’est pas une déclaration, il n’y a pas donc
de point virgule ; à la fin.

4.2.2. Constantes variables

C’est une constante déclarée comme une variable dont on ne peut pas
modifier le contenu au cours du programme. Elle occupe donc un espace en
mémoire centrale.

A.Zahi/DI/FSTF
42

Syntaxe

const type id = valeur;

 const : mot clé qui indique que id est une constante.

 id : identificateur qui représente le nom de la constante.

 type: l’un des types de base.

 valeur : valeur de la constante.

Exemple

void main()
{
float s,r=11.6;
const float PI=3.14
s= PI*r*r ;
}

5. Fonctions standards d’entrée/sortie

La librairie standard <stdio.h> contient un ensemble de fonctions qui


permettent de communiquer avec l’environnement extérieur. L’appel à la
librairie <stdio.h> s’effectue par la directive de compilation # include.

5.1. Fonction printf

La fonction printf() permet de transférer le contenu d’une variable, d’une


constante ou le résultat d’une expression sur la sortie standard stdout, par défaut
l’écran. C‘est une fonction d’écriture formatée i.e., les arguments pris comme
paramètres sont convertis selon le format spécifié.

Syntaxe
printf(’’format’’, expr1, expr2,..., exprn) ;

 expr1, expr2, ..., exprn : les valeurs à afficher.

 format : une chaîne de caractères constituée par :

Ž Le texte à afficher.

Ž Des séquences d’échappement pour le contrôle de l’affichage.

Ž Des spécificateurs de format qui permettent d’annoncer le


format avec lequel l’expression doit être affichée. Pour chaque
expression on associe un spécificateur de format. Il est constitué
du symbole % suivie d’un caractère qui indique le format
d'impression.

A.Zahi/DI/FSTF
43

Symbole Type Impression comme

%d ou %i int entier relatif


%u int entier naturel (unsigned)
%o int entier exprimé en octal
%x int entier exprimé en hexadécimal
%c int Caractère
%f double rationnel en notation décimale
%e double rationnel en notation scientifique
%s char* chaîne de caractères
5.2. Fonction sacnf

La fonction scanf() permet de saisir des données à partir du clavier et les


stocke aux adresses fournies comme arguments.

Syntaxe

scanf(’’format’’, &v1, &v2,..., &vn) ;

 v1, v2,...,vn : les variables qui reçoivent les données saisies,


l’adresse de chaque variable est obtenue par l’opérateur &.

 format c’est une chaîne de caractères qui contient les


spécificateurs de format de chaque variable comme pour la
fonction printf. Un spécificateur de format est constitué du symbole
% suivie d’un caractère qui indique le format dans lequel la donnée
saisie doit être convertie.

Remarque

Les données saisies au clavier doivent être séparées par des espaces ou des
retour chariot, sauf s’il s’agit de la saisie d’un caractère.

5.3. Fonctions getchar() et putchar()

Les fonctions getchar() et getchar() permettent respectivement de saisir et


d’afficher des caractères.

Syntaxe
char c ;
c = getchar() ;
putchar(c) ;

 La fonction getchar() retourne un int qui correspond au caractère lu.


Elle retourne l’entier EOF, valeur définie dans stdio.h, qui
correspond à la fin de lecture.

 La fonction putchar() retourne un int qui correspond au caractère lu


ou la constante EOF, en cas d’erreur.

A.Zahi/DI/FSTF
44

Exemple

#include <stdio.h>
void main()
{
int c ;
while ((c = getch() != EOF)
putchar() ;
}

6. Expressions et Opérateurs

Un opérateur est un symbole qui décrit une opération ou une action à


effectuer sur un ou plusieurs opérandes. Les opérateurs sont classés en quatre
classes :

6.1. Opérateurs arithmétiques

Il existe cinq opérateurs arithmétiques en C qu’on peut classer en opérateurs


binaires et unaires.

• Addition, c’est un opérateur à la fois binaire et unaire (+ )

• Soustraction, c’est un opérateur à la fois binaire et unaire (- )

• Multiplication, c’est un opérateur binaire (* )

• Division, c’est un opérateur binaire (/ )

• Reste de la division entière, c’est un opérateur binaire (% )

Syntaxe

expr1 op expr2 /*pour les opérateurs binaires*/

op expr /*pour les opérateurs unaires*/

 expr1, expr2 et expr sont les opérandes. Pour les opérateurs +, -, *,


/ les opérandes peuvent être des entiers ou des réels. Pour
l’opérateur % les opérandes sont toujours des entiers.

Exemple

Le programme C ci-dessous permet de lire un entier, un réel et d’afficher


leur somme, leur différence et leurs produits:

A.Zahi/DI/FSTF
45

#include <stdio.h>
void main()
{
int nb ;
float re;
printf (’’donner nb et re : ’’) ;
scanf(’’%d %f’’, &nb, &re) ;
/* le résultat d’une opération entre un entier et un
réel est un réel */
printf (’’somme : %f\n’’, (nb+re)) ;
printf (’’différence : %f\n’’, (nb-re)) ;
printf (’’produit : %f\n’’, (nb*re)) ;
}

Remarque

Lorsque le type des deux opérandes n’est pas le même il y a conversion


implicite dans le type le plus fort. Soient x, y deux opérandes d’un opérateur et
a,b leurs types, la conversion se fait suivant la règle suivante :

si a est plus fort que b alors


convertir en a
sinon
convertir en b

6.2. Affectation

L’affectation permet de modifier les expressions qui se situent à gauche de


l’opérateur, deux types d’affectation :

• L’affectation simple, s’effectue à l’aide de l’opérateur =

• L’affectation composée, s’effectue à l’aide d’un opérateur op= construit à


partir de l’opérateur = et l’un des opérateurs (+, -, *, /, %).

Syntaxe

expr1 = expr2 /* Affectation simple */

expr1 op= expr2 /* Affectation composée */

 L’affectation composée, expr1 op= expr2 est équivalente à expr1


= expr1 op expr2.

A.Zahi/DI/FSTF
46

Exemple

#include <stdio.h>
void main()
{
int a, b ;
scanf(’’%d %d’’, &a, &b) ;
/* reste de la division de a par b*/
a %= b ;
a += b ;
a /= b ;

printf(’’le reste est %d’’, a) ;


}

6.3. Incrémentation décrémentation

Ce sont des opérateurs unaires qui permettent respectivement d’ajouter et de


retrancher 1 à la valeur de leur opérande.

Syntaxe

++ expr, expr++ /* Incrémentation */

--expr, expr-- /* Décrémentation */

 L’opérateur ++ permet d’ajouter 1 à la valeur de son opérande, les


expressions ++x et x++ sont équivalentes à x=x+1

 L’opérateur -- permet de retrancher 1 à la valeur de son opérande,


les expressions --x et x-- sont équivalentes à x=x-1

 La modification de l’expression se fait avant ou après l’évaluation


de l’expression et ceci suivant que l’opérateur est placé avant ou
après l’expression :

Ž expr, ++ expr : la modification se fait avant l’évaluation

Ž expr--, expr ++: la modification se fait après l’évaluation.


Exemple

#include<stdio.h>
main()
{
int a=50, b=60, x, y;
printf("a =%d ** b = %d", a, b);
x = ++a;
y = --b;
printf("\nx =%d ** y = %d", x, y);
x = a++;
y = b--;
printf("\nx =%d ** y = %d", x, y);

A.Zahi/DI/FSTF
47

6.4. Opérateurs Logique

Le résultat d’une opération logique est de type booléen. Or le type booléen


n’existe pas en C, la valeur d’une expression est 1 si elle est vraie, 0 si elle est
fausse. Toute valeur non nulle est considérée comme vraie et une valeur nulle
comme fausse.

Syntaxe
expr1 op expr2

 expr1, expr2 constituent les opérandes.

 op est l’un des opérateurs suivants : et logique (&&), ou logique (||),


négation (!), égalité(==), différent (!=), supérieure (>), supérieure ou
égale(>=), inférieure(<), inférieure ou égale(<=),

Exemple
char c ;
int i, age, n
float m ;

(c != ‘.’)
(i <= n && exist ==1)
(m>=12 && age <=24) || (m>=12 && age <26)

6.5. Opérateur conditionnel

L’opérateur conditionnel ?: est un opérateur ternaire, ses opérandes sont


des expressions.

Syntaxe
expr1 ? expr2 : expr3

 La valeur de l’expression conditionnelle est l’une des expressions


expr2 ou expr3. Si l’expression expr1 est vraie alors le résultat est
la valeur de l’expression expr2 sinon i.e., expr1 est fausse le
résultat est la valeur de l’expression expr3.

Exemples

1. Le programme ci-dessous permet d’afficher la valeur absolue d’un entier en


utilisant l’opérateur conditionnel.

#include <stdio.h>
main()
{
int x , abs_x;
printf (’’donner x : ’’) ;
scanf(’’%d ’’, &x) ;
abs_x = (x>=0) ? (x) : (-x) ;
printf (’’valeur absolue de x est : %d ’’, abs_x) ;
}

A.Zahi/DI/FSTF
48

2. Le programme ci-dessous permet d’afficher le maximum de deux entiers.

#include <stdio.h>
void main()
{
int x ,y, max;
printf (’’donner x et y : ’’) ;
scanf(’’%d%d ’’, &x, &y) ;
max = (x>y) ? (x) : (y) ;
printf (’’le maximum de x et y est : %d ’’,
max) ;
}

6.6. Expression

Une expression permet de représenter une valeur dans un programme. On


distingue deux types d’expressions :

• Expression simple, constituée par une seule variable, une seule constante
(littérale ou symbolique).

• Expression complexe, formée par une suite, d’opérateurs et


d’opérandes, les opérandes peuvent être des variables, des constantes
(littérales ou symboliques) ou des appels de fonctions.

Exemple

#define PI 3.14
#define G 9.8
#define TVA 0.20
int prixHT ;

/* Expressions simples*/
PI, G, /*constantes symboliques */
50, -1.6, /*‘a’ constantes littérales */
prixHT /* variable */

/* Expressions complexes */
2+8,
prixHT * TVA

7. Structures de contrôle
7.1. Le choix
7.1.1. if sans else

Syntaxe

if(expr)
Partie_alors

 Partie_alors : un bloc d’instructions

 Si la valeur de expr, l’expression entre parenthèses, est non nulle ce


bloc est exécutée, sinon on fait rien.

A.Zahi/DI/FSTF
49

Exemples

1. Calcul de la valeur absolue d'un nombre réel.

#include <stdio.h>
main()
{
float X, Val_X ;
printf("saisir la valeur de X :");
scanf("%f", &X) ;

Val_X = -X ;
if (X > 0)
Val_X = X ;

printf("valeur absolue de %f = %f", X, Val-X) ;


}

2. Calcul du maximum de deux entiers

#include <stdio.h>
main()
{
int x, y, Max ;
printf("saisir la valeur de x et y :") ;
scanf("%d%d", &x, &y) ;

Max = x ;
if (x < y)
Max = y ;

print("Max(%d,%d)= ", x,y,Max) ;


}

7.1.2. if avec else

Syntaxe

if(expr)
Partie_alors
else
partie_sinon

 Partie–alors et Partie-sinon sont des blocs d’instructions.

 La partie–alors est exécutée si la valeur de expr, l’expression entre


parenthèses, est non nulle. Sinon, c’est la partie-sinon qui est
exécutée.

Remarque

L’expression expr doit être toujours entre parenthèses.

A.Zahi/DI/FSTF
50

Exemples

1. Le programme suivant saisit deux entiers, x et y , et décide si x est


divisible par y .

#include <stdio.h>
main()
{
int x, y;
printf("Saisir x et y : ") ;
scanf("%d%d", &x,&y);

if (x % y == 0 )
print("%d est divisible par %d",x,y);
else
printf("%d n’est pas divisible par %d",x,y);
}

2. Une droite est définie par deux points, A = (x1 , y1 ) et B = (x 2 , y 2 ) ,


l’algorithme ci-dessous saisit les points, A , B et P = (x , y ) , et décide si le
point P appartient à la droite ( AB ) .

#include <stdio.h>
main()
{
float x, y, xa, ya, xb, yb;

printf("Saisir le point A : ") ;


scanf("%f%f", &xa, &ya);
printf("Saisir le point B : ") ;
scanf("%f%f", &xb, &yb);
printf("Saisir le point P : ") ;
scanf("%f%f", &x, &y);
if ((ya-y)*(xb-x) = (xa-x)*(yb-y) )
printf("P appartient à la droite") ;
else
printf("P n’appartient pas à la droite") ;
finsi
}

7.1.3. Imbrication des tests

Lorsqu’on a des tests imbriqués une ambiguïté se pose concernant


l’instruction if dont dépend une partie else. Deux cas se présentent :

• 1er Cas : Par défaut, un else est associé au if le plus proche. Dans
l’exemple suivant le else est associé à if(expr2).
if (expr1)

if(expr2)
inst1
else
inst2

A.Zahi/DI/FSTF
51

Exemple

Maximum de trois entiers

#include <stdio.h>
main()
{
int a,b,c,max ;

printf (" Saisir a, b et c :") ;


scanf("%d%d", &a,&b) ;

if a > b)
if (a > c)
max = a ;
else
max = c ;
else
if (b > c)
max = b
else
max = c

printf("Max = %d", Max) ;


}

• 2ème Cas : Un else doit être associé à un if plus loin. L’ambiguïté est levée
en regroupant les instructions, entre les if et else concernés, dans un bloc
d’instructions, i.e., entre accolades. Dans l’exemple suivant le else est
associé à if (expr1).

if (expr1)
{
if(expr2)
inst1

}
else
inst2

Exemple

Le programme ci-dessous permet de calculer la valeur de la fonction


définie par :

1 si x > b

f (x ) = 0 si x < a
x − a
 si a < x < b
b − a

en un point x , saisi au clavier, les valeurs de a et b sont aussi saisis.

A.Zahi/DI/FSTF
52

#include <stdio.h>
main()
{
float x, fx, a, b;

printf (" Saisir a, b et x :") ;


scanf("%f%f%f", &a,&b,&x) ;

fx = 1;
if (x > a)
{
if (x > b)
fx = (x-a)/(b-a);
}
else
fx = 0;
printf(" f(%f)= %f",x,fx);
}

Exercices

Voir chapitre 0

7.1.4. Switch

L’instruction switch est une instruction if généralisée qui permet, suivant la


valeur d’une expression, de se brancher à une étiquette de cas.

Syntaxe
switch(expr)
{
case etiq1 :
Bloc_1

case etiq2 :
Bloc_2

...

case etiqn :

Bloc_n
delfaut :
Bloc_d
}

 etiq1, etiq2,... etiqn les étiquettes de cas.

 expr est l’expression selon laquelle on effectue le choix.

 Après l’évaluation de expr, le résultat est comparé avec les étiquettes


etiq1, etiq2,..., etiqn. Si la valeur de expr coïncide avec l’une des
étiquettes, le bloc associé est exécuté. Sinon c’est la clause default qui est
exécutée.

A.Zahi/DI/FSTF
53

 Il faut noter que chaque cas se termine par l’instruction d’échappement


break qui permet de quitter l’instruction switch.

Exemple : Calculatrice des entiers

#include <stdio.h>
void main()
{
int a, b, s ;
char c;
printf(’’donner a, b’’) ;
scanf(’’%d%d’’, &a,&b) ;
scanf(’’%c ’’) ;

switch( c ) ;
{
case ‘+’ :
s= a+b ;
break ;
case ‘-’ :
s= a-b ;
break ;
case ‘*’ :
s= a*b ;
break ;
case ‘/’ :
s= a/b ;
break ;
default :
printf(’’ce n’est pas un
opérateur’’) ;
break ;
}
}

Exercices

Voir chapitre 0

7.2. Boucles
7.2.1. Boucle while

Syntaxe

while (expr)
corps-de-boucle

 La partie corps-de-boucle peut être une instruction élémentaire ou


un bloc d’instructions.

A.Zahi/DI/FSTF
54

Exemples
n
1. Calculer la somme des n premiers entiers : ∑i
i =1
#include <stdio.h>
main()
{
int i, n, S ;
printf(" Saisir n: ");
scanf("%d",&n);

S=0 ;
i=0 ;
while ( i<=n)
{
S += i;
i++;
}

printf("S=%d", S);
}

2. Un client achète plusieurs produits où chaque produit est caractérisé par la


quantité achetée qa et son prix unitaire pu . Etablir l'algorithme qui permet
de calculer et afficher le montant total à payer par un client. Le montant
d'achat d'un seul produit est défini par mp = qa * pu .

#include <stdio.h>
main()
{
char Rep;
float MT =0 ; mp, pu ;

Rep = 'O';
while ( Rep == 'O')
{
printf("saisir qa et pu") ;
scanf("%f%f", &qa,&pu) ;
Mp = qa*pu ;
MT = MT+mp ;
printf(" Un autre produit O/N") ;
scanf("%c", &Rep) ;
}
}

3. Saisir une phrase caractère par caractère. La fin de la phrase est identifiée par
le caractère ‘.’

#include <stdio.h>
main()
{
char c;
printf("Saisir un carcatère : ") ;
c=getc() ;
while(c != ‘.’)
c=getc() ;
}

A.Zahi/DI/FSTF
55

7.2.2. Boucle do while

Syntaxe

do
corps_de_boucle

while (expr) ;

 La partie corps-de-boucle peut être une instruction élémentaire ou


un bloc d’instructions.

Exemples
n
1. Calculer la somme des n premiers entiers : ∑i
i =1
#include <stdio.h>
main()
{
int i, n, S ;
printf(" Saisir n: ");
scanf("%d",&n);
S=0 ;
i=0 ;
do
{
S += i;
i++;
}
while (i<=n);

printf("S=%d", S);
}

2. Un client achète plusieurs produits où chaque produit est caractérisé par la


quantité achetée qa et son prix unitaire pu . Etablir l'algorithme qui permet
de calculer et afficher le montant total à payer par un client. Le montant
d'achat d'un seul produit est défini par mp = qa * pu .

#include <stdio.h>
main()
{
char Rep;
float MT =0 ; mp, pu ;
Rep = 'O';
do
{
printf("saisir qa et pu") ;
scanf("%f%f", &qa,&pu) ;
Mp = qa*pu ;
MT = MT+mp ;
printf(" Un autre produit O/N") ;
scanf("%c", &Rep) ;
}
while ( Rep == 'O') ;
}

A.Zahi/DI/FSTF
56

3. Saisir une phrase caractère par caractère. La fin de la phrase est identifiée par
le caractère ‘.’

#include <stdio.h>
main()
{
char c;
printf("Saisir un carcatère : ") ;

do
c=getc(stdin) ;
while(c != ‘.’);
}

7.2.3. Boucle for

Syntaxe

for (expr1 ; expr2 ; expr3)


corps-de-boucle

 La partie corps-de-boucle peut être une instruction élémentaire ou


un bloc d’instructions.

 Les expressions expr1 , expr2 et expr3 jouent respectivement les


rôles d’initialisation, de condition d’arrêt et d’incrémentation/
décrémentation.

Exemples

n
1. Calculer la somme des n premiers entiers : ∑i
i =1
#include <stdio.h>
main()
{
int i, n, S ;
printf(" Saisir n: ");
scanf("%d",&n);

S=0 ;
for (i=1; i<=n; i++)
S += i;

printf("S=%d", S);
}

A.Zahi/DI/FSTF
57

2. Calcul du maximum et du minimum dans une suite d’entiers qui se termine


par un entier négatif. La suite est saisie au clavier.

#include <stdio.h>
main()
{
int max, min, n;
printf(" Saisir n") ;
scanf("%d", &n);

for (max = min = n; n>0; )


{
if ( n < min)
min=n;
else
if (n>max)
max=n;

printf(" Saisir n") ;


scanf("%d", &n);
}
printf("Max= %d *** Min = %d", max, min) ;
}

3. Contrôle de plusieurs compteurs dans une boucle for


#include <stdio.h>
main()
{
int m, n;

for (m = 1, n = 8; n < m; m++, n--)


printf("m= %d *** n= %d ", m, n);

4. Quotient et reste de la division entière, sans utiliser les opérateurs / et %.


#include <stdio.h>
void main()
{
int n, m, q, r;
printf(" Saisir n : ");
scanf("%d", &n);

printf(" Saisir m : ");


scanf("%d", &m);

for (q =0, r=n; r>d; q++)


r -= m;

printf("Quotient = %d *** Reste = %d", q,r);


}

A.Zahi/DI/FSTF
58

7.3. Instructions d’échappement

Une instruction d’échappement permet de rompre l’exécution d’une


boucle, d’une fonction ou d’un programme.

7.3.1. Instruction break


L’instruction break permet d’arrêter l’exécution de l’instruction switch et
des boucles while, for ou do-while le schéma ci-dessous montre le
fonctionnement de l’instruction break.

main()
{
...
...
while ( )
{
...
...
break ;
...
...
}
...
}

Exemple

#include <stdio.h>
/* la boucle s’arrête à la lecture du premier 5 */
void main()
{
int a ;
for (int i=0 ; i<=10; i++)
{
scanf(’’%d’’, &a);

if(a==5)
break ;
}

if (i <10)
printf (’’Sorite prématurée’’)
}

7.3.2. Instruction continue

L’instruction continue permet d’arrêter l’itération en cours dans une


boucle, et l’exécution recommence en début de boucle. Le schéma ci-dessous
montre le fonctionnement de l’instruction continue.

A.Zahi/DI/FSTF
59

main()
{
...
...
while ( )
{
...
...
continue;
...
}
}

Exemple

#include <stdio.h>
void main()
{
int n ;
float S ;
S=0;
for (int i=0 ; i<=100; i++)
{
scanf("%d", &n);
if(n==0)
continue ;
else
S=S+1/n ;
}
}

7.3.3. Instruction return

L’instruction return permet de quitter une fonction. Quand l’instruction


est rencontrée l’exécution de la fonction est arrêtée, si return est suivie d’une
expression, la valeur de l’expression est transmise à la fonction appelante, sinon
la valeur retournée est indéterminée.

Exemple

#include <stdio.h>
float val_abs (float x)
{
if (x >=0) return x;
else return -x;
}
int main()
{
float y ,v ;
scanf(’’%f’’, &y);
v=val_abs(y);
printf(’’%f’’, v);
return;
}

A.Zahi/DI/FSTF
60

7.3.4. Instruction exit

L’instruction exit permet d’interrompre l’exécution d’un programme. Cette


fonction possède un argument de type entier qui permet d’indiquer le code de
terminaison du programme.

Exemple
#include <stdio.h>

main()
{
int n ;
int c ;
scanf(’’%d’’, &n);
c=n*n;
printf(’’%d’’, c);
exit(1);
}

8. Les Pointeurs
8.1. Mémoire de l’ordinateur

La mémoire d’un ordinateur est constituée de plusieurs cases mémoires


rangées de façon séquentielle et dont la taille dépend des performances de la
machine. Chaque case est identifiée par une adresse unique comprise entre 0 et
une valeur maximale qui détermine la capacité de la mémoire installée dan la
machine. Lors du fonctionnement de l’ordinateur une partie de la mémoire est
occupée par le système d’exploitation (DOS, Windows 95/98/2000/NT, Unix,
etc.), le reste est utilisé par les applications pour stocker les variables et les
instructions et effectuer les appels de fonctions. Quatre zones mémoires sont
réservées pour chaque programme :

• La zone de code : contient les instructions des fonctions.

• La zone de données : contient les variables globales et les variables de la


fonction main(). Lorsqu’un programme déclare une variable le
compilateur lui réserve automatiquement un emplacement mémoire dans
cette zone et associe une adresse à son nom. L’allocation et l’initialisation
des variables se font avant le lancement de la fonction main().

• La pile : utilisée lors de l’appel des fonctions, les variables locales et les
paramètres de la fonction appelée sont logés dans cette zone. La mémoire
locale est allouée au moment de l’appel et libérée à la fin de l’exécution.
• Le tas (Heap) cette zone, appelée aussi mémoire dynamique, contient
les données dont la taille augmente ou diminue au cours de l’exécution
d’un programme.

A.Zahi/DI/FSTF
61

Mémoire centrale

• Applications:traitement
de texte Word, Tex...), Segment de données
• Tableurs (Excell,...)

• Dessins( Autocad, Segment de code


Paint,...)

• Compilateurs (C, C++,


Segment de Pile
visual Basic...)
• Programmes Utilisateurs
Segment heap

Systèmes
d’exploitation
• Linux, DOS, Windows...

8.2. Notion de pointeur

Un pointeur est une variable numérique qui contient l’adresse d’un


emplacement mémoire, on dit que le pointeur pointe sur un emplacement
mémoire. C’est une association indirecte avec le contenu de l’espace pointé.

Valeur de X Variable X

Pointeur vers X
Adresse de X

Deux pointeurs utiles :

• Pointeur NULL : permet de représenter un pointeur invalide i.e., un


pointeur qui ne pointe sur aucun espace mémoire. La valeur NULL est
déclarée dans le fichier en-tête <stddef.h> .

• Pointeur générique void* : permet de pointer sur n’importe quel type


d’objet. Il est surtout utilisé dans les fonctions qui retournent un pointeur
sur un objet dont l’espace est alloué dynamiquement.

A.Zahi/DI/FSTF
62

8.3. Déclaration

Syntaxe

nom_Type *nom_pointeur ;

 Nom_Type , représente le type de base de la variable pointée.

 Nom_pointeur, est le nom de la variable pointeur. Le choix du nom


suit les mêmes règles que pour le choix d’une variable simple.

 L’opérateur * indique que nom_pointeur est de type pointeur.

Exemple

void main()
{
int *ptr_entier ; /* pointeur sur un entier*/
long int *ptr_long; /*pointeur sur un entier long*/
double *ptr_double; /* pointeur sur un réel double*/
char *ptr_carac ; /* pointeur sur un caractère*/
}

Remarque

La déclaration d’une variable de type pointeur consiste à lui réserver un


espace en mémoire dans le segment heap (mémoire dynamique) .

8.4. Initialisation

Comme pour les variables simples, un pointeur non initialisé peut provoquer
des problèmes d’exécution. En effet, quand on déclare un pointeur, ce dernier est
initialisé par une valeur quelconque (i.e., une adresse quelconque). Pour cela, un
pointeur doit être initialisé avant toute utilisation, c’est le programmeur qui
doit s’en charger. Il existe deux façons d’initialiser un pointeur : par une adresse
existante, en utilisant l’opérateur d’adressage, ou en lui attribuant une nouvelle
adresse.

8.4.1. initialisation à l’aide de l’opérateur d’adressage &

Un pointeur peut être initialisé par l’adresse d’une variable qui existe déjà.
L’initialisation a la forme suivante :

Syntaxe
type X ;
type* ptr_X ;
ptr_X= &X ; /* affectation de l’adresse de X à ptr_X */

 L’opérateur & renvoie l’adresse de la variable en paramètre.

A.Zahi/DI/FSTF
63

Exemple
void main()
{
int X = 25; /* X contient la valeur 25 */
int *ptr_X ;
ptr_X = &X ; /* ptr_X contient l’adresse de X */
}

8.4.2. Initialisation à l’aide de la fonction malloc ()

Un pointeur peut être initialisé par l’adresse d’une case mémoire réservée au
cours de l’exécution du programme. Pour ce faire nous avons besoin des
fonctions malloc() et sizeof() qui sont situées dans la bibliothèque <stdlib.h> ou
dans <alloc.h>.

Syntaxe

/* initialisation d’un pointeur*/


nom_type *ptr_X ;
int t= sizeof(nom_type) ;
ptr_X= (nom_type* ) malloc(t) ;

 sizeof est un opérateur qui retourner la taille d’un type i.e., la taille
de l’espace mémoire nécessaire pour loger une variable de ce type.

 malloc est une fonction qui permet de réserver un espace mémoire de


taille t et de retourner son adresse.

 L’initialisation d’un pointeur dans ce cas consiste, à convertir


l’adresse retournée par la fonction malloc au type désiré ensuite
l’affecter à ptr_X.

Exemple

int *ptr_X ;
/* allocation mémoire pour une variable entière X */
ptr_X = (int *) malloc (siezof(int)) ;

double *ptr_d ;
/* allocation mémoire pour une variable réelle */
ptr_d = (double* ) malloc (siezof(double)) ;

8.5. Indirection

Après la déclaration et l’initialisation d’un pointeur, nous avons besoin de


manipuler la variable pointée. Pour accéder à cette variable on utilise l’opérateur
* suivant la syntaxe suivante :

A.Zahi/DI/FSTF
64

Syntaxe

nomtype X ;
nomtype *ptr_X ;
ptr_X =( nomtype *) malloc(sizeof(nomtype)) ;
X=*ptr_X ;

 L’opérateur * délivre la valeur pointée par ptr_X .

 *ptr_X représente une variable de type nomtype sur laquelle on


peut effectuer toutes les opérations permises sur le type nomtype,
Lecture, affichage, opérateurs, etc.

Exemple 1

#include<stdio.h>
void main( )
{
int i = 0;
int *p;
float x = 3.14;
float *f;
f= (float* ) malloc(sizeof(float));
scanf(“%f”, f);
p = &i;
*f = 666;
f = &x;
printf(“%f”,*f);
*f = *p;
*p = 34;
*p = *p + 1;
printf( "%d %f %d\n", i, *f, *p );
}

Remarques

• Si ptr_X est un pointeur sur une variable X, alors *ptr_X et X


contiennent le même contenu.

• L’initilisation d’un pointeur au moment de la déclaration permet


d’initialiser la valeur du pointeur et non le contenu de l’espace pointé.
 int* p = &x ; /* Juste*/

 int* p = 10 ; * Faux*/

8.6. Libération de l’espace

La fonction free permet de libérer un espace mémoire qui a été alloué par
la fonction malloc, cette fonction est appelée une fois qu’on a plus besoin de cet
espace.

Syntaxe
free(p);

A.Zahi/DI/FSTF
65

9. Les fonctions
9.1. Analyse descendante

En utilisant les éléments de programmation présentés précédemment


(opérateurs, instructions de choix, boucles, etc.), il est facile de résoudre tous les
problèmes relativement simples. Cependant pour les problèmes complexes et de
grandes tailles, il faudrait utiliser une méthodologie pour construire la solution
correspondante. L’analyse descendante est l’une des méthodes les plus utilisée
pour le développement d’une solution informatique pour les problèmes
complexes. L’analyse descendante est basée sur la technique ‘diviser pour
régner’ qui consiste à :

• Décomposer le problème en sous problèmes indépendants, à décomposer


eux-mêmes en sous problèmes et ainsi de suite jusqu’ à ce qu’on arrive à
des problèmes triviaux.

• Résoudre les sous problèmes triviaux séparément, pour chaque sous


problème on conçoit un sous programme qu’on appelle fonction.

• Combiner les sous programmes (fonctions) obtenus pour construire la


solution globale du problème.

P1 P2 P3

P11 P12 P31 P32 P33

P321 P322

Figure 11 : Décomposition d’un problème

Une fonction, est un ensemble d’instructions réalisant une tâche bien précise,
elle peut être considérée comme une boîte noire qui reçoit en entrée des données
et fournit des résultas en sortie.

Données Fonction Résultats

Figure 12 : Schéma d’une fonction

A.Zahi/DI/FSTF
66

1 i =n i
Exemple : Calcul de f n (x ) = ∑ x
n! i =1
• Ce problème peut être décomposé en trois sous problèmes :

Ž P1 : calculer n! , pour n donné.


Ž P2 : calculer x n , pour n et x donnés.
Ž P3 : calculer la somme.des puissances croissantes de x

• Fact(n), Puiss(x,n) et Som(x,n) sont les fonctions (sous


programmes) qui permettent de résoudre respectivement les sous
problèmes P1, P2 et P3.

• La solution globale du problème se présente comme suit :

(1/Fact(n))*Som(x,n)

La fonction Puiss est utilisée dans la foncfion Som(x,n).

9.2. Pseudo-fonction

Une pseudo-fonction, appelée macro avec paramètres, permet de représenter


une expression simple, elle est définie par la directive #define

Syntaxe

#define IDENF (paramètres) (expression)

 IDENF Identificateur qui représente le nom de la macro.

 expression: chaîne de caractères qui représente l’expression de la macro,


lorsque le préprocesseur rencontre la chaîne IDENF, il remplace le texte
de la macro par expression.

 Dans l’expression chaque paramètre doit être entre parenthèses.

Exemple

#include <stdio.h>
#define CARRE(x) ((x)*(x))
#define MAX(x,y) ((x) >(y) ? (x):(y))
void main()
{
int n,m, M, C ;
printf("donner n et m: ");
scanf("%d%d", &n, &m);

M = MAX(m,n) ;
printf("Le max est : %d", M);

C = CARRE(n)
printf(" le carré de %d est : %d", n, C) ;
}

A.Zahi/DI/FSTF
67

Remarque

Les parenthèses entourant les arguments sont nécessaires pour éviter les
effets de bord, En effet si on définie la macro : #define carre (x) x*x,
l’instruction r=carre (x+y) ; sera remplacée par l’expression x+y*x+y ;

9.3. Déclaration des fonctions utilisateur

La déclaration d’une fonction en C est constituée par deux parties :

• La partie interface, appelée aussi prototype, spécifie l’apparence de la


fonction : le nom, les données et les résultats fournies par la fonction.

• La partie corps spécifie le comportement de la fonction i.e., les


instructions à exécuter sur les données pour obtenir les résultats.

9.3.1. Prototype d’une fonction

L’interface est constituée par trois éléments chacun joue un rôle particulier.

Syntaxe
type_retour nom_fonction(liste des paramètres)

 type_retour indique le type de la valeur que la fonction doit retourner.


Ce type peut être l’un des types simples ( int, float, double, char,...).
Dans le cas où la fonction ne retourne aucune valeur on doit spécifier
void comme type de retour.

 nom_fonction indique le nom de la fonction, celui-ci doit suivre les


mêmes règles que les noms des variables simples. Il est préférable de
choisir, pour les fonctions, des noms qui indiquent ce qu’elles font.

 Liste des paramètres, appelée aussi paramètres formels, ce sont les


objets (données et résultats) sur lesquelles s’exécute la fonction. Pour
chacun des paramètres on doit préciser le type, l’identificateur et la
nature : fixe ou variable.

Ž Un paramètres fixe est un objet sur lequel il n’y a aucun effet


par la fonction, la valeur en entrée est la même qu’en sortie. Ce
type concerne les données de la fonction. On le déclare de la
manière suivante :

type_retour nom_fonction(type1 id, ..., ...)

Ž Un paramètre variable est un objet qui peut être modifié par la


fonction, la valeur en entrée n’est pas toujours la même que
celle de en sortie. Ce type de paramètre concerne les résultats de
la fonction. On le déclare de la manière suivante :

type_retour nom_fonction(type1 *id,..,...)

A.Zahi/DI/FSTF
68

Exemples

/*a et b : paramètres fixes. */


int somme (int a, int b) ;

/*a et b : paramètres fixes, s : paramètre variable*/.


void somme(int a, int b, int *s) ;

/*fonction sans paramètres */


void affiche () ;

/*a et b : paramètres variables.*/


void echange (int *a, int* b) ;

9.3.2. Corps de la fonction

Le corps de la fonction est placé entre accolades à la suite de l’en-tête.

Syntaxe

{
déclarations des variables locales
instructions
return expression ;
}
 Variables locales ce sont des variables déclarées dans la fonction et
qui ne sont pas visibles à l’extérieure.

 Instructions représentent les opérations qui permettent d’effectuer la


tâche de la fonction. Quand la fonction est appelée, l’exécution
commence à la première instruction qui suit l’accolade ouvrante et se
termine à la rencontre de la première instruction return ou de
l’accolade fermante.

 return permet de renvoyer la valeur d’une expression à la fonction


appelante. Lorsque cette instruction est rencontrée l’expression est
évaluée et la valeur trouvée est transmise à la fonction appelante.

Exemples

1. fonction main

void main ()
{
printf(’’bonjour Bonjour’’) ;
}

2. Maximum de deux entiers : sans type de retour


void Maximum (int a, int b, int* Max)
{
*Max = a ;
if (a>=b)
*Max = b ;
}

A.Zahi/DI/FSTF
69

3. Somme de deux entiers : avec type de retour, avec paramètre


int somme(int a, int b)
{
int s ; /* variable locale */
s= a+b ;
return s ;
}

4. Valeur absolue

float Val_Abs(float a)
{
float abs ;
if (a>=0)
abs = a ;
else
abs = -a
return abs ;
}

9.3.3. Comment obtenir une fonction

Pour l’écriture d’une fonction on doit répondre aux questions suivantes :

• Quel la valeur que la fonction doit retourner ? Cette valeur définie le


type de retour de la fonction.

• Quels sont les données dont la fonction a besoin pour effectuer sa tâche ?
Les données constitueront les paramètres fixes de la fonction.

• Quels sont les résultats que la fonction doit fournir ?. Les résultats
constitueront les paramètres variables de la fonction.

• Quelles sont les instructions qui permettent d’obtenir les résultats à partir
des données ? Les instructions constitueront le corps de la fonction.

9.4. Appel d’une fonction


9.4.1. Principe

Une fois déclarée, une fonction peut être utilisée dans plusieurs parties du
programme, on parle ainsi de l’appel de fonction. Au moment de l’appel, la
fonction appelante transmet à la fonction appelée les paramètres effectifs
(valeurs des paramètres formels); ensuite le corps de la fonction appelée est
exécutée, après, la fonction appelante reprend l’exécution à la ligne qui suit la
ligne d’appel et récupère éventuellement un résultat.

A.Zahi/DI/FSTF
70

Fonction
appelante Fonction
appelée

Paramètres
effectifs
Suspension de
l’exécution Exécution de
la fonction

Valeur de
Reprise de retour
l’exécution

Retour vers
l’appelant
Figure 13 : Processus de l’appel d’une fonction

9.4.2. Syntaxe de l’appel

L’appel d’une fonction constitue un paramètre dans une instruction :

• Affectation à une variable :

variable = nom_fonction (paramètres effectifs)

• Paramètre effectif d’une autre fonction

fonc(nom_fonction (paramètres effectifs))

• Un facteur dans une expression :

Var1 = nom_fonction (paramètres effectifs)* var2


Exemples

1. Valeur absolue
#include <stdio.h>
float absolue( float a)
{
float abs ;
abs = a ;
if( a <0)
abs =-a
return abs ;
}
void main()
{
float x, y, Max ;
printf(" Entrer la valeur de x : ") ;
scanf("%f ", &x) ;
/* appel de la fonction absolue*/
printf("%f", absolue(x)) ;
}

A.Zahi/DI/FSTF
71

2. Maximum de deux entiers


#include <stdio.h>
Maximum ( int a,int b ,int * max )
{
*Max=a ;
if (a>=b)
*Max = b
}
void main()
{
float x, y, max ;
printf(" Entrer la valeur de x : ") ;
scanf(" %d", &x) ;
printf(" Entrer la valeur de y : ")
scanf(" %d", &y) ;
/* appel de la fonction max */
Maximum(x,y, &max)
printf (" %d", max)
}

Remarques

• Différence entre paramètres formels et paramètres effectifs :


Ž Les paramètres formels sont spécifiés lors de la déclaration de la
fonction

Ž Les paramètres effectifs sont spécifiés au moment de l’appel.

• Lors de l’appel d’une fonction on doit respecter les contraintes suivantes :


Ž Le nombre de paramètres effectifs doit être le même que celui des
paramètres formels.

Ž L’ordre des paramètres effectifs doit être le même que celui des
paramètres formels.

Ž Les paramètres effectifs et les paramètres formels doivent être de


même type.

9.4.3. Passage des paramètres

Lors de l’appel d’une fonction, la fonction appelante transmet les paramètres


à la fonction appelée, deux modes de transmission sont possibles :

• Passage par valeur : la fonction appelante ne transmet qu’une copie du


paramètre effectif, par suite la fonction n’a aucun effet sur le paramètre en
question. Ce sont les paramètres fixes qui sont concernés par ce mode de
transmission.

• Passage par adresse: la fonction appelante transmet l’emplacement


mémoire du paramètre effectif, par suite la fonction peut avoir un effet sur
le paramètre en question. Ce sont les paramètres variables qui sont
concernés par ce mode de transmission.

A.Zahi/DI/FSTF
72

En langage C la méthode utilisée pour le passage des paramètres est le


passage par valeur. Le passage par adresse est réalisé explicitement par le
programmeur en passant l’adresse du paramètre au lieu de sa valeur. Le passage
des paramètres se réalise selon les étapes suivantes:

• Copier les valeurs des paramètres dans la pile.

• Allouer l’espace mémoire, dans la pile, pour les paramètres et les


variables locales de la fonction appelée.

• Exécuter le corps de la fonction et stocker les résultats de la fonction dans


la pile.

• Récupérer les valeurs sur la pile

Exemple1 : Exécution d’une fonction avec un paramètre fixe.

int x=20, y ;
y = f2(x) ;

Mémoire
centrale

int f2(int x)
{
x = 20 x= x+x ;
y=40 1. Copier x return x ;
sur la pile }
2. Exécuter
la fonction

3. Stocker le résultat
4. Récupérer le résultat
sur la pile
de la pile

x = 20
x= 40

Pile

Figure 14 : Passage par valeur

A.Zahi/DI/FSTF
73

Exemple 2 : Exécution d’une fonction avec un paramètre variable.

int x=20, y ;
f2(&x) ;

Mémoire
centrale

void f2(int * x)
{
x = 20 *x= *x + *x ;
x = 40 1. Copier &x }
sur la pile
2. Exécuter
la fonction

3. lire la valeur du
paramètre à partir de
la M. C. (&x)
&x
4. Stocker le résultat
dans la M.C. &x
Pile

Figure 15 : Passage par adresse

9.4.4. Porté des variables

On distingue deux catégories de variables :

• Variables locales : ce sont des variables déclarés à l’intérieur d’une


fonction. Ces variables ne sont pas accessibles à partir des autres
fonctions.

• Variables globales : ce sont des variables qui ne sont déclarées dans


aucune fonction. Les variables déclarées dans la fonction main sont aussi
des variables locales. Les variables globales sont visibles partout dans le
programme i.e., dans toutes les fonctions.

A.Zahi/DI/FSTF
74

Exemple

#include <stdio.h>

int m;/* variable globale */

void init0()
{
m = 0;
printf("\n %d",m);
}

void init1(int t)
{
int k =15 ; /* variable local */

t = k+ 1;
printf("\n %d",t);
}

void init2(int *p)


{
*p = 2;
printf("\n %d",*p);
}
void main()
{
int n; /* variable locale*/

init0();
printf("\n %d",m);

n = m;
init1(n);
printf("\n %d",n);

init2(&n);
printf("\n %d",n);

init2(&m);
printf("\n %d",m);

init1(m);
printf("\n %d",m);
}

le résultat de ce programme est : 0 0 16 0 2 2 2 2 16 2

Exercices
1. Ecrire une fonction qui retourne l’image d’un réel par la fonction définie
par le graphe suivant :

a b c d

A.Zahi/DI/FSTF
75

i =n
xi
2. Ecrire un programme qui calcul la valeur ∑ i! , Ecrire les fonctions
i =1
nécessaires.

3. Ecrire un programme qui saisit un entier p et détermine s’il est parfait,


premier, triangulaire ou premier avec un entier saisi. Le programme doit
permettre à l’utilisateur de choisir l’opération désirée.

A.Zahi/DI/FSTF
76

Chapitre 2: Tableaux et Chaînes de


caractères

1. Tableaux uni dimensionnels

Un tableau uni dimensionnel est une structure qui abrite un ensemble fini
d’éléments de même type. Un tableau occupe une place contiguë dans la
mémoire i.e., les éléments sont stockés les un à la suite des autres.

21 1er élément
12 2 ème élément
3
Tableau

.
.
.

dernier élément
20

Figure 16 : Stockage d’un tableau en mémoire

1.1. Déclaration

Syntaxe

type_element nom_tableau[CAP];

 nom_tableau est un identificateur qui indique le nom de la variable,

 type_element indique le type des éléments du tableau,

 CAP est une constante qui indique le nombre maximal d’éléments


qu’on peut stocker dans ce tableau.

A.Zahi/DI/FSTF
77

Remarque

• Il est recommandé de définir la constante qui indique la capacité du


tableau comme une constante symbolique :

#define CAP 10
int t[CAP];

• Les tableaux en C sont indexés de 0 à CAP-1.

• La taille d’un tableau doit être connue au moment de la déclaration, on ne


peut donc pas faire les déclarations suivantes:

int t[ ];
int t[n]; avec n.une variable.

• Il est impératif de déclarer un tableau avec une capacité maximale CAP,


cependant il n’est pas obligatoire d’utiliser tous les CAP éléments. Pour
indiquer la taille effective du tableau i.e., le nombre d’éléments
effectivement utilisés, on accompagne la déclaration du tableau par la
déclaration d’un entier N qui joue ce rôle.

Ainsi la déclaration d’un tableau devient :

#define CAP 10 /* Capacité du tableau */

int N ; /* Taille du tableau */


int t[CAP];

Exemples

#define CAP1 15
#define CAP2 20
#define CAP3 30
void main()
{
/* tableau qui peut contenir 15 entiers */
int t[CAP1] ;

/* tableau qui peut contenir 20 réels*/


double r[CAP2] ;

/*tableau qui peut contenir 30 caractères*/


char nom[CAP3] ;
}

1.2 Initialisation d’un tableau

Il est possible d’initialiser l’intégralité ou seulement une partie d’un tableau,


par une liste de constantes au moment de la déclaration. L’initialisation permet
d’affecter aux éléments, respectivement et à partir de 0, les constantes entre
accolades. Dans le cas où la taille n’est pas indiquée le compilateur crée un
tableau avec autant d’éléments que de valeurs entre accolades.

A.Zahi/DI/FSTF
78

Exemple

#define CAP 5

/* initialisation de l’intégralité du tableau*/


int t[CAP] = {1,2,3,4,8};

/* initialisation d’une partie du tableau*/


int k[CAP] = {1,2};

/* initialisation sans indiquer la taille */


int l[] = {4,7,9,76};

1.3. Accès à un élément du tableau

Chaque élément du tableau est identifié par son rang. Pour y accéder on
utilise l’opérateur d’indexation [.] avec le rang de l’élément comme paramètre.

Syntaxe

nom_tableau [exp] ;

 exp est une expression délivrant une valeur entière qui indique le rang de
l’élément dans le tableau.

 Si T est un tableau, T[i] représente son (i+1)eme élément, Ainsi T[i] peut
être considéré comme une variable simple sur laquelle on peut effectuer
les opérations suivantes :

Ž Saisie : scanf("%car", &T[i] ) ; où car est un spécificateur


de format de l’un des types de base.

Ž Affichage : printf("%car", T[i] ); où car est un


spécificateur de l’un des types de base.

Ž Affectation :

/*valeur d’une constante*/


T[i]= Constante;

/*valeur d’une expression*/


T[i]= expression;

/*valeur d’une autre variable*/


T[i]= X ;

Ž Elément d’une expression :

S=2*PI*T[i] ;

if( T[i] >=0)


T[i]= sqrt(T[i]) ;

A.Zahi/DI/FSTF
79

Exemple

Ce programme permet de saisir un tableau d’entiers, de remplacer chaque


élément par la somme de ses diviseurs et d’afficher le tableau résultant.

#include <stdio.h>
#define CAP 10
void main()
{
int T[CAP], n, s, d ;
/* Saisie du tableau */
printf (’’entrer la taille du tableau :’’) ;
scanf(’’%d’’, &n) ;

for (int i=0 ;i<n ; i++)


{
printf(’’Donner T[%d] : ’’,i) ;
scanf(’’%d’’, &T[i]) ;
}
/* Recherche des diviseurs */
for (int i=0 ;i<n ; i++)
{
s=1 ;
d=2 ;
while (d<=T[i])
{
if(T[i]%d==0)
s += d ;
d++;
}
T[i]=s ;
}
/* Affichage du tableau */
for (int i=0 ;i<n ; i++)
printf (’’T[%d] = %d ’’, i, T[i]) ;
}

1.4. Pointeurs et Tableaux


1.4.1. Le nom d’un tableau

La déclaration type_tab T[CAP] consiste à réserver l’espace mémoire pour


CAP éléments de type type_tab. Lors de l’utilisation de l’identificateur T,
chaque occurrence de T sera convertie en une valeur constante dont :

• Le type est un ’’ pointeur vers le type type_tab ’’,

• La valeur est l’adresse du premier élément du tableau.

Remarques

• La conversion n’a lieu que pour les identificateurs des tableaux qui
apparaissent dans une expression et non lors de la déclaration.

• Le nom d’un tableau est un pointeur constant. i.e., On ne peut pas


modifier sa valeur au cours de l’exécution du programme. Ainsi on ne

A.Zahi/DI/FSTF
80

peut rien lui affecter, néo moins on peut créer un pointeur variable qui
pointe vers le premier élément.

int tab[10] ;
int * ptr_tab ;
ptr_tab=tab ;
tab= ptr_tab

1.4.2. Incrémentation et décrémentation

Les éléments d’un tableau sont stockés en mémoire les un à la suite des
autres et le nom du tableau contient l’adresse du premier élément. Pour accéder à
un élément du tableau on doit donc se positionner à son adresse. Pour cela le
nom du tableau doit être incrémenté ou décrémenté, i.e., augmentée ou diminuée
par la taille du type des éléments du tableau, jusqu’à atteindre l’élément cherché.

Exemple

Ce programme permet de saisir un tableau d’entiers, de remplacer chaque


élément par la somme de ses diviseurs et d’afficher le tableau résultant.

#include <stdio.h>
#define CAP 10
void main()
{
int T[CAP], n, s, d ; *p ;
/* Saisie du tableau */
printf (’’entrer la taille du tableau :’’) ;
scanf(’’%d’’, &n) ;
p=T;
for (int i=0 ;i<n ; i++)
{
printf("Donner T[%d] : ",i) ;
scanf("%d", p]) ;
p++ ;
}
/* Recherche des diviseurs */
p=T;
for (int i=0 ;i<n ; i++)
{
s=1 ; d=2 ;
while (d<=*p)
{
if(*p % d==0)
s += d ;
d++;
}
*p=s ;
}
/* Affichage du tableau */
p=T ;
for (int i=0 ;i<n ; i++)
{
printf (’’T[%d] = %d ’’, i, *p) ;
p++;
}
}

A.Zahi/DI/FSTF
81

1.4.3. Indexation du tableau

Comme on a déjà vu, le nom d’un tableau est un pointeur vers le premier
élément. Par suite pour accéder à sa valeur on doit utiliser l’opérateur *. Ainsi, si
t est un tableau alors *t représente le premier élément de t et pour accéder au ieme
élément du tableau on doit incrémenter le non du tableau de i i.e., utiliser
l’expression *(t+i). Ainsi l’expression t[i] est équivalente à *(t+i).

Exemple
Ce programme permet de saisir un tableau d’entiers, de remplacer chaque
élément par la somme de ses diviseurs et d’afficher le tableau résultant.

#include <stdio.h>
#define CAP 10
void main()
{
int t[CAP], n, S, d ;
/* Saisie du tableau */
printf (’’entrer la taille du tableau :’’) ;
scanf(’’%d’’, &n) ;
for (int i=0 ;i<n ; i++)
{
printf(’’Donner t[%d] : ’’,i) ;
scanf(’’%d’’, t+i) ;
}
/* Recherche des diviseurs */
for (int i=0 ;i<n ; i++)
{
s=1 ;
d=2 ;
while (d<=*(t+i))
{
if(*(t+i)%d==0)
s += d ;
d++;
}
*(t+i)=s ;
}
/* Affichage du tableau */
for (int i=0 ;i<n ; i++)
printf (’’t[%d] = %d\t ’’, i, *(t+i)) ;
}

1.4.4. Tableaux dynamiques

Avec la déclaration, type tab[MAX], l’espace nécessaire au stockage est


alloué au début de l’exécution du programme. Pour créer un tableau dont la
taille est déterminée au moment de l’exécution on doit déclarer le tableau avec
un pointeur variable.

Syntaxe
/* déclaration d’un tableau dynamique */
nomtype *tab ;

/* allocation de l’espace à ce tableau */


tab = (nomtype*) malloc(t * sizeof(nomtype)) ;

A.Zahi/DI/FSTF
82

 L’espace réservé aux tableaux dynamiques est alloué au cours de


l’exécution du programme en utilisant la fonction malloc.

 L’allocation de l’espace mémoire au tableau tab de talle t consiste à


réserver t cases mémoire de taille sizeof(nomtype).

Exemple
int *t ;
double *d ;
char *c ;
/* allocation de l’espace à un tableau de 10 entiers */
t = (int ) malloc(10 * sizeof(int));

/* allocation de l’espace à un tableau de 40 réels */


d = (int ) malloc(40 * sizeof(double));

/* allocation de l’espace à un tableau de 20 caractères */


c = (char ) malloc(20 * sizeof(double));

1.5. Tableau paramètre d’une fonction

Un tableau uni-dimensionnel est définie par l’adresse du premier élément et


la taille effectif. Ainsi, le passage d’un tableau comme paramètre à une fonction
consiste à lui passer ces deux informations, la syntaxe est la suivante :

Syntaxe

Déclaration de la fonction
• La taille n’est pas modifiée par la fonction

type nom_fonc1 ( type tab[CAP], int taille) ;


type nom_fonc2 ( type tab[], int taille) ;
type nom_fonc2 ( type *tab, int taille) ;

• La taille est modifiée par la fonction

type nom_fonc1 ( type tab[CAP], int *taille) ;


type nom_fonc2 ( type tab[], int *taille) ;
type nom_fonc2 ( type *tab, int *taille) ;

Appel de la fonction
type tab[10] ;
int n ; /* taille du tableau */

nom_fonc1(t,n) ;
nom_fonc2(t,&n) ;
Remarques

• La fonction n’a pas besoin de la taille maximale du tableau car on ne


réserve de l’espace sur la pile qu’à l’adresse du premier élément et à la
taille effective. L’accès à un élément du tableau est effectué par son
adresse, calculée à partir de celle du premier élément. Le dernier élément
du tableau est identifié par la taille effective.

A.Zahi/DI/FSTF
83

• La fonction peut avoir un effet sur tous les éléments du tableau, mais pas
sur la valeur du paramètre qui est de type pointeur i.e., l’adresse du
premier élément ne change pas par la fonction. Par exemple, Après l’appel
de la fonction :

void remplir(int *t, int n)


{
int *p = t + n ;
while ( t != p)
{
*t =*t + 2 ;
t++ ;
}
}

les éléments du tableau sont modifiés mais pas la valeur du pointeur t.


Exemple

#include <stdio.h>
#define CAP 10
/*********************************************************/
/* FONCTION SAISIE */
/*********************************************************/
void Saisie (int t[], int n)
{
int i;
for (i=0 ;i<n ; i++)
{
printf(’’Donner t[%d] : ’’,i) ;
scanf(’’%d’’, t+i) ;
}
}
/*********************************************************/
/* FONCTION AFFICHAGE */
/*********************************************************/
void Affichage (int *t, int n)
{
int i;
for (int i=0 ;i<n ; i++)
printf (’’t[%d] = %d\t ’’, i, *(t+i)) ;
}
/*********************************************************/
/* FONCTION DIVISEUR */
/*********************************************************/
void Diviseur (int t[CAP], int n)
{
int i, s, d;
for (int i=0 ;i<n ; i++)
{
s=1 ;
d=2 ;
while (d<=*(t+i))
{
if(*(t+i)%d==0)
s=s+d ;
d++;
}
*(t+i)=s ;
}
}

A.Zahi/DI/FSTF
84

/*********************************************************/
void main()
{
int t[CAP], n;

/* Saisie du tableau */
printf (’’entrer la taille du tableau :’’) ;
scanf(’’%d’’, &n) ;
Saisie(t,n) ;
/* Recherche des diviseurs */
Diviseur (t,n) ;
/* Affichage du tableau */
Affichage (t,n) ;
}

2. Tableaux de dimension deux

Un tableau de dimension deux est un tableau uni-dimensionnel de dimension


L dont chaque élément est un tableau uni-dimensionnel de dimension C. L et C
sont les deux dimensions du tableau bidimentionnel, elles représentent
respectivement le nombre de lignes et le nombre de colonnes. On peut ainsi dire
qu’un tableau de dimension deux est une matrice de dimension L et C.

En mémoire, un tableau de dimension deux occupe un espace contiguë, les


éléments sont stockés ligne par ligne.

21
… 1er ère ligne
3
14
…. 2 ème ligne
Tableau

.25
.

12
… dernière ligne
20

Figure 17 : Stockage d’un tableau de dimension 2

A.Zahi/DI/FSTF
85

Exemple

Pour stocker les notes des 12 modules, d’une section de la fst, on utilise un
tableau de dimension n et 12, où n est le nombre d’étudiants dans la section. Une
ligne du tableau représente les notes d’un étudiant dans les 12 modules. Une
colonne représente les notes de tous les étudiants dans un module.

M1 M2 . . . M12
E1 12 09 . . . 16
E2 05 14 . . . 12
.
.
.
En 13.5 15 . . . 16

2.1. Déclaration

Syntaxe

type_element nom_tableau[MAX_LIN] [MAX_COL];

 nom_tableau est un identificateur qui indique le nom de la variable.

 type_element indique le type des éléments du tableau.

 MAX_LIN et MAX_COL sont des constantes qui indiquent,


respectivement, le nombre maximal d’éléments qu’on peut stocker
dans une ligne respectivement dans une colonne.

Exemple
/* matrice d’entiers de 7 lignes et 6 colonnes */
int matrice[7][6] ;

/*texte de 10 lignes, chacune est formée par 80 caractères */


char texte[10][80] ;

/*tableau qui contient les notes d’une section */


#define MEX_ETUD /* nombre maximale d’étudiants */
float notes [MAX_ETUD][12] ;

2.2. Initialisation

Les tableaux de dimension deux peuvent être initialisés au moment de la


déclaration par une liste d’expressions:

Exemple

int T[4][5]={ {0, 1, 2, 3, 4},


{10, 11, 12, 13, 14},
{20, 21, 22, 23, 24},
{30,31,32,33,34}}

A.Zahi/DI/FSTF
86

2.3. Accès à un élément

Chaque élément du tableau est identifié par deux indices qui indiquent sa
ligne et sa colonne, pour accéder à un élément on utilise l’opérateur d’indexation
avec la ligne et la colonne comme paramètres.

Syntaxe

nom_tableau [exp1][exp2] ;

 exp1, exp2 sont des expressions délivrant des valeurs entières qui
indiquent respectivement la ligne et la colonne dans le tableau.

 Si T est un tableau de dimension 2, T[i][j] désigne l’élément de la


ligne i et la colonne j, il est considéré comme une variable simple qui
peut être utilisée dans une expression ou sur laquelle on peut effectuer
les opérations de saisie, d’affichage et d’affectation .

Exemple

Ce programme permet de saisir le tableau des notes des 12 modules d’une


section, de calculer la moyenne de chaque étudiant, de stocker le résultat dans la
13ème colonne et d’afficher la moyenne de chaque étudiant.

#define M_LIN 100


#define M_COL 15
void main()
{
float notes[M_LIN][M_COL], moy ;
int i, j, ne, nm;

/* Saisie des notes */

printf("donner le nombre d’étudiants ");


scanf("%d",&ne);

for(i= 0; i<ne; i++)


for(j=0; j<12; j++)
scanf("%d", &notes[i][j];

/* Calcul de la moyenne générale */


for (i=0 ; i<ne ;i++)
{
moy =0.0 ;
for j=0 ; j<12 ; j++)
moy += notes[i][j];

notes[i][13]=moy;
}
/* Affichage de la moyenne de chaque étudiant */

for(i= 0; i<ne; i++)


printf(’’%d’’, notes[i][13];
}

A.Zahi/DI/FSTF
87

Exercice

Chaque semaine la direction d’un magasin d’appareils électroménagers


enregistre ses ventes, en nombre d’appareils, dans un tableau de vente. A la fin
du mois les résultats sont envoyés au siège. On désire écrire un programme qui
affiche le nombre d’appareils vendu par semaine.

2.4. Tableau de dimension deux paramètre d’une fonction

Un tableau de dimension deux est défini par l’adresse de la première ligne,


qui est de type tableau, le nombre effectif de lignes et le nombre effectif de
colonnes. Pour passer un tableau bidimensionnel comme paramètre à une
fonction on doit lui fournier ces informations. Il faut noter que la taille maximale
d’une ligne, qui n’est d’autre que le nombre maximal de colonnes, est nécessaire
à la fonction pour pouvoir accéder à tous les éléments du tableau. La syntaxe est
la suivante

Syntaxe

Déclaration de la fonction
type_retour fonc1(type_elem Mat[][MAX], int L, int M)
type_retour fonc2(type_elem Mat[][MAX], int *L, int *M)

Appel de la fonction
int L, M ;
type_elem Mat[MAXL][MAXC] ;

fonc1(Mat, L, M)
fonc2(Mat, &L, &M)

 MAX est une constante qui indique la taille maximale d’une ligne.

Exemple

Ce programme permet de saisir le tableau des notes des 12 modules d’une


section, de calculer la moyenne de chaque étudiant, de stocker le résultat dans la
13ème colonne, de calculer le nombre de module non validé, de stocker le résultat
dans la 14 ème colonne et d’afficher la liste des admis (numéro de la ligne).

#define M_LIN 100


#define M_COL 20

/**************************************************/
/* Fonction Saisie des notes */
/**************************************************/
void Saisie( float notes[][M_COL], int nl, int nc)
{

for(i= 0; i<nl; i++)


for(j=0; j<nc; j++)
scanf("%d", &notes[i][j];
}

A.Zahi/DI/FSTF
88

/**************************************************/
/* Fonction Calcul de la moyenne générale */
/**************************************************/
void Cal_Moy (float notes[][M_COL], int nl, int *nc)
{
for (i=0 ; i<nl ;i++)
{
moy =0.0 ;
for j=0 ; j< *nc ; j++)
moy += notes[i][j];
notes[i][13]=moy;
}
*nc = *nc +1 ;
}
/****************************************************/
/* Fonction Calcul du nombre de modules non validé */
/****************************************************/
void Cal_nmnv (float notes[][M_COL], int nl, int *nc)
{
int nm_nv;
for (i=0 ; i<ne ;i++)
{
nm_nv = 0 ;
for j=0 ; j<12 ; j++)
if (notes[i][j]< 7)
nm_nv += 1;
notes[i][14]=nm_nv;
}
*nc = *nc +1 ;
}
/****************************************************/
/* Fonction Affichage du tableau */
/****************************************************/
void affiche (float notes[][M_COL], int nl, int nc)
{

for(i= 0; i<nl; i++)


{
for (int j =0; j <nc; j++)
printf("\n %d ", notes[i][j]);
printf(" \n");
}
}
/****************************************************/
/* Fonction main */
/****************************************************/
void main()
{
float notes[M_LIN][M_COL], moy ;
int i, j, ne, nc;

printf("donner le nombre d’étudiants ");


scanf("%d",&ne);

printf("donner le nombre de modules ");


scanf("%d",&nm);

Saisie( notes, ne, nm);


Cal_Moy(notes, ne, &nm);
Cal_nmnv(notes, ne, &nm);
Affiche(notes, ne, nm);
}

A.Zahi/DI/FSTF
89

3. Chaînes de caractères

Une chaîne de caractères est une suite de caractères. En C, bien qu’il existe
une bibliothèque qui permet de gérer les chaînes de caractères, il n’existe aucun
type qui permet de les représenter. Une chaîne de caractères est donc représentée
par un tableau de caractères. Le tableau peut être statique ou dynamique.

3.1. Déclaration

Pour déclarer une chaîne de n caractères on a besoin d’un tableau de n+1


éléments, le dernier élément est réservé au caractère NULL ‘\0’, qui indique la
fin de la chaîne.

Syntaxe
char chaine[nb_caractere] ;/* représentation statique */
char * chaine ; /* représentation dynamique */

 nb_caractere c’est une constante qui indique le nombre de caractères


de la chaîne.

 chaine c’est un ’identificateur qui représente le nom de la chaîne.

Remarque
Dans le cas d’une représentation dynamique un espace mémoire doit être
réservé à la chaîne, à l’aide de la fonction malloc, avant toute utilisation :

char * ch ;
ch = (char *) malloc(nb_caractere * sizeof(char)) ;

Exemples
char Nom[7] ;/* peut contenir un nom de 7 caractères */
char* prenom

3.2. Initialisation

Les tableaux de caractères peuvent être initialisés au moment de la


déclaration de deux façons :

• Comme pour les tableaux d’autres types :


char nom[3] = {‘A’,’l’,’i’,’\0’};

• Par une constante littérale :


char nom[4] = "Ali";
char* adresse = "25 Rue Jupiter, Système Solaire";
char profession[] = "Pilote d’avion";
Remarques

• Dans le premier cas il ne faut pas oublier le caractère ’\0’ qui indique la
fin de la chaîne.

• Dans le deuxième cas, le caractère de fin de chaîne est ajouté


automatiquement.

A.Zahi/DI/FSTF
90

3.3. Fonctions de manipulation

La bibliothèque <string.h> fournit une multitude de fonctions pratiques


pour le traitement des chaînes de caractères. Voici une brève description des
fonctions les plus fréquemment utilisées.

3.3.1. Affichage d’une chaîne

Les fonctions puts et printf permettent d’afficher à l’écran des chaînes de


caractères, ces fonctions peuvent afficher aussi bien des chaînes littérales que des
variables.

Syntaxe

/* prototype */
int puts (const char *ch);
int printf (const char *format, ch1, ch2,..., chn) ;

/* appel */
char *ch = " c’est moi" ;
puts(ch) ;
printf("%s ", ch) ;

 puts permet d’afficher la chaîne ch à l’écran, suivie d’un retour


chariot. Cette fonction renvoi le nombre de caractères de la chaîne.

 printf permet d’afficher les chaînes ch1, ch2, …, chn à l’écran


relativement à l’ordre de conversion, %s, spécifié dans la chaîne
littérale format.

Exemple

#include <stdio.h>

char *vert1= " Il faut d'abord choisir le point";


char *vert2= " Pour tracer ensuite le cercle saint";
char vert3[]= " Autour de ma tête et de mon être sain";

char vert4[]= " D'une exactitude presque militaire";


char *vert5= " Le point sert de centre et de repère";
char *vert6= " Noté zéro, nul parfois je m'y perds";
char auteur[]= "Dravitch";

main()
{
puts(vert1);
puts(vert2);
puts(vert3);

printf("\n\n");
printf ("%s\n%s\n%s\n", vert4, vert5, vert6);
printf("\n\n");
puts(auteur);
}

A.Zahi/DI/FSTF
91

3.3.2. Saisie d’une chaîne

Les fonctions gets et scanf permettent de lire des chaînes de caractères à


partir du clavier.

Syntaxe

/* prototype */
char* gets (char * ch);
int scanf (const char * format, ch1, ch2,..., chn) ;

/* appel */
char ch[10] ;
gets(ch) ;
scanf("%s", ch) ;

 gets permet de lire jusqu’à la rencontre du retour chariot, puis range le


résultat dans ch et remplace le retour chariot par le caractère ’\0’.
Cette fonction renvoi la chaîne ou le caractère NULL.

 scanf permet de lire ch1, ch2,..., chn à l’écran relativement à l’ordre


de conversion, %s, spécifié dans la chaîne littérale format.

 A la différence de la fonction gets(), scanf() ne permet pas de saisir


les chaînes contenant des espaces.

Exemple

#include <stdio.h>
#include <stdlib.h>
main()
{
char nom[14] ;
char *plainte ;

printf (’’entrer votre nom ’’) ;


scanf(’’%s ’’, nom) ;

plainte =(char*) malloc(50* sizeof(char)) ;


puts(’’entrer votre plainte ’’) ;
gets(plainte) ;

printf(’’ votre déposition est la suivante:\n’’) ;


puts (plainte) ;
}

3.3.3. Longueur d’une chaîne

Syntaxe

/* prototype */
int strlen(const char * ch) ;

/* appel */
char* ch1;
char ch2[20] ;

A.Zahi/DI/FSTF
92

int len1 = strlen(ch1) ;


int len2 = strlen(ch2) ;

 La fonction strlen renvoi le nombre de caractères de ch sans compter


le caractère nul.

Exemple
#include <stdio.h>
#include <string.h>
main()
{
char section[] = "Maitrises IEEA et TELECOM";
printf("Longueur :%d\n", strlen(section));
}

3.3.4. Copie de chaînes

Syntaxe

/* prototype */
char * strcpy( char * dest, char* source) ;

/* appel */
char * dest, *source ;
strcpy(dest, source) ;

 strcpy copie la chaîne source dans dest caractère par caractère y


compris le caractère ‘\0’ et retourne la chaîne dest.

Remarque

• Il faut réserver l’espace nécessaire pour la chaîne destination

• Il n’y a pas d’affectation des chaînes de caractères, pour réaliser cette


opération on utilise la fonction strcpy.

Exemple

#include <stdio.h>
#include <string.h>

main()
{
char dest[10];
char source[] = "Bonjour toto";

strcpy(dest, source);
printf("source : %s\n", source );
printf("copie : %s\n", dest);
printf("%s\n", dest);
}

A.Zahi/DI/FSTF
93

3.3.5. Concaténation

Syntaxe

/* prototype */
char * strcat( char * dest, char* source) ;

/* appel */
char * dest, *source ;
strcat(dest, source) ;

 strcat concatène la chaîne source à la chaîne dest. Cette fonction


retourne la chaîne dest.

Exemple

#include <stdio.h>
#include <string.h>
main()
{
char st[25];
char espace[] = " ", s[] = "salut", t[] = "toto";
strcpy(st, s);

strcat(st, espace);
strcat(st, t);

printf("s : %s\n", s);


printf("t : %s\n", t);
printf("st: %s\n", st);
}

3.3.6. Comparaison

Syntaxe

/* prototype */
int strcpy( char * s1, char* s2) ;

/* appel */
char * s1 , *s2 ;
int res= strcmp(s1, s2) ;

 strcmp compare la chaîne s1 à la chaîne s2. Les chaînes sont


comparées caractère par caractère en partant de la gauche. Cette
fonction retourne :

Ž une valeur négative dès qu’un caractère de la chaîne s1 est


plus petit que celui de la chaîne s2 .

Ž une valeur positive dès qu’un caractère de la chaîne s1 est


plus grand que celui de la chaîne s2 .

Ž La valeur 0 si les deux chaînes sont identiques.

A.Zahi/DI/FSTF
94

Exemple

#include <string.h>
#include <stdio.h>

main()
{
char s1[] = "aaa", s2[] = "bbb", s3[] = "ccc";
int ptr;
ptr = strcmp(s2, s1);

if (ptr > 0)
printf("s2 est plus grande que s1 \n");
else
printf("s2 est plus petite que s1 \n");

ptr = strcmp(s2, s3);

if (ptr > 0)
printf("s2 est plus grande que s3 \n");
else
printf("s2 est plus petite que s3 \n");

Exercices

Ecrire les fonctions qui permettent de réaliser les fonctions : strlen, strcmy, stcat,
et strcmp.

A.Zahi/DI/FSTF
95

Chapitre 3: Structures

Dans les chapitres précédents, nous n’avons utilisé que des objets simples
dont le type est prédéfini par le langage. Pour représenter des objets complexes
et hétérogènes, le langage C offre des mécanismes, tels que les structures et les
énumérations, qui permettent de construire de nouveaux types à partir des types
de base. Lors de la manipulation de ces constructeurs, Il faut distinguer entre la
construction et l’exploitation :

• La construction, appelée aussi définition, consiste à définir la forme du


type qu’on veut construire : son nom, le nom et le type de chaque
composant.

• L’exploitation correspond à la déclaration et à la manipulation des


variables de ce type.

1. Le mot clé typedef

Le mot clé typedef permet d’affecter un nouveau nom à un type existant,


qu’il soit simple ou composé.

Syntaxe

typedef type nom_type ;

 nom_type devient le nouveau nom du type, on peut ainsi déclarer


des variables à l’aide de nom_type.
Exemple

#include <stdio.h>
#include <stdlib.h>

typedef float real ;


typedef char* string ;
void main()
{
/* les notes de l’étudiant */
real note1 , note2 , moy ;

/* le nom de l’étudiant */
string nom;
nom = (string) malloc(10*sizeof(char));

A.Zahi/DI/FSTF
96

printf("donner le nom de l'étudiant: ") ;


gets(nom);
printf("Saisir la note1 : ") ;
scanf ("%f", &note1);
printf("Saisir la note2 : ") ;
scanf ("%f", &note2);
moy = (note1+note2)/2;
printf(" Mr %s a eu une moyenne de %f ", nom, moy) ;
}

2. Enumérations
2.1. Définition d’une énumération

Une énumération permet de construire un type à partir d’une liste de


valeurs. Cette liste constitue l’ensemble des valeurs prises par une variable de ce
type.

Syntaxe

typedef enum
{
enum_1,
enum_2,
.
.
enum_n,
} nom_enumeration ;

 nom_enumeration le nom de l’énumération.

 enum_1, enum_2, …, enum_n sont les identificateurs des


différentes constantes de l’énumération.

 Le compilateur affecte de façon automatique des valeurs entières, à


chaque constante de l’énumération, en partant de 0 et avec une
progression de 1.

 Il est possible de fixer la valeur d’un énumérateur lors de la


définition; la progression reprend à 1 pour l’énumérateur suivant.

 nom_enumeration devient le nom d’un type, On peut ainsi faire les


déclarations suivantes :
nom_enumeration v_1, v2, …;

Exemples

1. Construction d’un type booléen


typedef enum
{ Enumérateur Code
VRAI , VRAI 0
FAUX, FAUXt 1
} Bool ;

A.Zahi/DI/FSTF
97

2. Constrction d’un type couleur


typedef enum
{ Enumérateur Code
rouge , rouge 0
vert, vert 1
bleu, bleu 2
} Couleur ;

3. Constrction d’un type jour


typedef enum
{ Enumérateur Code
Lundi, Lundi 0
Mardi, Mardi 1
Mercredi, Mercredi 2
Jeudi = 50, Jeudi 50
Vendredi, Vendredi 51
Samedi, Samedi 52
Dimanche, Dimanche 53
} Jour;

2.2. Opérations sur les énumérations

Les opérations possibles sur les énumérations sont la comparaison et


l’affectation simple. Un objet de type énumération ne peut être saisi ou affiché
que sous forme d’un entier.

Exemples
1. Recherche séquentielle dans un tableau

#include <stdio.h>
typedef enum
{
vrai,
faux
} bool;
main()
{
int tab[10], n, i, v;
bool trouve;
printf(" Saisir la taille du tableau: ");
scanf("%d", &n);
for (i=0; i<n; i++)
{
printf("saisir tab[%d] = ", i);
scanf("%d", &tab[i]);
}
printf("Saisir la valeur v: ");
scanf("%d", &v);
i=0; trouve = faux;
while( i <=n && trouve == faux)
{
if(tab[i] == v) trouve = vrai;
i++;
}
if (trouve == vrai)
printf(" %d se trouve dans la case %d", v,i);
else
printf(" %d n'appartient pas au tableau", v);
}

A.Zahi/DI/FSTF
98

2. feu de circulation

#include <stdio.h>

typedef enum
{
rouge,
vert,
jaune,
} couleur;

void main()
{
couleur c;
printf("Saisir la couleur\n rouge: 0\n vert : 1 \n
jaune: 2\n\n choix: ");
scanf("%d",&c);

switch(c)
{
case rouge :printf("\n Arrêter ");
break;

case vert :printf("\nAvancer ");


break;

case jaune : printf("\nralentir ");


break;

default : printf("\nFeu en panne");


break;
}
}

3. Les Structures

Une structure permet de construire des objets formés par plusieurs


composantes hétérogènes i.e., de types différents. Les composantes d’une
structure s’appellent aussi membres ou champs.

3.1. Définition d’une structure

Syntaxe

typedef struct
{
type_1 nom_champ_1 ;
type_2 nom_champ_2 ;
.
.
type_n nom_champ_n ;

} ; nom_structure

 nom_structure c’est un identificateur qui indique le nom de la


structure.

A.Zahi/DI/FSTF
99

 nom_champ_1, nom_champ_2,...,nom_champ_n sont les noms


des membres qui caractérisent l’objet.

 type_1, type_2,...,type_n, sont les types des différents membres.

Exemples

1. Construction d’un type complexe

typedef struct
{
float real ;
float img ;
} complexe;

2. Construction d’un type date

typedef struct
{
int annee;
int mois;
int jour;
} date;

3. Construction d’un type point

typedef struct
{
float x ;
float y ;
} point;

3.2. Déclaration

La déclaration d’une variable d’un type construit obéit aux mêmes règles et
à la même syntaxe que celles des types de bases.

Syntaxe

• Variables statiques

nom_structure s1, s2 ;

• Variables dynamiques

nom_structure *s1, *s2 ;

 Il ne faut oublier, dans ce cas, d’allouer de l’espace mémoire à


ces variables avant de les utiliser :

s1= (nom_structure *) malloc(sizeof(nom_structure));

A.Zahi/DI/FSTF
100

Exemples

complexe z1, z2 ;
complexe *z3, *z4 ;

z3= &z1 ;
z4= (complexe*) malloc(sizeof(complexe)) ;

3.3. Opérations sur les structures

Les structures peuvent être manipulées soit membre par membre ou comme
une entité indépendante.

3.3.1. Accès aux membres

Pour désigner un membre d’une structure on utilise l’opérateur de sélection


point (.) pour les variables statiques et l’opérateur (Æ) pour les variables
dynamiques.

Syntaxe

nom_variable.nom_champ; /* Variable statique */

nom_variable->nom_champ; /* Variable dynamique */

 nom_variable le nom de la variable et nom_champ le nom du membre


au quel on veut accéder.

 Les membres ainsi désignés se comportent comme des variables


simples qu’on peut utiliser de différentes manières dans un programme :

Ž Saisie :

scanf("%c", &nom_structure.nom_champs) ;
scanf("%c", &nom_structure->nom_champs) ;
avec c, le spécificateur de format associé au type du champ.

Ž Affichage :

printf("%c", nom_structure.nom_champs) ;
printf("%c", nom_structure->nom_champs) ;
avec c, le spécificateur de format associé au type du champ.

Ž Affectation
nom_structure.nom_champs)= expression ;
nom_structure->nom_champs)= expression ;

Ž Elément d’une instruction : facteur d’une expression, instruction


du choix, boucle etc.

A.Zahi/DI/FSTF
101

Exemple
Ce programme saisit deux complexes, calcul leur somme et leur produit et
affiche les résultas.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
float real;
float img;

} complexe;

void main()
{
complexe z1;
complexe *z2;
complexe *som, prod;
/* saisie des variables*/
printf("\nSaisi du complexe z1\n");
printf("\tz1.real = "); scanf("%f",&z1.real);
printf("\tz1.img = "); scanf("%f",&z1.img);
printf("\nSaisi du complexe z2\n");
z2 =(complexe*) malloc(sizeof(complexe));
printf("\tz1.real = "); scanf("%f",&z2->real);
printf("\tz1.img = "); scanf("%f",&z2->img);
/* calcul de la somme de z1 et z2*/
som=(complexe*) malloc(sizeof(complexe));
som->real = z1.real + z2->real;
som->img = z1.img + z2->img ;
/* calcul du produit de z1 et z2 */
prod.real = (z1.real*z2->real - z1.img*z2->img);
prod.img = (z1.real*z2->img + z1.img*z2->real);

/* affichage des résultats */


printf("Somme = %f + i%f ", som->real, som->img);
printf("\nProduit = %f + i%f ", prod.real,
prod.img);
}

3.3.2. Initialisation

Une variable de type structure peut être initialisée lors de la déclaration par
une liste d’expressions constantes.

Syntaxe
typedef struct
{
type_1 nom_champ_1 ;
type_2 nom_champ_2 ;
.
.
type_n nom_champ_n ;
} nom_structure;

nom_structure s1 = {exp_1, exp_2, …, exp_n}

A.Zahi/DI/FSTF
102

 Chaque expression exp_i est affectée au membre correspondant


nom_champ_i, exp_i doit être une constante de même type que
nom_champ_i

Exemple
complexe z1 = {8.,10.};
complexe z2 = {9.25,5.2};

3.3.3. Affectation

L’affectation d’une structure à une autre de même type permet de transférer


les valeurs des champs de la structure source dans leurs homologues de la
structure destination.

Syntaxe

typedef struct
{
type_1 nom_champ_1 ;
type_2 nom_champ_2 ;
.
.
type_n nom_champ_n ;
} nom_structure;

nom_structure s1, s2 ;

s1 = s2;

3.4. Structure paramètre d’une fonction

Syntaxe

typedef struct
{
type_1 nom_champ_1 ;
type_2 nom_champ_2 ;
.
.
type_n nom_champ_n ;
} nom_structure;

Prototype de la fonction

/* comme paramètre fixe */


void fonc1(nom_structure s1) ;

/* comme paramètre variable */


void fonc2(nom_structure *s1) ;

/* comme type de retour */


nom_structure fonc3(…) ;

A.Zahi/DI/FSTF
103

Appel de la fonction
nom_structure *s1, s2, s3 ;

fonc1(*s1) ;
fonc1(s2) ;

fonc2(s1) ;
fonc2(&s2) ;

s3 = fonc3(…) ;

Exemple
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
float real;
float img;
} complexe;
/* fonction saisie d'un complexe*/
void saisie(complexe *z)
{
printf("\treal = "); scanf("%f",&z->real);
printf("\timg = "); scanf("%f",&z->img);
}
/* fonction calcul de la somme*/
void somme(complexe z1, complexe z2, complexe *s)
{
s->real = z1.real + z2.real;
s->img = z1.img + z2.img ;
}
/* fonction calcul du produit*/
complexe produit(complexe z1, complexe z2)
{
complexe p;
p.real = (z1.real*z2.real - z1.img*z2.img);
p.img = (z1.real*z2.img + z1.img*z2.real);
return p;
}
/* fonction affichage */
void affiche(complexe z)
{
if(z.real == 0)
if(z.img == 0)
printf("0");
else
if(z.img == 1)
printf("i");
else
printf("i%1.2f",z.img);
else
if(z.img == 0)
printf("%10.2f", z.real);
else
if(z.img == 1)
printf("%1.2f + i",z.real);
else
printf("%1.2f + i%1.2f",z.real,
z.img);
}

A.Zahi/DI/FSTF
104

void main()
{
complexe z1;
complexe *z2;
complexe *som, prod;

/* saisie de complexe*/
printf("\nSaisi du complexe z1\n");
saisie(&z1);
z2 =(complexe*) malloc(sizeof(complexe));
printf("\nSaisi du complexe z2\n");
saisie(z2);

/* calcul de la somme de z1 et z2*/


som=(complexe*) malloc(sizeof(complexe));
somme(z1,*z2,som);

/* calul du produit de z1 et z2 */
prod = produit(z1,*z2);

printf("\n");
printf("Somme = ");affiche(*som);
printf("\nProduit = ");affiche(prod);
}

3.5. Tableau de structures

Un tableau de structure est un tableau dont les éléments sont des structures.

Syntaxe

#define CAP 100

typedef struct
{
type_1 nom_champ_1 ;
type_2 nom_champ_2 ;
.
.
.
type_n nom_champ_n ;
} nom_structure;

nom_structure T[CAP];

 T le nom du tableau.

 nom_structure type des éléments du tableau.

 T[i] représente l’élément de rang i, c’est une variable de type


nom_structure,

 Pour accéder au jème champ de l’élément i on écrit :

T[i].nom_champ_j.

A.Zahi/DI/FSTF
105

Exemple

Ce programme saisi un tableau de complexe et affiche l’élément qui le plus petit


module
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define CAP 10

typedef struct
{
float real;
float img;
} complexe;

/* fonction saisie d'un complexe*/


void saisie(complexe *z)
{
printf("\treal = "); scanf("%f",&z->real);
printf("\timg = "); scanf("%f",&z->img);
}

/* fonction calcul du module */


float module(complexe z)
{
float m;
m=sqrt(z.real*z.real + z.img*z.img);
return m;
}
/* fonction affiche complexe */
void affiche(complexe z)
{
if(z.real == 0)
if(z.img == 0)
printf("0");
else
if(z.img == 1)
printf("i");
else
printf("i%1.2f",z.img);
else
if(z.img == 0)
printf("%10.2f", z.real);
else
if(z.img == 1)
printf("%1.2f + i",z.real);
else
printf("%1.2f + i%1.2f",z.real,
z.img);
}
/* saisie d’un tableau de complexes */
void saisieTab(complexe T[], int n)
{
int i;
for (i=0; i<n; i++)
{
printf("\nSaisi du complexe Tab[%d] \n",i+1);
saisie(&T[i]);
}
}

A.Zahi/DI/FSTF
106

/* function maximum */
int Max_Mod(complexe T[], int n)
{
int ind;
float max;
max =-1;
ind = 0;
for (i=0; i<n; i++)
{
mod = module(T[i]);
if (mod > max)
{
max= mod;
ind = i;
}
return ind;
void main()
{
complexe Tab[CAP];
int i,ind,n;
float mod, max;
printf("saisir la taille du tableau");
scanf("%d", &n);
saisieTab(Tab,n);
ind = Max_Mod(Tab, n);
affiche(Tab[ind]);
}

3.6. Tableau membre d’une structure

Une structure peut contenir un ou plusieurs tableaux comme membres, les


tableaux peuvent contenir tous les types de données C.

Syntaxe

typedef struct
{
type_1 nom_champ_1 ;
type_tab T[10];
.
.
.
type_n nom_champ_n ;
} nom_structure ;

 Pour accéder aux éléments du tableau, on utilise les opérateurs


d’accès (.) et (Æ) et l’opérateur d’indexation ([]) :
nom_structure *s1, s2 ;
s1->T[i]
s2.T[i]
Exemple

A la fst, pour chaque étudiant on retient les informations suivantes: le nom,


le code, les notes des 12 modules, et la moyenne générale. Le programme ci-
dessous saisit les informations d’un étudiant, calcul sa moyenne générale, calcul
le nombre de modules non validés et affiche s’il est admis

A.Zahi/DI/FSTF
107

#include <stdio.h>
typdef struct
{
char nom[10] ;
int CNE;
float mod [12] ;
float Moy ;
} etudiant;

/* saisi d’un tableau de réel*/


void saisiMod(float t, int n)
{
int i;
for (i=0; i<n; i++)
{
printf("\nSaisir le module M[%d] \n",i+1);
scanf("%f",&t[i]);
}
}
/* saisie d’un étudiant étudiant */
void saisie( etudiant * etu)
{
printf ("entrer le nom ") ;
gets(etu->nom) ;
printf("entrer le CNE") ;
scanf("%d",&etu->CNE) ;
printf("entrer les des 12 modules ") ;
saisiMod(etu->mod, 12);
}
/* calcul de la moyenne générale*/
void cal_moy(etudiant *etu)
{
int i;
etu->Moy=0.0;
for (i=0; i<12; i++)
etu->Moy += etu->mod[i];
etu->Moy = (etu->Moy)/12;
}

/* admission */
void admis(etudiant etu)
{
if ( etu.moy >=10)
return 1 ;
else
return 0
}

void main()
{
etudiant e;
saisi(&e);
cal_moy(&e);
if( admis(e))
printf ("Admis") ;
else
printf ("Ajourné ") ;
}

A.Zahi/DI/FSTF
108

3.7. Structures imbriquées

Une structure peut contenir un membre de type structure, noter que la


structure membre doit être définie avant la structure qui la contient.

Syntaxe

typedef struct
{
type_1 nom_champ_1 ;
.
.
type_n nom_champ_n ;
} st_memmbre ;

typedef struct
{
type_1 nom_champ_1 ;
st_membre s1;
st_membre s2;
.
.
.
type_n nom_champ_n ;
} nom_structure;

Exemple
#include<stdio.h>
struct date
{
int jour ;
int mois ;
int annee ;
} ;
struct livre
{
char titre [30] ;
char auteur[14] ;
int code ;
date d_entrée ;
date d_sortie ;
} ;

/* saisie d’une date */


void saisieDate(date *d)
{
printf (’’entrer le jour’’) ;
scanf("%d " &d->jour) ;
printf(’’entrer le mois’’) ;
scanf("%d " &d->mois) ;
printf(’’entrer l’année ’’) ;
scanf("%d " &d->annee) ;

A.Zahi/DI/FSTF
109

/* lecture d’un livre */


void saisielivre(livre * l)
{
printf (’’entrer l’auteur ’’) ;
gets(l->auteur) ;
printf (’’entrer le titre’’) ;
gets(l->titre) ;
printf(’’entrer le Code’’) ;
scanf(’’%d’’,&l->code) ;
printf("entrer la date d’entrée ") ;
saisiDate(&l->d_entree) ;
printf("entrer la date de sortie ") ;
saisiDate(&l->d_sortie);
}
/* fonction recherche du code d’un livre par le titre dans
un tableau de livre*/

int RechCode(livre L[], int n, char* titre)


{
int i ;
for (i=0, i<n ; i++)
{
if(strcmp((L[i].Titre, titre))
return L[i].Code;
}
return -1;
}

main()
{
livre L[50] ;
int n, i ;
char titre[30] ;
printf("Saisir le nombre de livres") ;
sacnf("%d ", &n) ;

/* Saisie des livres */


for(i=0 ; i<n ; i++)
saisielivre(&L[i]) ;
/* Recherche d’un livre */
printf("Saisir le titre") ;
gets(titre) ;
printf("Le code est : ", RechCode(L,n,titre)) ;
}

A.Zahi/DI/FSTF
110

Chapitre 4: Fichiers

Un programme communique avec son environnement extérieur (Utilisateurs,


Programmes, Machines, etc.,) à travers des dispositifs appelés périphériques. En
C, l’échange de l’information entre un programme et les périphériques se fait par
l’intermédiaire des fichiers. Tous les périphériques sont considérés comme des
fichiers, le programme lit les données sur un périphérique et écrit les résultats sur
un périphérique. Dans ce chapitre nous allons présenter comment manipuler les
fichiers dans un programme C.

1. Définition

Un fichier constitue l’entité de base pour conserver l’information sur un


support de stockage (disque dur, disquette, CD, flash disque etc.,). C’est une
collection d’informations homogène vue structurée comme une suite d’octets ou
de caractères. Sur un support de stockage, un fichier est identifié par une chaîne
de caractères qui désigne le nom physique du fichier, ce nom est généralement
attribué par l’utilisateur.

Il existe deux fichiers qui sont définis par défaut pour tous les
programmes : le fichier stdin, qui est associé avec l’entrée standard (le clavier) et
le fichier stdout qui est associé la sortie standard (l’écran).

2. Mémoire tampon

Pour des raisons de performances, les accès à un fichier se font par


l’intermédiaire d’une mémoire tampon appelée buffer. C’est une zone de la
mémoire centrale réservée à un ou plusieurs octets ou caractères du fichier. Le
programme récupère, les informations en provenance du fichier, à partir du
buffer et dépose, les informations à destination du fichier, sur le buffer.
L’utilisation de la mémoire tampon permet de réduire le nombre d’accès au
support de stockage et minimise par suite les déplacements de la tête de
lecture/écriture.

A.Zahi/DI/FSTF
111

Programme C

Instructions
+
Données

Mémoire tête
tampon l/e Support
de
stockage
Mémoire
centrale

Figure 18 : Procédure d’accès à un fichier

3. Accès à un fichier

3.1. Le type FILE*

FILE* est un pointeur sur une structure déclarée dans le fichier en-tête
<stdio.h>. Cette structure contient les informations telles que l’adresse de la
mémoire tampon, la position courante de la tête de lecture/écriture, le type
d’accès au fichier, état d’erreur etc., Un programme doit déclarer un pointeur sur
cette structure pour pouvoir accéder aux fichiers.

Syntaxe

FILE * flot;

3.2. Ouverture/fermeture

Pour établir la connexion avec le fichier, le programme notifie le système


d’exploitation par la fonction d’ouverture fopen, qui reçoit le nom physique du
fichier comme paramètre, le système génère ensuite un bloc de type FILE et
retourne son adresse au programme. La connexion est coupée à l’aide de la
fonction de fermeture fclose .

Syntaxe

FILE *flot;
flot= fopen(non_physique, mode_ouverture) ;
fclose(flot) ;

A.Zahi/DI/FSTF
112

 flot pointeur sur la structure qui contient les informations au sujet


du fichier

 non_physique c’est une chaîne de caractères qui contient le nom


du fichier physique.

 mode_ouverture c’est un pointeur sur une chaîne de caractères qui


indique le mode d’ouverture du fichier. Elle peut être l’une des
chaînes suivantes :

Mode Position Signification


’’r’’ début Ouverture d’un fichier texte en
lecture
’’w’’ début Ouverture d’un fichier texte en
écriture
’’a’’ fin Ouverture d’un fichier texte en
écriture
’’rb’’ début Ouverture d’un fichier binaire en
lecture
’’wb’’ début Ouverture d’un fichier binaire en
écriture
’’ab’’ fin Ouverture d’un fichier texte en
écriture
’’r+’’ début Ouverture d’un fichier texte en
lecture/ écriture
’’w+’’ début Ouverture d’un fichier texte en
lecture/ écriture
’’a+’’ fin Ouverture d’un fichier texte en
lecture/écriture
’’r+b’’ ou ’’rb+’’ début Ouverture d’un fichier binaire en
lecture/écriture
’’w+b’’ ou ’’wb+’’ début Ouverture d’un fichier binaire en
lecture/écriture
’’a+b’’ ou ’’ab+’’ fin Ouverture d’un fichier binaire en
lecture/ écriture

 La fonction fopen retourne une valeur de type pointeur vers FILE,


si l’ouverture a réussi la valeur retournée permet de repérer le
fichier, dans le cas contraire la valeur retournée est la constante
NULL.

 La fonction fclose permet de fermer le fichier repéré par flot. Elle


retourne la valeur 0 si le fichier a été fermé, et rend la valeur EOF
s’il y a eu une erreur.

A.Zahi/DI/FSTF
113

Exemple

#include <stdio.h>
main(()
{
FILE * flot ;
flot= fopen(’’fichier.dat’’, ’’r’’) ;
if(flot==NULL)
printf(’’erreur d’ouverture ’’) ;
else
/* traitement sur le fichier*/
....
fclose(flot) ;
}

4. Lecture /écriture
4.1. Lecture et écriture par caractère

Les fonctions fgetc et fputc permettent de lire et d’écrire un caractère sur


un fichier.

Syntaxe

FILE *flot;
int car ;
char car ; /* erreur */
car=fgetc (flot) ;
fputc(flot) ;

 flot est un pointeur de type FILE*, il pointe sur le fichier à partir


duquel se fait la lecture ou sur lequel se fait l’écriture.

 car est de type int, c’est le caractère à écrire dans le fichier ou dans
lequel on récupère le caractère lu à partir du fichier.
Exemple

#include <stdio.h>
main()
{
int car ;
FILE* f;
/* écriture dans le fichier test.dat*/
f= fopen ("test.dat", "w");
if(f != NULL){
while ( (car=getchar()) != '\n')
fputc(car,f );
}
fclose(f);
/* lecture du fichier test.dat*/
f= fopen ("test.dat", "r");
if(f != NULL)
{
while ( (car= fgetc(f)) !=EOF)
printf("%c" , car);
}
fclose(f);
}

A.Zahi/DI/FSTF
114

4.2. Lecture et écriture par chaînes de caractères

Les fonctions fgets et fputs permettent de lire et d’écrire des chaînes de


caractère sur un fichier.

Syntaxe

FILE *flot;
char * chaine ;
fgets(chaine,nb, flot) ;
fputs(chaine, flot) ;

 chaine est un pointeur vers char qui contient la chaîne à lire ou à


écrire.

 flot est un pointeur de type FILE*, il pointe sur le fichier à partir


duquel se fait la lecture ou sur lequel sa fait l’écriture.

 nb est la taille en octets du tableau pointé par chaine.

Exemple
#define BUFSIZE 10
#include <stdio.h>
main()
{
char* ch1="Abou Bakker Elkawarizmi\n";
char* ch2="Alain Turing \n";
char bf[BUFSIZ+1];
FILE* f;
/* écriture dans le fichier chaine.dat*/
f= fopen ("chaine.dat", "w");
if(f != NULL)
{
fputs(ch1,f);
fputs(ch2,f);
}
fclose(f);
/* lecture du fichier chaine.dat*/
f= fopen ("chaine.dat", "w");
if(f != NULL)
{
while (fgets (bf,sizeof(bf),f))
printf("%s\n",bf);
}
fclose(f);
}

4.3. Lecture et écriture formatées

Les fonctions fscanf et fprintf permettent, de lire et d’écrire des données


avec conversions de type.

A.Zahi/DI/FSTF
115

Syntaxe

fscanf (f, format,&var_1, &var_2,...) ;


fprintf(f, format ,var_1, var_2 ...);

 f est un pointeur de type FILE*, il pointe sur le fichier à partir


duquel se fait la lecture ou sur lequel se fait l’écriture,

 format c’est une chaîne de caractère qui indique ce qui doit être
écrit ou lu. Cette chaîne contient des caractères constants et des
spécificateurs de formats commençant par le caractère %, décrivant
comment les paramètres var_i doivent être écrits

 var_i une variable qui contient une valeur à lire ou à écrire


Exemples

1. Lecture et écriture d’une seule structure dans un fichier


#include <stdio.h>
struct Foncti
{
int Code;
float Sal;
char Nom[15];
};
/* écriture dans le fichier*/
void Ecriture(char * nom, Foncti, fon)
{
f= fopen (nom, "w");
if(f != NULL)
{
fprintf(f,"%d\n",fon.Code);
fprintf (f,"%f\n",fon.Sal);
fprintf (f,"%s\n",fon.Nom);
}
fclose(f);
}
/* lecture à partir du fichier */
void lecture(char* nom, Foncti *g)
{
f= fopen (nom, "r");
if(f != NULL)
{
fscanf (f,"%d\n", &g->Code);
fscanf (f,"%f\n", &g->Sal);
fscanf (f,"%s\n", &g->Nom);
}
fclose(f);
}
main()
{
Foncti fon ={145, 5000.00, "Ali"},g;
FILE* f;
/* écriture dans le fichier "fonc.dat" */
Ecriture("fonc.dat",fon)
/* lecture à partir du fichier*/
lecture("fonc.dat", &g) ;
printf("%d %s %f\n",g.Code,g.Nom,g.Sal);}

A.Zahi/DI/FSTF
116

2. Lecture et écriture d’un tableau de structures dans un fichier

#include <stdio.h>
struct Foncti
{
int Code;
float Sal;
char Nom[15];
};

/* écriture du tableau dans le fichier */


void EcrireTab(char *nom, Foncti fonc[], int nb)
{
f= fopen (nom, "w");
if(f != NULL)
{
for(int i =0; i<nb; i++)
{
fprintf(f,"%d ",fon[i].Code);
fprintf (f,"%f ",fon[i].Sal);
fprintf (f,"%s\n ",fon[i].Nom);
}
}
fclose(f);
}
/* Lecture du tableau à partir du fichier */
void LireTab(char *nom, Foncti d[], int *nb)
{
Foncti g;
f= fopen (nom, "r");
if(f != NULL)
{
*nb=0;
while (!feof(f))
{
fscanf(f,"%d\n",&g.Code);
fscanf(f,"%f\n",&g.Sal);
fscanf(f,"%s\n",&g.Nom);
d[Nb]=g;
(*nb)++;
}
}
fclose(f);
}
main()
{
Foncti fon[] ={ {145, 5000.00, "Ali"}, {148,
3000.00, "Doudou"}, {150, 2000.00, "Dadi"}};
Foncti d[10],g;
int nb;
FILE* f;
EcrireTab("fonc.dat", fonc,3) ;
LireTab("fonc.dat", d,&nb) ;
for(int i=0; i<nb; i++)
printf("%d %s %f\n", d[i].Code, d[i].Nom,
d[i].Sal);
}

A.Zahi/DI/FSTF
117

4.4. Lecture et écriture par blocs

Les fonctions fread et fwrite permettent de lire et d’écrire des blocs de


données tels que les structures et des tableaux.

Syntaxe

fread(p, t , n, f) ;
fwrite(p, t , n, f) ;

 p est un pointeur générique qui pointe sur le bloc à lire ou à écrire.

 t indique la taille du bloc à lire ou écrire.

 n indique le nombre de blocs à lire ou écrire,

 f est un pointeur de type FILE*, il pointe sur le fichier à partir


duquel se fait la lecture ou sur lequel se fait l’écriture,

 Ces fonctions retournent le nombre de blocs traités.


Exemples

1. Lecture et écriture d’une seule structure dans un fichier

#include <stdio.h>
struct Foncti
{
int Code;
float Sal;
char Nom[15];
};
/* écriture dans le fichier*/
void Ecriture(char * nom, Foncti, *fon)
{
f= fopen (nom, "w");
if(f != NULL)
fwrite (fon, sizeof(Foncti), 1,f);
fclose(f);
}
/* lecture à partir du fichier */
void lecture(char* nom, Foncti *g)
{
f= fopen (nom, "r");
if(f != NULL)
fread(g, sizeof(Foncti), 1,f);
fclose(f);
}
main()
{
Foncti fon ={145, 5000.00, "Ali"} , g;
FILE* f;
/* écriture dans le fichier fonc.dat */
Ecriture("fonc.dat",&fon)
/* lecture à partir du fichier fonc.dat */
lecriture("fonc.dat",&g)
printf("%d\n",g.Code);}

A.Zahi/DI/FSTF
118

2. Lecture et écriture d’un tableau de structures dans un fichier


#include <stdio.h>
struct Foncti
{
int Code;
float Sal;
char Nom[15];
};
/* écriture du tableau dans le fichier */
void EcrireTab(char *nom, Foncti fonc[], int nb)
{
f= fopen (nom, "w");
if(f != NULL)
{
fwrite(fon, sizeof(Foncti), nb, f);
}
fclose(f);
}
/* Lecture du tableau à partir du fichier */
void LireTab(char *nom, Foncti d[], int nb)
{
Foncti g;
f= fopen (nom, "r");
if(f != NULL)
fread(d, sizeof(Foncti), nb,f);
fclose(f);
}
main()
{
Foncti fon[] ={ {145, 5000.00, "Ali"}, {148,
3000.00, "Doudou"}, {150, 2000.00, "Dadi"}};
Foncti d[10];

int i;
FILE* f;
/* écriture du tableau dans le fichier */
EcrireTab("fonct.dat", fonc, 3) ;

fclose(f);
/* Lecture du tableau à partir du fichier */
Liretab("fonct.dat", d,3) ;
i=0 ;
while (i<3)
{
printf("%d%f%s\n",d[i].Code,d[i].sal,d[i].Nom);
i++;
}
}

5. Accès directe

Pour chaque fichier ouvert est associé un indicateur de position qui indique à
quel endroit du fichier aura lieu la prochaine opération (lecture/écriture). Cette
position est donnée en nombres d’octets à partir du début du fichier. Par défaut,
les fonctions précédentes travaillent en mode séquentiel, et mettent à jour cet
indicateur par incrémentation automatique. En effet, chaque lecture ou écriture
s’effectue à partir d’une position courante, et incrémente cette position du
nombre de caractères lus ou écrits.

A.Zahi/DI/FSTF
119

Les fonctions rewind, ftell, et fseek permettent d’effecteur un contrôle sur


l’indicateur de position, on peut par suite faire un accès aléatoire au fichier.

Syntaxe

rewind(f)
ftell(f) ;
fseek(f, dec, position)

 La fonction rewind permet de placer l’indicateur de position au


début du fichier.

 La fonction ftell permet de retourner la valeur de l’indicateur de


position.

 La fonction fseek permet de donner une nouvelle valeur à


l’indicateur de position.

 dec valeur du décalage est exprimée en octets,

 position celle à partir de la quelle est calculé le décalage, elle


s’exprime à l’aide des constantes définies dans le fichier <stdio.h>,

Ž SEEK_SET début de fichier,


Ž SEEK_CUR position courante.
Ž SEEK_END fin de fichier.
Exemple

#include <stdio.h>
#define PAS 10
char mess[]="abcdefghijklmnopqrstuvwxyz";
int main(void)
{
FILE *f;
char temp[PAS];
/* Ecriture dans le fichier */
f=fopen("text.txt","w");
if(f != NULL)
fprintf(f,"%s",mess);
fclose(f);
/* fonction ftell */
f=fopen("text.txt","r");
printf (" Avant la lecture\n \t position :%d\n",
ftell(f));
fgets(temp,PAS,f);
printf (" \n Apres la 1 er lecture\n");
printf("\t caractere :%s\t position : %d\n", temp,
ftell(f));
fgets(temp,PAS,f);
printf (" \n Apres la 2 eme lecture \n");
printf("\t caractere : %s \t position : %d\n", temp,
ftell(f));
fgets(temp,PAS,f);
printf (" \nApres la 3 eme lecture \n");
printf("\t caractere : %s \t position : %d\n", temp,
ftell(f));

A.Zahi/DI/FSTF
120

/* fonction rewind */
rewind(f);
printf ("\n Apres rewind, la position est: %d\n",
ftell(f));
fgets(temp,PAS,f);
printf (" \n1 er lecture Apres rewind \n");
printf("\t caractere : %s \t position : %d\n", temp,
ftell(f));
fclose(f);
getchar();
}

A.Zahi/DI/FSTF

You might also like