Vous êtes sur la page 1sur 71

Université Sidi Mohamed Ben Abdellah

Faculté des Sciences Dhar El-Mehraz Fès


Département d’Informatique

Initiation
à la programmation C

Par Noureddine Chenfour


1995-2015

N. Chenfour 1
Chapitre 1 :

Eléments de base du langage C

Résumé :

- Pour commander un ordinateur, on utilise un programme

- Un programme est une séquence de commandes (Instructions) adressées au


microprocesseur

- Le programme est chargé depuis le Disque Dur vers la mémoire (qui est à contenu
volatil, mais à accès très rapide par rapport au disque dure).

- La mémoire est rattachée au Microprocesseur par l’intermédiaire d’une suite de


BUS (de données ou d’adresse) permettant de faire véhiculer Instruction ou
données (+ adresses) entre le Microprocesseur et la mémoire.

- Le microprocesseur charge les instructions depuis la mémoire (RAM) instruction


par instruction.

- Chaque instruction sera déposée dans un registre d’instruction, traitée par le bloc
de décodage et exécution des instruction. Si l’instruction comporte l’adresse d’une
donnée (Mov Ax, X),

- Celle-ci sera chargée dans le microprocesseur via un bus de donnée, vers


l’accumulateur = registre AX qui constitue la sortie de l’UAL : Unité
Arithmétique et Logique, là où se passent toute les opération du processeur.

- L’instruction Exécutée par le Microprocesseur est en code Machine (binaire).

N. Chenfour 2
- Pour faciliter la tâche aux développeurs, il fallait inventer un langage de
programmation (Le langage d’assemblage) + le traducteur [Langage d’assemblage
 Binaire] (ce dernier est appelé ASSEMBLEUR).

Exemples d’instruction du langage d’assemblage :

MOV AX, X

ADD AX, Y

MOV Z, AX

- Ce code qui signifie (Z  X + Y) sera transformé en binaire pour être exécuté par
le Microprocesseur.

- L’évolution a permis plus tard de créer des langages plus évolués (proche de la
syntaxe humaine). L’instruction devient par exemple (en Langage C) :

Z=X+Y;

- Le traducteur dans ce cas est appelé COMPILATEUR.

- Pour faire de la programmation il faut donc choisir un langage de programmation


(Pascal, C, C++, Java, …) en fonction des besoins.

- Il faut ensuite étudier et maîtriser la syntaxe du langage.

I. Squelette général d’un programme C

Rappel : Un programme est un ensemble de variables (les données du programme) + un


ensemble d’instructions utilisant ces variables :

Déclaration des variables Globales

void main() {

Déclaration des variables Locales au main()

Instructions

N. Chenfour 3
II. Déclaration de variables
- Une variable peut être globale ou locale au main. Si elle est déclarée dans le main,
alors c’es une variable locale (elle ne peut être utilisée que dans le main).

- Pour déclarer une variable, il faut lui donner un nom (significatif) et un type.

- Il existe plusieurs types, nous utiliserons dans ce chapitre 3 types de base :

1. int : permettant de gérer des entiers signés : 2 Octets de valeurs entre -32768 et
32 767. exemple : ages, quantités, années, mois, etc…

2. float : permettant de gérer des valeurs réels sur 4 Octets. Exemples : salaires, prix
en DH, etc…

3. char : permettant de gérer les caractère (entre ‘quotes’). exemples réponse à la


question …(o/n) ? on va répondre par ‘o’ ou par ‘n’.

- Les noms de variables, appelés identificateurs, sont formés comme une suite de
lettres de chiffres et de blancs soulignés ( _ ), qui commence par une lettre ou un
_ : alpha, a2, prix_unitaire, 2A, tù, t#,

- La syntaxe de déclaration est la suivante :

type var1, var2, var3, …. ;

avec type = int ou float ou char, …


Exemple :
int a1, a2, a3 ;
float x1, y1 ;
char c ;
- Une variable peut être initialisée lors de la déclaration :
Syntaxe :
type variable = valeur ;

type variable ;
variable = valeur ;

Exemple :
int a1=20, a2, a3=10 ;
float x1=14.5, y1 ;
char c = ‘A’ ;

N. Chenfour 4
Liste des types de données standards

Type Longueur Domaine de valeurs


char 8 bits -128 .. 127
unsigned char 8 bits 0 .. 255
short int 16 bits -32768 .. 32767
int 16 bits -32768 .. 32767
unsigned int 16 bits 0 .. 65535
long 32 bits -2,147,483,648 .. 2,147,483,647
unsigned long 32 bits 0 .. 4,294,967,295
float 32 bits 3.4 × (10-38) .. 3.4 × (10+38 )
double 64 bits 1.7 × (10-308) .. 1.7 × (10+308 )
long double 80 bits 3.4 × (10-4932) .. 1.1 × (10+4932 )

III. Les Instructions de base


L’affectation :
Cela consiste à attribuer une valeur à une variable. On utilisera le symbole : = .
Variable = valeur ;
Généralement :
Variable = Expression ;
Les Expressions :
Expression est généralement une expression arithmétique qui utilise des
opérateurs arithmétiques : +, -, *, /, % (reste d’une division entière)
Exemple :
X=Y+Z*2;
X=3*Y/5;
Remarques :
1. * et / sont plus prioritaire que + et –
2. Les expressions sont évaluées de gauche vers la droite :
X = Y +1 Z +2 T ;
X = Y +2 Z *1 T +3 E ;
3. Il est possible d’utiliser les parenthèses pour changer l’ordre d’évaluation :
X = (Y +1 Z) *2 T
4. Une variable peut figurer à gauche et à droite d’une affectation
X = 20 ;
X = X + 1 ;  21
On peut lire ça : X reçoit l’ancienne valeur de X + 1
5. Une variable ne peut figurer à droite d’une affectation que si elle a déjà une valeur.

N. Chenfour 5
Exemples :
1. on a 2 variable X et Y et on veut échanger leur valeur :
int X = 20, Y = 30 ;
on a besoin d’une 3ème variable Z :
int Z ;
en suite :
Z = X ;
X = Y ;
Y = Z ;
Remarque :
Attention, le langage C est sensible à la casse, càd : X différent de x, int # Int, …

Conversions implicites :
int X = 20.5 ;  20
char c = 65 ;  ‘A’
int x = ‘A’ ;  65
float x ;
x=1/2;0
Règle : une expression sur des entiers donne un résultat entier
Pour résoudre le problème, il suffit que l’une des valeurs soit un réel :
x = 1.0 / 2 ;  x = 1 / 2.0 ;  x = 1. / 2 ;  x = 1 / 2. ;  0.5
Pb. Si les opérandes sont des variables :
int a =1, b=2 ;
float x = a / b ;  0
Solution 1 :
float x = 1. * a / b;  0.5
Solution 2 : le Casting  Transtypage  Transformation de type explicitement
float x = (float)a ;
#include <stdio.h>
#include <conio.h>
void main() {
int a=1, b=2;
float x;
x = (float)a / b;
clrscr();
printf("%f", x);  0.5 ;
}

N. Chenfour 6
IV- Les Entrées/Sorties
4.1 Affichage :
Réalisé par l’intermédiaire de la fonction printf(…).
Syntaxe :
printf("chaîne de spécification de format", arg1, arg2, …)
Informations à afficher, de
type élémentaire qq (int,
float, char, …). On peut
Messages + descripteur de aussi fournir des
fromat constantes : 20, 30, ‘a’, …
Les descripteurs de format, on utilisera :
%d  pour afficher les entiers (int)
%f  pour l’affichage des réels (float)
%c  pour l’affichage des cractères (char).

Remarque 1 :
Dans la chaîne de spécification de format, on utilisera autant de spécificateurs de
format (%?) que d’arguments :
Exemple :

,
printf ("…..%d….%c….%f….%d…" arg1, arg2, arg3, arg4) ;

Si pour l’exemple on n’a pas utilisé le dernier (%d), alors arg4 ne sera pas affiché.
Remarque 2 :
Le type des arguments correspond à celui des spécificateurs de format : arg1 est
un entier, arg2 un char, arg3 un float et arg4 un int.

Remarque 3 :
Il existe cependant une possibilité de conversion automatique du type de données lors
de l’affichage à l’aide des descripteurs de format :
char c = ‘A’ ;
printf("%d", c) ;  65 (code ascii de ‘A’) ;
int a = 65 ;
printf("%c", a) ;  ‘A’ (caractère de code ascii de 65) ;
float x = 3.4 ;
printf("%d", (int)x) ;  3 (partie entière) ;
int i = 30 ;
printf("%f", (float)i ) ;  30.0000

Remarque 4 :
La chaîne de caractères peut comporter des caractères de contrôles :
\n : retour chariot ( le symbole \ avec le caractère suivant constitue un seule caractère).
\t : tabulation
\b : backspace (retour arrière)
\" : pour afficher des guillemets
\\ : pour afficher \

N. Chenfour 7
Remarque 5 :
La fonction printf peut être utilisée sans les arguments (arg1, arg2, …), son objectif
serait alors un simple affichage d’un message d’invitation (généralement utilisé avant un
scanf) :
printf("entrer un entier : ") ;
scanf("%d", &x) ;

Remarque 6 : Format d’affichage


Le Format d’affichage est un moyen utilisé pour préciser la taille des données à
afficher :
1. les entiers :
printf("%tailled", x) ;
avec taille est une constante qui définie la taille de la zone d’affichage en nombre de
caractères :
printf("%20d", x) ;
l’entier x sera affiché sur un emplacement de 20 caractères en complétant par des espaces
à gauche.

Si la taille n’est pas suffisante, elle est alors ignorée.

2. Les réels :
printf("%taille.ncavf", x) ;
avec taille est une constante qui définie la taille de la zone d’affichage en nombre de
caractères et ncav : le nombre de chiffre après la virgule.
printf("%20.2f", x) ;
l’entier x sera affiché sur un emplacement de 20 caractères en complétant par des espaces
à gauche, avec 2 chiffres après la virgule

1. Si la taille n’est pas suffisante, elle est alors ignorée.


2. la partie : taille peut ne pas être spécifiée :

printf("%.2f", x) ;

Remarque :
Si on veut éliminer la partie flottante dans l’affichage :
printf("%.0f", x) ;

Remarque :
Pour utiliser des couleurs lors de l’affichage, il faut utiliser la fonction : cprintf au lieu
de printf. Celle-ci a la même syntaxe d’utilisation.
Exemple :
#include <stdio.h>
#include <conio.h>
void main() {
clrscr();
system("cls");
textcolor(14);
system("COLOR 27");
textbackground(3);
printf("Bonjour");
clrscr();// pour donner la couleur de fond à tout l’écran
cprintf("un message en rouge\n");
getchar();
getch();
}

N. Chenfour 8
4.2 La saisie :
4.2.1 fonction scanf(…) :
Sa syntaxe ressemble à celle de la fonction printf avec 2 différences :
1. dans la chaîne, on utilise uniquement les descripteurs de format
2. les arguments sont précédés par le symbole & pour désigner leurs adresses.

scanf ("%d%c%f%d", &arg1, &arg2, &arg3, &arg4) ;

Remarque 1 :
Pour le cas de scanf() est nécessaire de respecter le format des argument à l’aide des
descripteurs de format.
Remarque 2 :
La fonction scanf n’est jamais utilisée pour afficher, donc jamais autre caractère que
les spécificateurs de format dans la chaîne du scanf.

4.2.2 fonction getchar() :

Elle peut être utilisée pour lire un caractère :


char c ;
c = getchar() ;
c’est équivalent :
char c ;
scanf("%c", &c) ;

Remarque :
On peut utiliser la fonction getchar() pour arrêter l’exécution du programme à une
position donnée, car getchar() attendra une touche (retour chariot) depuis le clavier. Dans ce
cas, on peut l’utiliser comme suit :
getchar() ;

4.2.3 Fonction getch() de <conio.h>


Remarque :
Les 2 fonctions scanf et getchar() attendent une validation par un retour chariot. Les
données en entrée sont alors chargées dans un tampon intermédiaire qui sera consommé par
ces deux fonctions :

scanf() getchar() getch()

Tampon intermédiaire de
lecture (RAM)

Clavier

N. Chenfour 9
La fonction getch() effectue UNE LECTURE AU VOL, càd directement depuis le clavier, en
ne passant pas par le tampon intermédiaire.
Autres caractéristiques :
1. pas besoin de valider par retour chariot
2. n’affiche pas le caractère tampon
3. même si le tampon est plein, la fonction getch() lit depuis le clavier
Les autres fonctions lisent depuis le tampon jusqu’à ce qu’il soit complètement consomé.

Exemple 1 :
#include <stdio.h>
#include <conio.h>

void main() {
int x, y;
char c;

clrscr();
printf("Entrer un entier : ");
scanf("%d", &x);

printf("Entrer un autre entier : ");


scanf("%d", &y);

printf("Entrer un caractère : ");


c = getch();
printf("%c\n", c);

printf("x = %d, y = %d, c=[%c]\n", x, y, c);


getch() ;
}

Exemple 2 :
#include <stdio.h>
#include <conio.h>

void main() {
int x, y;
char c;

clrscr();
printf("Entrer un entier : ");
scanf("%d", &x);

printf("Entrer un autre entier : ");


scanf("%d", &y); //flushall();// ou
getchar();
printf("Entrer un caractère : ");
scanf("%c", &c);

printf("x = %d, y = %d, c=[%c]\n", x, y, c);

getch();
}

N. Chenfour 10
V. Les Instructions de choix
5.1 L’instruction if :
Syntaxe :
- cas du if sans else :

if (condition) instruction ;
ou :
if (condition) {
instruction 1 ; Bloc d’instructions imbriqué
instruction 2 ;

}
Exemple :
#include <stdio.h>
#include <conio.h>

void main() {
float MHT, MTHT, TTVA=0.2, TVA, MT, Remise;
int Q;

clrscr();

printf("Entrer le Montant Hors Taxes : ");


scanf("%f", &MHT);

printf("Entrer la quantité : ");


scanf("%d", &Q);

MTHT = MHT * Q;
TVA = MTHT * TTVA;
MT = MTHT + TVA;

printf("Le Montant Total est : %10.2fDH\n", MT);

if (MT >= 2000) {


Remise = 0.05 * MT;
MT = MT - Remise;
printf("Remise = %.2fDH\n", Remise);
printf("Motant Total à payer : %.2fDH\n", MT);
}

getch();

- cas du if avec else :


if (condition) instruction ;
else une_autre_instruction ;
ou
if (condition) {
instruction 1 ;
...
}
else {
une_autre_instruction ;
...
}

N. Chenfour 11
5.2 Les Conditions :
Règles d’écriture des conditions :
- Une condition est toujours définie entre les 2 parenthèses :
if ( condition ) {
...
}
- On distingue entre les conditions simples (élémentaires) et les conditions
composées.
- Une condition élémentaire est une comparaison entre 2 valeurs, 2 variables, une
variable et une valeur ou généralement 2 expressions en utilisant l’un des
opérateurs de relation :
inférieur <
Inférieur ou égal <=
Supérieur >
Supérieur ou égal >=
Egal ==
Différent (not equal) !=
Exemple :
if (x < y)…
if (2*x+3 >= 3*y) …
Cas Particuliers :
1. Le true en C++ est représenté par toute valeur non nulle

if ( X ) ...

if ( X != 0 ) ...

2. Le false est représenté par 0 (une valeur nulle)



if ( !X ) ...

if ( X == 0 ) ...
Remarque :
L’opérateur de relation utilisé pour l’égalité est ==, à ne pas confondre avec le
symbole =.
On a ainsi :
if ( X = 20 ) ...

if ( (X = 20) != 0 ) …
qui est une superposition de 2 instruction : l’affectation + la comparaison : à la
suite de cette instruction, on sortira tjs avec X ayant la valeur 20, car = est un
opérateur d’affectation.

- Une condition composée est compose de 2 ou plusieurs comparaisons. Ainsi dire


que X est située entre a et b (a <= X <= b), revient à dire que (X est >= à
a) et (X <= à b). Ce qui nécessite l’utilisation de la notion d’opérateurs
logiques (ici, c’est le et logique)
 if ( a <= X && X >= b ) …

N. Chenfour 12
La liste des opérateurs logique est la suivante :

Le et logique (and) &&


Le ou logique (or) ||
Le non logique (not) !

- L’utilisation de parenthèses imbriquées n’est utile que pour lever l’ambiguïté


d’évaluation de la condition car le && est plus prioritaire que le ||. Les 2 moins
prioritaires que le !:
Exemple :

if ( X < 0 && Y > 2 || Z == 20 ) …



if ( (X < 0 && Y > 2) || (Z == 20) ) …
mais c’est différent par rapport à l’écriture :
if ( X < 0 && (Y > 2 || Z == 20) ) …

5.3 Les if imbriquées :


Il est possible d’imbriquer autant de fois que nécessaire des instructions if dans d’autre
instruction if ou dans leurs partie else :
if ( C1) {

if (C3) {

}

if (C4) {

}
else {

}
}
else if (C2) {

}
else {

if (C5) {

}

}

N. Chenfour 13
5.2 L’instruction switch :
Elle permet de réaliser autrement une séquence d’instructions if … else if …else if…,
dans le cas de test d’égalité sur une même variable de type ordinal (entier ou caractère).
if ( X == a ) {
T1 ;
}
else if (X == b) {
T2;
}
else if (X == c) {
T3;
}
else {
T4;
}

switch ( X ) {
case a:
T1;
break;
case b:
T2;
break;
case c:
T3;
break;
default:
T4;
}

Ceci est valable si:


1. X est de type ordinal : int, char, short int, …
2. a, b et c sont des constantes
3. a, b et c sont distinctes
Remarque dans le cas ou un même traitement (T3) devrait être exécuté si X à la valeur c ou d
ou e :
switch ( X ) {
case a:
T1;
break;
case b:
T2;
break;
case c:case d:case e:
T3;
break;
default:
T4;
}

N. Chenfour 14
VI. les Boucles
6.1 la boucle while :
C’est un if dont le traitement est répété tant que la condition est vérifiée. on sorira de
la boucle lorsque la condition n’a plus la valeur vrai. La syntaxe est la suivante :
while ( Condition ) {

}
Exemple 1 :
Calculer la première puissance de 2 >= à 1000 : chercher le p tq : 2n = p, le n étant incunu

int p = 1 ;
int n = 0 ;
while (p<1000) {
p = p * 2 ;
n ++ ;
}
Printf("2 puissance %d est = %d\n", n, p) ;

6.2 la boucle do … while :


Syntaxe :
do {
...
}
while ( Condition ) ;

La seule différence entre le while et le do…while est la position du test. Pour le while elle se
trouve au début, alors que pour le do…while elle est à la fin. Le résultat de ceci est que : pour
le while le traitement risque de ne jamais être exécuté si la condition n’est pas vérifiée au
début alors que pour le cas de do…while le traitement s’exécute au moins une fois, car le test
est effectué après le traitement. En dehors de cette contrainte les 2 boucles sont équivalentes.
L’exemple précédent peut donc être réalisé avec la boucle do…while.

int p = 1 ;
int n = 0 ;
do {
p = p * 2 ;
n ++ ;
}
while (p<1000) ;
Printf("2 puissance %d est = %d\n", n, p) ;

Remarques :
1. Ces 2 boucles sont parfaitement adaptées au cas où on ne connaît pas au préalable
le nombre de répétition
2. Les 2 boucle peuvent tout de même être utilisées si on connaît le nombre de
répétition :

N. Chenfour 15
Exemple 2 : afficher les entiers de 1 à 10 :
int i = 1 ; //initialisation
while (i<=10) {// le test
printf("%d\n", i); //Le traitement à répéter
i++ ; // l’incrémentation
}
Exemple 3 : afficher les nombres pairs entre 0 et n :
scanf("%d", &n) ;
int i = 0 ; //initialisation
while (i<=n) {// le test
printf("%d\n", i); //Le traitement à répéter
i = i + 2 ; // l’incrémentation
}
Exemple 4 : afficher les nombres pairs entre n et m :
int n, m , p, i ;
scanf("%d", &n) ;
scanf("%d", &m) ;
//permuter si n>m  on aura en résultat n < m
if (n>m) {
p = n ;
n = m ;
m = p ;
}
if (n%2==0) {// n est paire
// on commence par n
i = n; //initialisation
}
Else {// n est impaire
// on commence par n + 1
i = n + 1; //initialisation

}
while (i<=m) {// le test
printf("%d\n", i); //Le traitement à répéter
i = i + 2 ; // l’incrémentation
}
Exemple 5 : lire une réponse saisie au clavier qui doit être obligatoirement ‘o’, ‘n’, ‘O’ ou ‘N’ :
do {
printf("Encore une note ? ");
reponse = getch();
printf("%c\n", reponse);
if (reponse!='o' && reponse!='O'
&& reponse!='n' && reponse!='N') {
printf("Réponse Incorrecte!");
}
}
while (reponse!='o' && reponse!='O'
&& reponse !='n' && reponse!='N');

N. Chenfour 16
Exemple 6 : Exercice : afficher les nombres premiers entre n et m.

6.1 la boucle for :


Syntaxe :
for (initialisation ; test ; incrémentation|décrém) {
traitement à répéter
}
On remarque que les 3 instructions d’initialisation, de test et d’incrémentation (ou de
décrémentation) sont réunies dans la même ligne qui constitue la syntaxe de for. (c’est la
différence par rapport aux 2 autres boucles).
L’exemple 4 peut ainsi être réalisé à l’aide de for comme suit :
int n, m , p, i ;
scanf("%d", &n) ;
scanf("%d", &m) ;
//permuter si n>m  on aura en résultat n < m
if (n>m) {
p = n ;
n = m ;
m = p ;
}
if (n%2 !=0) {// n est impaire
n = n + 1; //initialisation
}
for (i=n; i <= m; i = i + 2 ) {// initialisation + test + incrémentation
printf("%d\n", i); //Le traitement à répéter
}

Remarques :
1. Il y a une différence entre le for du langage Pascal est celui du langage C : avec le for
du langage Pascal, on ne peut utiliser for que si on connaît le nombre de répétition à
l’avance. Le for du langage C est plus général et peut être utilisé même si on ne
connaît pas le nombre de répétition.
2. On va tout de même réserver le for pour des cas où l’on connaît le nombre de
répétition à l’avance.

N. Chenfour 17
Chapitre 2 :
Procédures et Fonctions
N. Chenfour

2.1 Définitions
Une procédure ou une fonction (appelée aussi sous programme) est un bloc complet
d’instructions possédant un nom et pouvant être exécuté plusieurs fois par l’intermédiaire du
nom qui lui est attribué. On appelle cela : un appel à la procédure ou à la fonction. Ainsi tout
bloc de programme pouvant être réutilisé plusieurs fois dans le même programme est candidat
à être transformé en un sous programme. Le nom du sous programme est un identificateur :
suite de caractères alphanumériques ou blanc souligné ( _ ), qui commence par un caractère
alphabétique.

Résultats :
- Lisibilité du code
- Code optimal
- Réutilisabilité de traitement déjà réalisé.
On distingue entre une procédure et une fonction par les conditions suivantes :
- Une procédure réalise un traitement sans valeur de retour. Càd : la procédure sera
utilisée pour obtenir un comportement bien déterminé :
Exemple :
clrscr() ;  le comportement c’est effacer l’ecran
textcolor(couleur) ;  permet de changer la couleur de l’écriture
gotoxy(x, y) ;  permet de déplacer le curseur d’écriture vers un endroit donné
de l’écran.

- Une fonction est comme une procédure, réalise un traitement mais à la fin elle
calcule et retourne une valeur pouvant être exploitée par l’appelant.
Exemple :
X = cos(Y) ;  calcule et retourne la valeur du cosinus de y.
C = getch() ;  attend qu’une touche soit tapée au clavier et retourne la
valeur de cette touche.
On remarque que l’appel à une fonction est réalisé dans une EXPRESSION :
c'est-à-dire que les fonctions sont utilisées comme des variables ou des constantes : elle
peuvent figurer à droite d’une affectation par exemple.
Une procédure est par contre utilisée comme une INSTRUCTION complète.

- De ce fait une fonction est une procédure qui en plus d’être une procédure, elle
retourne une certaine valeur calculée dans son corps.
- Une fonction peut alors être appelée comme une procédure : dans le cas où on n’a
pas besoin de sa valeur de retour.
Exemple :
getch() ;  elle bloque l’affichage en attendant qu’une touche soit tapée. Sa
valeur de retours (le caractère tapé) n’est pas retenue.

N. Chenfour 18
2.2 Définition et utilisation d’une procédure
Une procédure est définie de la manière suivante (généralement avant le main(), mais
elle peut être définie aussi après le main() ). A remarquer que le main() est aussi une
procédure.

void NomDeLaProcedure() {
Instructions de la procédure ;

}
void est le mot clé utilisé pour la définition d’une procédure.

Appel à une procédure :


L’appel à une procédure est réalisé de la manière suivante :
Void main() {

NomDeLaProcedure() ;

}

Exemple :
void AfficherMessage() {
printf("entrer une valeur : ") ;
}
Définition de la
void main() { procédure

AfficherMessage() ; Les appels à la
… procédure
AfficherMessage() ;

}

Remarques :
1. Une procédure ne peut accéder que :
- à des variables déclarées en dehors de la procédure (mais avant). Celles-ci sont
appelées des variables globales.
- à des variables déclarées à l’intérieur de la procédure : celles-ci sont appelées des
variables locales (à la procédure)
Exemple :

int x = 20 ; // Variable Globale


void incrementer() {
int pas = 10 ; // variable locale
x = x + pas ;
}
void main() {
incrementer() ;
printf("%d\n", x ) ; // possible
printf("%d\n", pas) ; // impossible
}

N. Chenfour 19
2. Une variable locale n’a le droit d’être utilisée que dans la procédure ou dans la
fonction où elle est déclarée.
3. Une variable locale peut porter le nom d’une variable globale, dans ce cas, la
procédure ne voit que la variable locale (celle-ci cache la variable globale).
4. 2 procédures (ou fonctions) peuvent utiliser des variables locales de même nom.
5. Une procédure telle que définie plus haut est appelée « procédure sans
paramètres ». Il s’agit d’une restriction de fonctionnalités au niveau des
procédures : c’est une limitation de la réutilisabilité : ainsi par exemple la
procédure « incrementer » ne sait incrémenter que la variable globale x. si on a une
autre variable (y) à incrémenter, on ne peut pas réutiliser la procédure
« incrementer ». D’où la nécessité souvent de réaliser des procédures « avec
paramètres ». Les paramètres sont des variables sur lesquelles la procédure peut
réaliser sont traitement. Et à chaque appel, on communique à la procédure les
valeur de ces paramètres : les valeurs (ou variables) communiquées à la procédure
sont appelées des « Arguments d’appel ».
Exemple :
void AfficherSomme(int x, int y) { // x et Y sont des
paramètres
int s = x + y ;
printf("somme = %d\n", s) ;
}

L’appel à cette procédure peut être réalisé comme


suit :

Void main() {
int a, b, x, y ;// variables locales au main()
scanf("%d%d", &a, &b) ;
AfficherSomme(a, b) ; // a, b, 20, 45, 3, x et y
AfficherSomme(20, a) ;// sont des arguments d’appel
AfficherSomme(b, 45) ;
AfficherSomme(2, 3) ;
scanf("%d%d", &x, &y) ;
AfficherSomme(x, y) ;
}

6. Lors d’un appel à une procédure avec paramètres les valeurs des arguments sont
affectées aux paramètres respectivement.

N. Chenfour 20
Dans le cas général :

void NomDeLaProcedure(type1 p1, type2 p2, ..., typeN pN) {


Instructions de la procédure ;

}

Appel à la procédure :
L’appel à une procédure est réalisé de la manière suivante :
Void main() {

NomDeLaProcedure(a1, a2, ..., aN) ;

}

7. Dans ce cas :
p1  a1,
p2  a2,

pN  aN.
Ensuite la procédure travaille sur les paramètres dont les valeurs ont été
communiquées par les arguments.
8. Lors d’un appel à une procédure avec paramètres il faut utiliser un nombre
d’arguments égal au nombre de paramètre.
9. Il faut aussi respecter le type des paramètres par l’intermédiaire des arguments.

2.3 Définition et utilisation d’une fonction


Une Fonction est une « procédure » qui calcule et retourne une valeur par
l’intermédiaire de l’instruction return .

typeDeRetour NomDeLaFonction(type1 p1,..., typeN pN) {


Instructions de la procédure ;

return valeur ;
}
Avec :
typeDeRetour est un type de données (int, char, float, …) qui correspond au type de la
valeur retournée par l’instruction return.
Appel à la fonction :
L’appel à la fonction peut être est réalisé de la manière suivante :
Void main() {

Resultat = NomDeLaFonction(a1, a2, ..., aN) ;

}

N. Chenfour 21
2.3 La Récursivité :
2.3.1 Définition
Elle consiste en une fonction ou une procédure qui fait appel à elle-même. Ce qui
permet de répéter un traitement un nombre de fois qq. La récursivité permettra donc de
remplacer les boucles. Tout ce qu’on peut faire avec une boucle, on pourra le réaliser à l’aide
de la récursivité (l’inverse n’est pas forcément vrai)
Il est à noter qu’un traitement récursif utilise généralement moins de variables et moins
d’instructions. Il est donc plus rapide qu’un traitement itératif.
Néanmoins, la récursivité est plus coûteuse en terme d’espace mémoire nécessaire.

Cas du procédure :
void p(…) {

p(…) ;

}
Ou encore pour une fonction :
type f(…) {

X = f(…) ;
ou
return f(…) ;

}

Remarque :
Une fonction ou procédure récursive doit obligatoirement disposer d’un test d’arrêt,
sinon on aura une boucle infinie.
Exemples :
- Cas d’une procédure :
void afficher(int N) {
if (N>=0) {
printf("%d\n", N) ;
afficher(N-1) ;
}
}
Ou encore :
void afficher(int N) {
printf("%d\n", N) ;
if (N>0) afficher(N-1) ;
}
Soit une boucle :
for (int i=0 ; i<N ; i++) {
traitement;
}

N. Chenfour 22
On pourra l’écrire une manière recursive:
void Repeter(int N) {
if (N>=0) {
traitement ;
}
}

Cas d’une Fonction :


long int factoriel(int N) {
if (N == 0) return 1 ;
else return N * factoriel( N-1 ) ;
}

2.3.2 Différents types d’appels récursifs :


On peut distinguer entre 2 types d’appels récursifs :
1- Traitement avant appel  l’exécution du traitement est réalisée dans l’ordre normal :
void P(int i) {

Traitement(i) ;
P(i+1) ;
}
 Résultat de l’appel P(0) :
Traitement(0) ;
Traitement(1) ;
Traitement(2) ;

void afficher(int i, int N) {
printf("%d, ", i) ;
if (i<=N) afficher(i+1, N) ;
}
Afficher(0, 5)  0, 1, 2, 3, 4, 5,

2- Appel avant le traitement  l’exécution du traitement est réalisée dans l’ordre


inverse :
void P(int i) {

P(i+1) ;
Traitement(i) ;
}
 Résultat de l’appel P(0) :

Traitement(2) ;
Traitement(1) ;
Traitement(0) ;

void afficher(int i, int N) {


if (i<=N) afficher(i+1, N) ;
printf("%d, ", i) ;
}
Afficher(0, 5)  5, 4, 3, 2, 1, 0,

N. Chenfour 23
Un autre exemple :
void binaire(int N) {
if (N>=0) {
binaire(N/2) ;
printf("%d", N%2) ;
}
}
2.3.3 La récursivité croisée
Cela consiste à définir une suite de procédures et/ou de fonctions dont chacune
appellera l’autre d’une manière circulaire :

Pn P1
P2

P3
Exemple :
U(n) = (V(n) + V(n-1) ) / 2
U(0) = 1
Avec :
V(n) = 2 * U(n-1)
V(0) = 2

Dans ce cas U appelle V et V appel U  Récursivité croisée.


Or une fonction ne peut appeler en langage C qu’une fonction définie plus haut
Solution : la notion de PROTOTYPE (ou entête) d’une procédure ou une fonction :
Il s’agit de définir la fonction avec son entête sans préciser le corps de la fonction.
Une telle fonction devient alors connue et pourra être :
1- appelée par toutes les fonctions définies plus bas
2- son corps pourra être définie n’importe où dans le programme.

Exemple :
float U(int n) ; ou float U(int) ; // déclaration
float V(int n) ; ou float V(int) ; // déclaration
//définition des fonctions :
float U(int n) {
if (n==0) return 1;
else return (V(n) + V(n-1))/2;
}
float V(int n) {
if (n==0) return 2;
else return 2 * U(n-1);
}

N. Chenfour 24
2.4 Définition d’un type fonction
Cela permet d’avoir dans le programme des variables de type fonction qui peuvent se
faire affecté des noms de fonctions préalablement définies.
On a besoin dans ce cas de définir un nouveau type. On utilisera donc le mot clé : typedef :
Utilisé généralement comme suit :
typedef TypeConnu TypeADefinir ;
le TypeADefinir devient un nouveau type connu.
Exemple 1 :
Définition d’un Alias à un type existant :
typedef int Integer ;
 pour définir des entier on peut faire :
Integer x, y ;

Exemple 2 :
Dans notre cas nous utiliserons le mot clé typedef pour définir un type fonction :
Syntaxe :
typedef TypeDeretour (* NomDuType)(…patamètres…) ;
Exemple 1 :
typedef void (* Operation)(int &) ;
Operation est le type qui représente toutes les procédures avec un paramètre de type entier et
dont le passage se fait par référence.

void inc(int &x) {


x++ ;
}

void dec(int &x) {


x-- ;
}

Operation p ;
void main() {
p = inc ;
int x = 20 ;
p(x) ;  21

p = dec ;
x = 20 ;
p(x) ;  19
}

N. Chenfour 25
Exemple 2 :
typedef float (* Operation)(float, float) ;
Operation est le type qui représente toutes les procédures avec un paramètre de type entier et
dont le passage se fait par référence.

float plus(float x, float y) {


return x + y ;
}

float moins(float x, float y) {


return x - y ;
}

float fois(float x, float y) {


return x * y ;
}

float diviser(float x, float y) {


return x / y ;
}

Operation op(char c) {
Operation p ;
Switch (c) {
case '+' : p = plus; break;
case '-' : p = moins; break;
case '*' : p = fois; break;
case '/' : p = diviser; break;
}
return p;
}

void main() {
printf("entrer l’opération(+|-|/|*) : ") ;
char c = getch() ;
Operation p = op(c) ;
printf("entrer les données : ") ;
float x, y, r ;
scanf("%f%f", &x, &y) ;
r = p(x, y) ;
}

2.5 Les bibliothèques :


Les procédures ou fonctions utiles peuvent être enregistrées dans des fichiers séparés
d’extension .H ou .CPP (« compilable » séparément). Ces modules peuvent être réutilisés
dans les différents programmes après leur inclusion à l’aide de l’instruction :
#include "bib01.H"
Avec bib01 une bibliothèque séparée.

N. Chenfour 26
N. Chenfour 27
Chapitre 3 :
Structures de Données
Enregistrements – Tableaux – Chaînes de
caractères
Par N. Chenfour

3.1 Les Enregistrements / Structures


3.1.1 Définition :
Un enregistrement est un type de données qui permet de décrire une entité composée.
Celle-ci sera définie par l’intermédiaire d’un ensemble de descripteurs appelés propriétés ou
champs (de l’enregistrement).
Un enregistrement appelé aussi structure est défini à l’aide de l’une des 2 manières suivantes :

struct NomDeStructure {
liste des champs

} liste de variables ;
Ou encore :

typedef struct {

liste des champs

} NomDeStructure ;
La déclaration des variables pourra alors être réalisée ultérieurement :

NomDeStructure liste des variables ;

Exemple :
Définition du type enregistrement :
typedef struct {
int x, y ;
int couleur ;
} Point ;

Déclaration des vaiables :

Point p1, p2 ;

N. Chenfour 28
3.1.2 Accès aux champs :
On utilisera le sélecteur « . » : enreistrement.champ
Exemple :
p1.x = 20 ;
p1.y = 30 ;

3.1.2 Lecture/ecriture des eregistrements


L’affichage ainsi que la saisie d’un enregistrement sont réalisés champ par champ. Dans ce
cas on pourra définir des fonctions permettant de réaliser ces 2 opérations.
Par exemple :
void LirePoint(Point &p) {
printf("entrer X : ") ;
scanf("%d", &p.x) ;
printf("entrer Y : ") ;
scanf("%d", &p.y) ;
}

void afficherPoint(Point p) {
printf("(%d , %d)\n", p.x, p.y) ;
}

Remarque :
Un champ d’un enregistrement peut lui aussi être de type enregistrement :
typedef struct {
int j, m, a ;
} Date ;

typedef struct {
int code ;
char nom[20] ;
Date dn ;

} Personne ;

L’accès à l’information de date complète est réalisé comme suit :


Personne pers ;
pers.dn.j = 20 ;
pers.dn.m = 12 ;
pers.dn.a = 1990 ;

Dans ce cas aussi, pour lire ces informations on le fait champ par champ :
scanf("%d", &pers.dn.j) ;
Remarque :
L’affectation entre enregistrements de même type est possible :
Exempe : Personne p1, p2;
p1 = p2

N. Chenfour 29
3.2 Les Tableaux
3.2.1 Définition
Un tableau est un ensemble de données de même type, stockées en mémoire de
manière contiguë, et accessible à l’aide d’un seul nom de variable en utilisant le numéro
d’ordre de chaque donnée, appelé indice.
La définition d’un type tableau est réalisée de la manière suivante :

typedef TypeDesEléments NomDuTypeTableau [Taille] ;

La déclaration est ensuite réalisée de la manière suivante :


NomDuTypeTableau VariableTableau ;
On peut aussi déclarer sans définir le type tableau :

TypeDesEléments VariableTableau [Taille] ;

Où taille indique le nombre maximum d’éléments du tableau.


Exemple :

int T1[20] ;
float T2[10] ;
Point T3[30] ;
Personne T4[50] ;

Remarques :
1. Un tableau peut être de n’importe quel type en particulier, on pourra avoir un
tableau d’enregistrement  chaque élément du tableau est un enregistrement.
2. Un tableau peut être un champ d’un enregistrement :
Exemple :
typedef struct {
char nom[20] ;
int x, y ;

} Option ;

typedef struct {
Option TO[20] ;
char type ;
int couleurs ;

} Menu ;

N. Chenfour 30
3.2.2 Accès aux éléments d’un tableau
L’accès aux éléments d’un tableau est réalisé par l’intermédiaire des crochets en
utilisant l’indice de l’élément (le numéro) : VariableTableau[indice]

Avec indice pouvant prendre ces valeurs de 0 jusqu’à Taille du tableau - 1.


Exemple1 :
T1[0] = 20 ;
T3[1].x = 45 ;
T3[1].y = 30 ;
Exemple2 :
Menu M ;
M.TO est tableau d’options
M.TO[i] est une option
M.TO[i].x = 1 ;

3.2.3 Lecture/Ecriture des tableaux


Un tableau doit être affiché élément par élément et lu élément par élément.
Exemple 1 :
void Afficher(int T[20], int N) {
for (int i =0 ; i<N ; i++)
printf("T[%d] = %d\n", i, T[i] );
}
L’appel est réalisé comme suit :

Afficher(T1, 10) ;

Exemple 2 :

void AfficherTableauDePoints(Point T[30], int N) {


for (int i =0 ; i<N ; i++)
printf("T[%d] = (%d, %d) \n", i, T[i].x, T[i].y );
}
L’appel est réalisé comme suit :

Afficher(T3, 10) ;

Remarques :
1. Lorsqu’on réserve un tableau de Taille T, on pourra utiliser uniquement N cases
avec N < T
2. dans ce cas toute procédure ou fonction qui reçoit en paramètre un tableau doit
aussi avoir un autre paramètre : c’est le nombre d’élément effectif du tableau (N)
3. Le passage des tableaux en paramètres est toujours réalisé par référence : Le nom
du tableau ( T ) correspond à l’adresse de début de stockage des élément du tableau
(l’adresse de T[0] ).

N. Chenfour 31
Exemple :
void LireTableau(int T[20], int N) {
for (int i=0 ; i<N ; i++) scanf("%d", &T[i]) ;
}

3.2.4 Initialisation d’un tableau

Type NomDuTableau [Taille] = { v1, v2, … } ;

Exemple :

int T[5] = {34, 67, 45, 30, 9} ;

3.3 Tableaux à plusieurs dimensions :


3.3.1 Définition

type NomDuTableau[TD1][TD2]… ;
avec TD1 est la taille de la 1ère dimension, TD2 de la 2ème ….

Exemple : Matrice

int M[20][30] ;
 Définition d’une matrice 20 lignes et 30 colonnes (la notion de ligne et de colonne
n’est qu’arbitraire)
3.3.2 Accès aux éléments
L’accès aux éléments est réalisé comme suit :
NomDuTableau[i][j][k]...

Dans l’exemple l’accès à une cellule est réalisé de la manière suivante :

M[i][j]

Remarque :
Pour parcourir une matrice, il faut parcourir les lignes et les colonnes  2 boucles : la
première boucle porte sur les lignes, la deuxième (imbriquée dans la première) permettra de
parcourir les colonnes.
Exemple :
void AfficherMatrice(int M[20][30], int NL, int NC) {
for (int ligne=0 ; ligne < NL ; ligne ++) {
for (int colonne = 0 ; colonne < NC ; colonne ++)
printf("%5d", M[ligne][colonne]) ;

printf("\n") ;
}
}

N. Chenfour 32
3.3.2 Initialisation
L’initialisation des matrices est réalisée de la même manière que pour le cas des tableaux à
une dimension :

Exemple : Cas des matrices :

int M[3][4] = {
{ 1 , 3 , 4 , 2 } ,
{ 0 , 9 , 5 , 6 } ,
{ 1 , 7 , 8 , 3 }
}
Correction Exercices :
#include <stdio.h>
#include <conio.h>

void insert(int x, int pos, int T[20], int &N) {


for (int i=N-1; i>=pos; i--) T[i+1] = T[i];
T[pos] = x;
N++;
}

void remove(int pos, int T[20], int &N) {


for (int i=pos + 1; i<N; i++) T[i-1] = T[i];
N--;
}

void print(int T[20], int N) {


for (int i=0; i<N; i++) printf("T[%d] = %d\n", i, T[i] );
}

void main() {
int T[20] = {1, 2, 3, 4, 5, 6, 7};
int N = 7;
clrscr();
insert(1000, 2, T, N);
print(T, N);
remove(3, T, N);
print(T, N);
getch();
}

N. Chenfour 33
Les Pointeurs
N. Chenfour

1- Une variable statique est une variable pour laquelle la mémoire est associée une fois
pour toutes lors de la compilation
int X ;
X = 20 ;
2- Une variable dynamique (ou pointeur) est une variable associée à une zone mémoire
d’adresse, cette zone mémoire doit contenir l’adresse de la zone mémoire de travail.

int *P ;

X
Contenu
Créée explicitement
(1) lors de l’exécution
par malloc
(2)
P ad Contenu

3- Le contenu du pointeur (P) est noté : *P


*P = 20 ;
4- Cette dernière instruction n’est valable que si P pointe sur une adresse mémoire valide.
5- L’Adresse Mémoire valide peut être :
- (1) Celle d’une variable existante :
P = &X ; se lisant : P égale l’ADRESSE de X
- (2) Une nouvelle adresse d’une nouvelle zone mémoire créée à l’aide de la
fonction malloc, qui a comme paramètre la taille nécessaire pour stocker le
contenu.
P = (int *) malloc (sizeof (int) ) ;
Retourne la taille (en
octets) du type ou de la
Casting = Transtypage variable en paramètre
Car malloc retourne un (void *)
Exemple 01:

void exp01() {
int x = 20;
int *p; // un pointeur
//faire pointer le p sur un espace existant :
p = & x;
printf("*p = %d\n", *p);
*p = 300;
printf("x = %d\n", x);
x = 768;
printf("*p = %d\n", *p);

N. Chenfour 34
Exemple 02:

void exp03() {
int * p;
p = (int *)malloc(sizeof(int));
*p = 345;
printf("le contenu de p est = %d\n", *p);
}

6- Parmi les résultants de la notion de pointeur est le passage par adresse :

void inc(int *P) { Le paramètre = Le Pointeur de type (int *)


(*P)++ ;
}
 P = &a
On incrémente le contenu
Dans l’appel :

int a ; // l’argument d’appel


inc (&a) ;  on appelle par l’adresse de a.  &a est de type (int *).

Exemple 03:

void inc1(int p) { //passage par valeur : p = a;


p++;
}

void inc2(int &p) { // passage par référence p = &a


p++;
}

void inc3(int *p) { // passage par adresse p = &a


printf("p = %d\n", p);
(*p)++;
}

void exp02() {
int a = 20;
printf("&a = %d\n", &a);
inc3(&a); // &a est de type (int *)
printf("a = %d\n",a);
}

7- Un autre résultat de l’utilisation des pointeurs est la possibilité de créer un tableau


dynamique qui est une séquence de cases mémoire adjacentes dont la première est
pointée par le pointeur :

int *p ;
p = (int *)malloc(sizeof (int) * 5 );

 création d’un tableau de 5 éléments.

N. Chenfour 35
1er élément  *p  p[0]
p ad p++
; p++ 2ème élément  p[1]  p++ ; *p
; 3ème élément

4ème élément

5ème élément

Exemple 04:

void exp04() {
int * p;
p = (int *)malloc(sizeof(int)*10);
for (int i=0; i<10; i++) p[i] = i*2;

for (i=0; i<10; i++)


printf("le p[%d] = %d\n", i, p[i]);
}

8- Dans ce cas l’incrémentation du pointeur p se fait par pas = la taille de l’élément (le
contenu).

9- La notation p[i] est valable  accéder à l’élément N° i

10- Sachant que :

p[0] = *p = * (p + 0)

 c’est le 1er élément

Exemple 05:

void exp05() {
int * p;
p = (int *)malloc(sizeof(int)*10);
for (int i=0; i<10; i++) p[i] = i*2;

int * q;// un pointeur de lecture


q = p;

for (i=0; i<10; i++) {


printf("le p[%d] = %d\n", i, *q);
q++;
}
}

N. Chenfour 36
11- Donc :

p[i] = *(p+i)

Exemple 06:

void exp06() {
int * p;
p = (int *)malloc(sizeof(int)*10);
for (int i=0; i<10; i++) p[i] = i*2;

for (i=0; i<10; i++) {


printf("le p[%d] = %d\n", i, *(p+i));
}
}

12- Cas particulier : les tableaux dynamiques de char.

char * s ;

13- Ce sont alors des chaînes de caractères dynamiques

Exemple 07:

void exp07() {
char * s;

s = (char *)malloc(4);
strcpy(s, "abc");
printf("s = %s\n", s);

free(s);

s = (char *)malloc(11);
strcpy(s, "0123456789");
printf("s = %s\n", s);
}

14- Elles peuvent être gérées de la même manière que les chaînes de caractère de longueur
fixe : strcpy, strlen, strstr,…
15- Remarque : une zone mémoire p allouée par malloc doit être libérée par free(p).

N. Chenfour 37
Exemple 08:

int longueur1(char *s) {


int l = 0;
while (s[l]!=0) l++;
return l;
}

int longueur2(char *s) { // solution basée sur l’arithmétique des pointeurs


char *p = s ;
while ( *p != 0) p++;
return (p-s);
}

void exp08() {
char s1[20];
strcpy(s1, "adb");
int l = longueur1(s1);
printf("longueur de s1 = %d\n", l);

char *s2;
s2 = (char *)malloc(11);
strcpy(s2, "0123456789");
l = longueur1(s2);
printf("longueur de s2 = %d\n", l);
}

N. Chenfour 38
Les Fichiers En Langage C
Fonctions de Haut niveau <stdio.h>
I- Schéma d’utilisation d’un fichier
1- Déclaration d’un identificateur de fichier (Nom logique du fichier)
2- Ouverture ou création
3- Séquence d’opérations de lecture, écriture et recherche
4- Fermeture du fichier

II- Déclaration
Syntaxe :
FILE * Identificateur_de_fichier ;
Exemple :
FILE *f, *g; //déclaration de deux identificateurs de fichiers f et g.

III- Ouverture
Syntaxe :
Identificateur_de_fichier = fopen (Nom_physique_du_fichier, Mode_ouverture) ;
- Le nom physique du fichier est une chaîne de caractère spécifiant le nom (et
éventuellement le chemin) du fichier à ouvrir ou à créer.
- Le mode d’ouverture est une chaîne de caractère qui précise le mode d’ouverture du
fihier. Il en existe deux types :
# En Lecture, Ecriture, Ajout, Création, ou Mise à jour
# En mode Texte ou en mode Binaire.
Le tableau suivant montre les différentes possibilités :
Mode Description
r Ouverture en mode lecture. Le pointeur de lecture est positionné au début du fichier.
Si le fichier n’existe pas fopen retourne NULL.
w Ouverture en mode Ecriture. Si le fichier existe déjà son contenu et écrasé, sinon le
fichier est crée.
a Ouverture en mode Ajout. Si le fichier n’existe pas déjà il est crée. S’il existe, après
ouverture le pointeur de fichier est positionné à la fin pour ajout.
r+ Ouverture de fichier pour mise à jour (lecture/écriture). Le pointeur de lecture est
positionné au début du fichier. Si le fichier n’existe pas fopen retourne NULL.
w+ Création pour mise à jour. Si le fichier existe déjà son contenu est écrasé.
a+ Ouverture pour Mise à jour en fin de fichier. Si le fichier n’existe pas déjà il est crée.
b Ouverture en mode Binaire.
t Ouverture en mode Texte. C’est l’option par défaut si on ne précise rien.
Exemples :
FILE *f, *g, *h ;
Char NF[80] = "C:\\REP\\Resultat.dat"
f = fopen("A:\\Test01.txt", "r") ;
g = fopen(NF, "wb") ;
h = fopen("Test.txt02", "r+t") ;

N. Chenfour 39
IV- Fonctions de manipulation
IV.1 Fonctions de Lecture d’un fichier Texte
IV.1.1 Lecture par fscanf
Syntaxe :
int fscanf(f, Format, &V1, &V2, …);
La fonction retourne le nombre d’arguments lus. Elle retourne EOF (valeur –1) en fin
de fichier et 0 si un champs n’est pas lu correctement.
Exemple :
Char S[20] ;
int N ;
float R ;
fscanf(f, "%s%d%f", S, &N, &R) ;
// lecture de tout le fichier mot par mot :
while ( (fscanf(f, "%s", mot) )> 0) printf("%s\n", mot) ;
IV.1.2 Lecture ligne par ligne : fgets
Syntaxe :
char * fgets(char *S, int N, FILE *f);
Permet de lire N caractères de la ligne en cours sans passer à la ligne suivante. Si la
ligne contient moins de N caractères, toute la ligne et lue et un caractère 10 et ajouté à la fin
de la chaîne lue. La fonction retourne NULL en fin de fichier.
Exemple :
// lecture de tout le fichier ligne par ligne :
Char Ligne[256];
while ( (fgets(Ligne, 250, f))!= NULL) printf("%s", Ligne);
IV.1.3 Lecture caractère par caractère : fgetc ou getc
Syntaxe :
int fgetc(FILE *f); // ou encore :
int getc(FILE *f);
Elles retourne le caractère lu et si fin de fichier, elle retourne EOF.
Exemple :
// lecture de tout le fichier caractère par caractère :
Char c;
while ( (c = fgetc(f))!= EOF) printf("%c", c);
IV.2 Fonctions d’écriture dans un fichier Texte
IV.2.1 Ecriture par fprintf
Syntaxe :
int fprintf(f, Format, V1, V2, …);
Exemple :
fprintf(f, "%s | %10.2f | %10d \n", Produit, Prix, Qt) ;
IV.2.2 Ecriture chaîne par chaîne : fputs
Syntaxe :
int fputs(const char *S, FILE *f);
N’ajoute pas de retour chariot dans le fichier.
Exemple :
char *T[] = {"Ecran ","Clavier", "imprimante", "souris",
"scanner"} ;
for(int i=0; i<5 ; i++) {
fputs(T[i],f);
fprintf(f, "\n") ;
}

N. Chenfour 40
IV.2.2 Ecriture caractère par caractère : fputs
Syntaxe :
int fputc(int c, FILE *f);
Exemple :
char c ;
while ((c = getch()) != 27) fputc(c, f) ;
IV.3 Fonctions de Lecture d’un fichier Binaire
IV.3.1 Lecture par Blocs : fread
Syntaxe :
unsigned int fread (void * Ptr, unsigned int T, unsigned int N, FILE *f);
Lit à partir du fichier N blocks de taille T chacun et les met dans la zone mémoire
pointé par la variable Ptr. La fonction fread retourne le nombre de block effectivement lus. En
fin de fichier la fonction retourne 0 (0 blocks lu).
Exemple 1 :
float R ;
fread(&R, sizeof (float), 1, f) ;
Exemple 2 :
Char S[256];
int k = fread(S, sizeof(char), 255, f) ;
S[k] = 0 ; //ajouter le terminateur de chaîne car il n’est pas
ajouté par la fonction fread.
Exemple 3 :
struct STR {
int x, y ;
float r ;
char c ;
} V ;
fread(&V, sizeof(STR), 1, f) ;
Exemple 4 :
// lecture block par block d’un fichier d’entiers :
int T[1000] , k;
k = fread(&T, sizeof(int), 1000, f) ;
while (k>0) {
for(int i=0 ; i<k ; i++) printf("%d,",T[i]) ;
k = fread(&T, sizeof(int), 1000, f) ;
}
IV.3.2 Lecture entier par entier : getw
Syntaxe :
int getw(FILE *f) ;
Lit le prochain entier à partir du fichier binaire f et le retourne. Cela suppose que le
fichier est constitué d’entiers.
Exemple :
int x ;
x = getw(f) ;
printf("%d\n",x) ;
IV.4 Fonctions d’Ecriture dans un fichier Binaire
IV.4.1 Ecriture par Blocs : fwrite
Syntaxe :
unsigned int fwrite (void * Ptr, unsigned int T, unsigned int N, FILE *f);
Ecrit dans un fichier binaire N blocks de taille T chacun pointés par la variable Ptr. La
fonction fwrite retourne le nombre de block effectivement écrits.
Exemple 1 :

N. Chenfour 41
float R[100] ;
int N ;
scanf("%d",&N) ;
for(int i=0; i<N; i++) scanf("%f",&R[i]) ;
fwrite(&R, sizeof (float), N, f) ;
IV.4.2 Ecriture entier par entier : putw
Syntaxe :
putw(int M, FILE *f) ;
Ecrit l’entier M dans un fichier binaire f.
Exemple :
int x = 20 ;
putw(x,f) ;
IV.5 Fonctions d’accès direct à un fichier
IV.5.1 Positionnement du pointeur de fichier
L’accès direct à un fichier texte ou binaire est réalisé indifféremment par
l’intermédiaire de l’une des 2 fonctions fseek ou fsetpos :
1- fseek(FILE *f, long Position, int Origine);
Elle fait un accès direct à la Position indiquée (en Octets) relativement à la valeur de la
variable Origine :
Origine = 0 : à partir du début du fichier
Origine = 1 : à partir de la position en cours du fichier
Origine = 2 : à partir de la fin du fichier
On peut utiliser les constantes prédéfinies : (SEEK_SET = 0, SEEK_CUR = 1, SEEK_END
= 2)
Position précise le nombre d’Octets sachant que le premier Octet du fichier porte l’indice 0.
Exemple :
FILE *f ;
f = fopen("test.txt","r+");//Ouverture pour modification.
fseek(f, 10, SEEK_SET) ;//Accès direct à au 11ème Octet (Octet
N° 10)
fprintf(f, "X") ; //Modifier le caractère en cours par ‘X’.
fseek(f, -5, SEEK_CUR) ;//Revient en arrière de 5 Octets.
fprintf(f, "Y") ;//écrase l’ancien caractère par Y.
fseek(f, 0, SEEK_SET) ;//Positionne le pointeur au début du
fichier
2- fsetpos(FILE *f, const unsigned long *Position);
Fait une recherche directe à partir du début du fichier. Elle est équivalente à :
fseek(f, Position, 0)
Exemple :
unsigned long Pos = 100 ;
fsetpos(f, &Pos) ;
Remarque :
Pour positionner le pointeur de fichier sur le Nème enregistrement d’un fichier binaire
d’enregistrements de type STR, il est nécessaire de calculer la position en octets :
long Pos = (N-1)*sizeof(STR); //Le Nème enregistrement est l’enregistrement N°
(N-1).
3- rewind(FILE *f);
Positionne le pointeur au début du fichier. Elle est équivalente à :
fseek(f, 0, SEEK_SET) ;

N. Chenfour 42
IV.5.2 Lecture de la position en cours du pointeur de fichier
Cette opération est réalisée par l’une des fonctions équivalentes fgetpos ou ftell .
Syntaxe :
fgetpos(FILE *f, unsigned long *pos);
long ftell(FILE *f);
Exemple :
fgetpos(f, &Pos) ;
équivalente à :
Pos = ftell(f) ;
Remarque :
Les fonctions d’accès direct sont utilisées à la fois pour accélérer le traitement, mais
aussi pour faire des opération de modification. En effet pour modifier un enregistrement
donné dans un fichier binaire par exemple, en réalise les opérations suivantes :
f = fopen(NomFichier,"r+b") ;
...
fread(&E, sizeof(E), 1, f) ;// Lecture de l’enregistrement à modifier
E.champ1 = Experssion1 ; // Modification des champs de l’enregistrement
...
fseek(f, -sizeof(E), SEEK_CUR) ; //Retour à la position de début
fwrite(&E, sizeof(E), 1,f) ; // Ecriture de l’enregistrement modifié
IV.6 Fonctions complémentaires
IV.6.1 Détection de Fin de fichier
Outre les valeurs particulières que retourne les différentes fonctions de lecture d’un
fichier texte ou binaire et qui peuvent détecter la fin de fichier, la fonction feof peut être
utilisée avec toutes les fonctions pour vérifier si on n’a pas atteint la fin du fichier. Cependant
la fonction feof ne peut détecter la fin de fichier qu’après l’échec d’une tentative de lecture.
On l’utilise alors de la manière suivante par exemple :
fscanf(f, "%s", Mot) ;
while ( !feof(f)) {
printf("%s ",Mot) ;
fscanf(f, "%s", Mot) ;
}
Elle est utilisée de la même manière avec toutes les autres fonctions après une tentative de
lecture.
IV.6.2 Fermeture du fichier
Lorsqu’on termine l’usage d’un fichier, il est nécessaire de le fermer.
fclose(FILE *f);
IV.6.3 Fermeture de tous les fichiers ouverts
fcloseall();
IV.6.4 Vider le tampon d’un fichier sur le disque
Lors de l’écriture dans un fichier, les information écrites passent par l’intermédiaire
d’un tampon intermédiaire. A chaque fois que celui-ci est plein, il est vidé sur le disque pour
accueillir les informations suivantes. Lorsqu’on ferme le fichier le tampon est alors vidé sur le
disque, ce qui explique la nécessité de fermer tout fichier ouvert.
Il est aussi possible de forcer le déchargement du tampon à l’aide de la fonction fflush.
fflush(FILE *f);
IV.6.4 Vider tous les tampons des fichiers
Pour vider tous les tampons associés aux différents fichiers ouverts y compris celui du
clavier, on utilise la fonction flushall :
flushall();

N. Chenfour 43
V- Fonctions d’accès physique aux fichiers
V.1 Suppression d’un fichier
Pour supprimer un fichier NF donée par exemple NF = "C:\\Dos\\doc.tmp", on utilise
indifféremment l’une des deux fonctions suivantes de <stdio.h> :
remove(NF);
unlink(NF);
V.2 Changement de nom d’un fichier
Pour changer le nom d’un fichier, on utilise la fonction rename de <stdio.h>.
rename (AncienNom, NouveauNom);
V.3 Gestion des Répertoires
La gestion des répertoires peut être réalisée à l’aide d’un ensemble de fonctions de la
bibliothèque <dir.h>
V.3.1 Création d’un répertoire
int mkdir(const char *Rep);
V.3.2 Suppression d’un répertoire
int rmdir(const char *Rep);
Remarque :
Les fonctions mkdir et rmdir retournent 0 dans le cas de succès, sinon –1
V.3.3 Changement de répertoire
int chdir(const char *Rep);
V.3.4 Répertoire courant d’un disque
getcurdir(int disque, char *Rep);
Récupère le nom du répertoire actif ("courant") de l'unité de disque spécifiée. On utilise 0
pour a:, 1 pour c:, ...
V.3.5 Répertoire actif
getcwd(char *Rep);
Récupère le nom du répertoire de travail actif.
V.4 Traitement d’un nom de fichier
1- fnsplit (const char *Chemin, char *Disque, char *Rep, char *Nom, char *Ext);
Décompose un nom de fichier complet en 4 parties (chaînes) : l’unité de disque, le nom
complet du répertoire, le nom du fichier sans chemin ni extension et la 4ème partie l’extension.
2- fnmerge (char *Chemin, const char *Disque, const char *Rep, const char *Nom,
const char *Ext);
La fonction fnmerge fait l’opération inverse. Elle construit un nom de fichier complet à partir
des 4 composants.
Les deux fonctions fnsplit et fnmerge sont définie dans la bibliothèque <dir.h>
V.5 Création automatique d’un nom de fichier temporaire
La fonction tmpnam définie dans <STDIO.H> permet de créer à chaque fois appelée
un nouveau nom de fichier temporaire :
char *tmpnam(char *NF);
Exemple :
#include <stdio.h>
int main()
{
char NF[20];
for(int i=1; i<=10; i++) {
tmpnam(NF);
printf("Nom de fichier Temporaire N° %d : %s\n", i, NF);

N. Chenfour 44
}
return 0;
}
V.6 Création automatique d’un fichier temporaire
La fonction tmpfile définie dans <STDIO.H> permet de créer à chaque fois appelée un
nouveau fichier binaire temporaire en mode mise à jour (w+b). dès qu’il est fermé par fclose,
le fichier temporaire est automatiquement supprimé.
FILE *tmpfile();
Exemple :
FILE *f = tmpfile() ;

fclose(f) ;
V.7 Droits d’accès à un fichier
Les fonction chmod et access de <io.h> permette respectivement la mise à jour et la
vérification des droits d’accès d’un fichier :
1- chmod(const char *NF, int mode);
Permet de modifier le mode d’accès d’un fichier (lecture/écriture seulement). Le paramètre
mode prend l’une des valeurs des constantes suivantes définies dans <sys\stat.h>
S_IWRITE (Permission en écriture)
S_IREAD (Permission en lecture)
S_IREAD|S_IWRITE (Permission en lecture et écriture)

2- int access(const char *NF, int mode);


mode prend les valeurs suivates :
0 Vérifie l'existence du fichier
1 Vérifie l'autorisation d'exécution
2 Vérifie l'autorisation d'écriture
la fonction access retourne 0 si le mode d’accès demandé est vrai, sinon elle retourne -1
V.8 Attributs d’un fichier
V.8.1 Lecture d’informations sur un fichier
La fonction stat permet de déterminer certaines informations sur un fichier telles que
la taille, la date de création, etc…
Syntaxe :
struct stat Etat;
stat(NomFichier, &Etat);
La fonction stat ainsi que la structure struct stat sont définies dans la bibliothèque
<sys\stat.h>. cette dernière permet de récupérer les informations sur le fichier. Elle est définie
comme suit :
struct stat {
short st_dev, st_ino;
short st_mode, st_nlink;
int st_uid, st_gid;
short st_rdev;
long st_size, st_atime;
long st_mtime, st_ctime;
};
Champ Description
st_dev et st_rdev Numéro d'unité du disque ou
st_atime, st_mtime et st_ctime Heure et Date de valeur du fichier.

N. Chenfour 45
st_size Taille du fichier en octets
st_mode Masque binaire indiquant l’attribut du fichier : lecture seule, …
St_nlink Prend toujours la valeur 1
St_ino , st_uid, st_gid Ces 3 éléments contiennent des valeurs non utilisé sous dos
Exemple :
#include <stdio.h>
#include <sys\stat.h>
#include <time.h>
main()
{
struct stat Etat;
stat("c:\\autoexec.bat", &Etat);
// Attributs lecture/écriture
if (Etat.st_mode & S_IREAD)
printf("Fichier ayant la permission de lecture.\n");
else if (Etat.st_mode & S_IWRITE)
printf("Fichier ayant la permission d’écriture.\n");
// Autres informations
printf("le fichier se trouve sur le disque : %c\n", 'A'+ Etat.st_dev);
printf("il est de taille : %ld\n", Etat.st_size);
printf("Date de dernière ouverture : %s\n", ctime(&Etat.st_ctime));
return 0;
}
La fonction ctime de la bibliothèque <time.h> est utilisée pour convertir la structure long de
la date en une chaîne littérale contenant toutes les information sur l’heure et la date.
Remarque :
Les seuls modes d’accès accessible avec la structure stat sont :
S_IWRITE (Permission en écriture)
S_IREAD (Permission en lecture)
S_IREAD|S_IWRITE (Permission en lecture et écriture)
Si on veut accéder aux autres modes d’accès : caché, archive , etc, on utilise la fonction
_dos_getfileattr
V.8.2 Lecture du mode d’accès d’un fichier
La fonction _dos_getfileattr permet de déterminer les différents modes d’accès d’un
fichier : lecture seule, caché, fichier système, fichier archive, répertoire ou nom de disque.
Syntaxe :
unsigned int Attrib ;
_dos_getfileattr(NomFichier, &Attrib) ;
Pour déterminer ensuite les différents modes il suffit de tester la valeur de l’expression :
Attrib & Mode
Si c’est différent de 0, cela signifie que le ficher dispose du mode Mode. Exemple :
If (Attrib & _A_HIDDEN) printf ("Fichier caché") ;
Mode prend donc l’une des valeur suivantes définies dans <dos.h> :
Définition Signification
#define _A_NORMAL 0x00 Fichier normal
#define _A_RDONLY 0x01 Fichier à lecture seule
#define _A_HIDDEN 0x02 Fichier caché
#define _A_SYSTEM 0x04 Fichier système
#define _A_VOLID 0x08 Nom du disque
#define _A_SUBDIR 0x10 Répertoire
#define _A_ARCH 0x20 Fichier archive
Exemple :
#include <stdio.h>
#include <dos.h>
main()

N. Chenfour 46
{
char NF[80];
unsigned int Attrib;

printf("Entrer le nom de fichier:");


scanf("%s", NF);
if (_dos_getfileattr(NF,&Attrib) != 0)
{
printf("Fichier introuvable") ;
return 0;
}
printf("Attributs du fichier %s :\n", NF) ;
if (Attrib & _A_NORMAL) printf("- Normal\n") ;
if (Attrib & _A_ARCH) printf("- Archive\n") ;
if (Attrib & _A_RDONLY) printf("- Lecture seule\n") ;
if (Attrib & _A_HIDDEN) printf("- Caché\n") ;
if (Attrib & _A_SYSTEM) printf("- Système\n") ;
if (Attrib & _A_RDONLY) printf("- C’est un répertoire\n") ;
if (Attrib & _A_VOLID) printf("- C’est un nom de disque\n") ;
return 0;
}

N. Chenfour 47
V.8.3 Changement du mode d’accès d’un fichier
La fonction _dos_setfileattr permet de modifier les différents modes d’accès d’un
fichier .
Syntaxe :
unsigned int Attrib = <Expression de masque>;
_dos_setfileattr(NomFichier,Attrib)
Exemple :
Donner à un fichier les attributs caché et lecture seule :
unsigned int Attrib = _A_RDONLY | _A_HIDDEN;
_dos_setfileattr(NomFichier,Attrib)
V.9 Création d’un fichier avec mode d’accès
V.9.1 fonction creat
La fonction creat de la bibliothèque <io.h> est une fonction de bas niveau permettant la
création d’un fichier tout en précisant le mode d’accès à lui attribuer après la création. La
fonction creat ouvre aussi le fichier après sa création et retourne un entier qui est un
descripteur du fichier pouvant être utilisé pour le manipuler.
int f = creat(NomFichier, Attribut);
Exemple :
int f = creat("Document.dat", S_IREAD);
close(f) ;
Le fichier "Document.dat" est créé avec un mode d’accès en lecture seule. Puisque le fichier
est ouvert, il est alors nécessaire de le fermer. Si on n’a pas besoin de descripteur du fichier, il
est possible de créer un fichier de la manière suivante :
close(creat("Document.dat", S_IREAD));
Remarque :
Les seuls modes d’accès (Attributs) possibles avec la fonction creat sont :
S_IWRITE (Permission en écriture)
S_IREAD (Permission en lecture)
S_IREAD|S_IWRITE (Permission en lecture et écriture)
On peut alors utiliser la fonction _creat qui donne les autres possibilités.
V.9.2 fonction _creat
int f = _creat(NomFichier, Attribut);
Dans ce cas Attribut prend une valeur combinée des constantes définies dans <dos.h> :
FA_RDONLY (Fichier à lecture seule)
FA_HIDDEN (Fichier caché)
FA_SYSTEM (Fichier système)
Remarque 1 :
Les fonctions creat et _creat créent un fichier et l’ouvre en écriture. Il est possible
alors d’utiliser le descripteur retourné pour écrire dans le fichier à l’aide de la fonction write :
int write(int descripteur, & Tampon, unsigned Taille);
Exemple 1: (Ecriture dans un fichier texte)
#include <sys\stat.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
main()
{
int f;
char Tmp[20] = "Clavier 150 DH\n";
f = creat("stock.dat", S_IREAD |S_IWRITE);
write(f, Tmp, strlen(Tmp));
close(f) ;

N. Chenfour 48
return 0;
}
Exemple 2: (Ecriture dans un fichier binaire)
#include <sys\stat.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
main()
{
int f;
int T[7]={25,20,30,58,14,25,59};
_fmode = O_BINARY; // c’est une variable prédéfinie permettant de
changer
le mode d’accès au fichier en binaire. Par défaut
c’est
le mode text qui est initialisé : O_TEXT
f = creat("test.bin", S_IREAD |S_IWRITE);
write(f, T, 7*sizeof(int));
close(f) ;
return 0;
}
Remarque 2 :
Les fonctions creat, _creat, write et close sont des fonctions de bas niveau pour la
gestion des fichiers. Il en existe d’autres définies dans la bibliothèque <io.h> et qui peuvent
être utilisé pour une gestion complète des fichiers :
int creat(NomFichier, Attribut);
int _creat(NomFichier, Attribut);
unsigned long filelength(int f);
int eof(int f);
long lseek(int f, long pos, int origine);
int open(const char *NomFichier, int acces [ , unsigned mode ] );
int read(int f, void *Tmp, unsigned Taille);
int _read(int f, void *Tmp, unsigned Taille);
int write(int f, void *Tmp, unsigned Taille);
int _write(int f, void *Tmp, unsigned Taille);
int lock(int f, long Position, long Taille);
int unlock(int f, long Position, long Taille);

N. Chenfour 49
V.10 Recherche des fichiers sur le disque
Les fonctions findfirst et findnext permettent de chercher les fichiers dans le disque.
findfirst extrait le premier fichier et findnext les fichiers suivants. findfirst est alors appelé une
seule fois et findnext est ensuite appelée successivement tant qu’elle retourne 0. En effet
findfirst et findnext renvoient –1 dans le cas où ils n’arrivent plus à extraire un fichier.
Syntaxe :
findfirst(Chemin, struct ffblk *f, int Attribut);
findnext(struct ffblk *f);
avec :
1- Chemin précise le chemin et le masque des fichiers recherchés. Par exemple :
"C:\\*.*", "C:\\Hamid\\*.cpp", "c:\\Simo\\*.bak", …
2- On récupère le fichier trouvé dans la variable f de type struct ffblk . Cette structure est
définie de la manière suivante :
struct ffblk {
char ff_reserved[21]; // Réservé au DOS */
char ff_attrib; // Attribut du fichier trouvé
int ff_ftime; // Heure de création
int ff_fdate; // Date de création
long ff_fsize; // Taille du fichier
char ff_name[13]; // Nom du fichier trouvé
};
ff_ftime et ff_fdate sont des structures sur 16 bits divisées en champs binaires pour gérer la
date de valeur d'un fichier (date et heure).
Bits ff_ftime 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Structure Heures Minutes Secondes/2

Bits ff_fdate 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Structure Anné depuis 1980 Mois Jour
3- Le 3ème paramètre Attribut permet de préciser le type des fichiers recherchés. Pour cela on
utilise l’une des constantes prédéfinie dans <dos.h>
Définition Signification
#define FA_NORMAL 0x00 Fichier normal
#define FA_RDONLY 0x01 Fichier à lecture seule
#define FA_HIDDEN 0x02 Fichier caché
#define FA_SYSTEM 0x04 Fichier système
#define FA_LABEL 0x08 Nom du disque
#define FA_DIREC 0x10 Répertoire
#define FA_ARCH 0x20 Fichier archive
Exemple :
struct ffblk f ;
int k = findfirst("*.*", &f, 0);
while (k != 0) {
printf("%s\n",f.ff_name) ;
k = findnext(struct ffblk *f);
}

N. Chenfour 50
Complément N° 2

Programmation en Langage C/C++


( Gestion des chaînes de caractères et des blocs de Mémoire)

Les Routines suivantes sont déclarées dans <STRING.H>


I- Routines utilisées comme des Procédures :

char * strcat(char * dest, const char * src);


strcat(S1,S2)  concaténation : S1=S1+S2.
char * strncat(char * dest, const char * src, unsigned n);
strcat(S1,S2,n)  S1=S1+(n caractères de S2).
char * strcpy(char * dest, const char * src);
strcpy(S1,S2)  copie S2 dans S1 : S1=S2.
char * strncpy(char * dest, const char * src, unsigned n);
strncpy(S1,S2,n)  copie n caractères de S2 dans S1.
char * strlwr(char * s);
strlwr(S)  Convertit S en minuscule.
char * strupr(char * s);
strupr(S)  Convertit S en majuscule.
char * strset(char * s, int ch);
strset(S,ch)  Remplie toutes les cases de la chaîne S par le caractère ch.
char * strnset(char * s, int ch, unsigned n);
strnset(S,ch,n)  Remplace n caractères de S par ch.

II- Routines utilisées comme des Fonctions :

char * strchr(const char * s, int c);


if (strchr (S,c)) …  teste si le caractère c ∈S
char * strstr(const char * s1, const char * s2);
if (strstr (S1,S2)) …  teste si la chaîne S2 est ⊂ S1
int strcmp(const char * s1, const char * s2);
if ( ! strcmp(S1,S2)) …  si (S1=S2) …
int stricmp(const char * s1, const char * s2);
if ( ! stricmp(S1,S2)) …  compare sans distinguer entre maj. et min.
int strncmp(const char * s1, const char * s2, unsigned n);
if ( ! strncmp(S1,S2,n) …  compare n caractères de S1 et S2.
unsigned strlen(const char * s);
L = strlen (S) L = longueur de S.
int strcoll(const char * s1, const char * s2);
compare deux chaînes S1 et S2 et retourne
- une valeur négative si S1<S2,
- une valeur = 0 si S1=S2,
- une valeur positive si S1>S2.

N. Chenfour 51
char *strdup(const char *s);
Crée un nouvel espace mémoire où elle duplique une chaîne de caractères existante :
Exp :
char *S1 = "abcd" ,*S2;
S2 = strdup(S1) ;

III- Routines utilisées Pour la gestion de la mémoire :

void *malloc(int n); // dans la bibliothèque <malloc.h>


Fait une demande de réservation d'espace mémoire. elle alloue un bloc de mémoire de
n octets et renvoie un pointeur sur la zone de mémoire allouée.
Exp :
char *S;
S = (char *)malloc(20); // alloue une zone mémoire de 20 octets pour la chaîne S.
void *realloc(void *Block, int T);
Alloue une nouvelle mémoire de taille T pour une variable Block tout en conservant
l’ancien contenu.
void free(void *Block);
Libère un Bloc de mémoire préalablement alloué par malloc ou realloc.
void * memset(void * s, int c, unsigned n);
Remplie n octets de s avec le même octet c.
int memcmp(const void * s1, const void * s2, unsigned n);
Compare les n premiers octets de s1 et s2 .
void * memmove(void * dest, const void * src, unsigned n);
Copie un bloc de n octets de src vers dest.

N. Chenfour 52
Série N° 1

Exercice 1 :
Ecrire un programme réalisant la facturation d’un produit de prix unitaire hors taxe
PHT, sachant que la quantité commandée est égale à Q, et le taux de TVA est fixé à 20%.
Exercice 2 :
Ecrire un programme qui reçoit en entrée deux valeurs n1 et n2, puis échange leurs
valeurs et les affiche à l’écran.
Exercice 3 :
Soient N1, N2 et N3 3 notes saisies au clavier. Ecrire un programme qui commence
par afficher le message ’Entrer 3 notes : ’, ensuite lit N1, N2 et N3, puis calcule et affiche
leur moyenne.
Exercice 4 :
Ecrire un programme qui lit 3 valeurs : 2 entiers et un réel et les affiche chacune dans
une ligne séparée. Ensuite les affiche dans une même ligne séparées par des virgules.
Exercice 5 :
Ecrire un programme Pascal qui pour une somme d’argent donnée (en DH), fait la
répartition en billets et pièces de 100 DH, 50 DH, 10 DH, 5 DH et 1 DH.
Exercice 6 :
Un client achète une quantité Q d’un produit valant P Dirhams l’unité. Lorsque le
montant brut M est inférieur ou égal à 200 DH, on rajoute 25 DH de frais de transport. Ecrire
un programme qui calcule le montant de la facture pour un client.
Exercice 7 :
Ecrire un programme qui lit 3 entiers x, y et z et détermine la valeur la plus grande.
Exercice 8 :
Ecrire un programme réalisant la facturation d’un article livré en un ou plusieurs
exemplaires. On fournira en données le nombre d’articles et leur prix unitaire hors taxes hors
taxes. Le taux de TVA sera toujours de 20 %. si le montant de TTC dépasse 1000 DH, on
établira une remise de 5 %. On cherchera à ce que le dialogue se présente comme suit:
Nombre d’articles ? (lecture)
Prix unitaire hors taxes ? (lecture)
Montant TTC : (affichage)
Remise : (affichage)
Net à payer : (affichage)

N. Chenfour 53
Série N° 2

Exercice 1 :
Ecrire un programme qui reçoit en entrée deux valeurs n1 et n2, ensuite il les échange
de telle façon à obtenir n1<=n2.
Exercice 2 :
Ecrire un programme qui calcule et affiche le minimum et le maximum de 3 réels lus
au clavier.
Exercice 3 :
Ecrire un programme qui lit 3 réels au clavier. Ensuite il demande à l’utilisateur s’il
veut calculer le minimum ou le maximum. Si la réponse et ’a’ ou ’A’, il calcule et affiche le
maximum et si la réponse et ’i’ ou ’I’ il calcul et affiche le minimum. Si la réponse et
différente, le programme affiche ’réponse incorrecte’.
Exercice 4 :
Ecrire un programme qui lit 3 notes à partir du clavier, calcule et affiche la moyenne
de ces notes. En fin, il affiche la mention correspondante :
’Très Bien’ si la moyenne est > 16
’Bien’ si la moyenne est entre 14 et 16
’Assez Bien’ si la moyenne est entre 12 et 14
"Passable" si la moyenne est entre 10 et 12
"Médiocre" si la moyenne est <10
Exercice 5 :
Ecrire un programme de calcul d’un prix TTC, à partir des données suivantes:
- Prix hors taxes.
- Code TVA : lettre (majuscule) :
A pour désigner 5.5 %
B pour désigner 7 %
C pour désigner 19 %
D pour désigner 33.33 %
Le programme doit afficher la valeur du taux de TVA, La TVA et le prix correspondant. Dans
le cas où l’utilisateur fournit un code incorrect, le programme doit afficher le message: ’Code
incorrect’ et aucun traitement ne sera fait.
Exercice 6 :
Un commerçant achète et revend un article dans les conditions suivantes :
 Prix d'achat : à saisir à partir du clavier
 Coût d'achat = Prix d'achat + frais; sachant que les frais sont 8% du prix d'achat si le
prix d’achat est >à 5000. Les frais sont de 5% si le prix est entre 1000 et 5000. sinon frais
est = 0.
 Frais de vente = 10% du coût d'achat.
 TVA = 20% si c’est un produit de type ‘A’,

N. Chenfour 54
 TVA = 28% si c’est un produit de type ‘B’,
 TVA = 33% si c’est un produit de type ‘C’,
 Le type du Produit est à saisir à partir du clavier
En fin on calcul le prix de vente sachant que :
 Prix de vente Hors Taxe est égal à Coût d'achat + Frais de vente.
Ecrire un programme qui fait le traitement correspondant.
Exercice 7 :
Un papetier vend des feuilles de format A4 qu’il fabrique lui même et rassemble par
cartons. Pour des quantités commandées ne dépassant pas 20 cartons, chaque carton est
facturé 100 DH. Au delà du 21ème au 50ème cartons, le prix unitaire passe à 90 DH et à partir
du 51ème carton, le prix unitaire passe à 80 DH.
Ecrire le programme qui calcule le montant à payer correspondant à une quantité commandée.
Exercice 8 :
Une usine de production d’engrais emballe les sachets d’engrais qui lui sont
commandés par les détaillants dans des emballages:
- De type A, qui contiennent 100 sachets,
- De type B, qui contiennent 30 sachets ou
- De type C, qui contiennent 10 sachets.
Ecrire un programme qui lit la quantité commandée, vérifie tous d’abord si elle est
correcte(c’est à dire que la quantité peut être emballée avec les emballages A,B et C), si c’est
le cas le programme détermine les nombre d’emballages de type A,B et C nécessaires.
Pour cela on utilise les deux fonctions DIV et MOD sachant que:
DIV donne le quotient d’une division, et MOD donne le reste de la division
Exercice 9 :
Ecrire un programme qui fait la résolution d’une équation : aX2+bX+c. le programme
doit lire a, b et c, calculer le déterminant, ensuite calculer et afficher la solution.

N. Chenfour 55
Série N° 3

Exercice 1 :
Ecrire un programme qui lit N valeurs de type entier et détermine la valeur la plus
grande et la valeur la plus petite.

Exercice 2 :
Ecrire un programme qui calcule la moyenne de N notes saisies au clavier. La valeur
de N sera aussi introduite par l’utilisateur.

Exercice 3 :
On veut informatiser le service de paie d’un supermarché. Lorsqu’un client se présente
au cassier, celui-ci tape le nombre d’articles acheté par le client, le prix unitaire ainsi que la
quantité de chaque produit. Le montant total correspondant sera alors calculé et affiché à
l’écran.

Exercice 4 :
Ecrire un programme qui affiche un triangle rempli d’étoiles s’étendant sur un nombre
de lignes fourni au clavier. Le résultat se présente comme suit :

Nombre de lignes? 5
*
**
***
****
*****

Réaliser de la même manière un programme qui affiche les étoiles sous la forme suivante :

*
***
*****
*******
*****
***
*
Exercice 5 :
Ecrire un programme qui calcule la moyenne d’un ensemble de notes lues au clavier.
Après chaque lecture d’une note, l’ordinateur doit poser la question ‘Encore une note?’, si la
réponse et ‘O’ ou ‘o’ il répète la lecture. Si la réponse est ‘N’ ou ‘n’, il s’arrête et affiche la
moyenne des notes lues. Si la réponse est un caractère différent, un message d’erreur est
affiché : "Réponse Incorrecte", et la question sera répétée jusqu’à ce que la réponse soit
correcte.

Exercice 6 :
On veut réaliser un jeu pour deviner un entier par l’utilisateur. Le jeu se jouera entre
l’ordinateur et l’utilisateur. L’ordinateur choisi un entier D au hasard entre 0 et 100.

N. Chenfour 56
L’utilisateur doit le deviner en proposant des nombres. A chaque proposition l’ordinateur
répond en situant le nombre proposé P par rapport au nombre à deviner D:
- Si P>D l’ordinateur répond "trop grand"
- Si P<D l’ordinateur répond "trop petit"
- Si P=D le jeu est terminé et la machine affiche le nombre de propositions faites par
l’utilisateur avant de trouver la solution.
Indication :
D = rand() % N;
est une expression qui permet de choisir aléatoirement un entier entre 0 et N-1. L’usage de la
fonction « rand() » nécessite l’inclusion de la bibliothèque « stdlib.h »
Pour obtenir de nouvelles valeurs à chaque exécution du programme, on doit faire une
initialisation du processus de choix des valeurs aléatoires à l’aide la fonction « srand() »
qui sera appelée au début du programme à l’aide de l’instruction suivante. :
srand(time(0));
L’usage de la fonction « time » nécessite l’inclusion de la bibliothèque « time.h »
Exercice 7 :
1) Ecrire un programme qui lit un entier et détermine si celui-ci est premier.
2) Ecrire un programme qui détermine les N premiers nombres premiers.
Exercice 8 :
n
1) Ecrire un programme qui calcule la somme : S (n) = ∑ k 2
k =1

n
2) Ecrire un programme qui calcule la somme : S (n) = ∑ (−1) k × k 2
k =1

n
1
3) Ecrire un programme qui calcule la somme : S (n) = ∑
k =1 k!

N. Chenfour 57
Série N° 4

Exercice 1 :
1- Ecrire une procédure AfficherReel qui affiche un réel avec un format approprié
(10:2) en commençant par le message " Le résultat est : ".
2- Ecrire une procédure qui permute les valeurs de ses 2 paramètres.
3- Ecrire une procédure (à 4 paramètres) qui génère 2 valeurs aléatoires X1 et X2
entre deux entier N et M. avant de générer X1 et X2, la procédure doit vérifier que N
est < à M, dans le cas contraire N et M seront permutés. En plus X1 et X2 doivent
être générés distincts et tels que X1 est < à X2.

Exercice 2 :
1- Ecrire une procédure qui reçoit une moyenne et affiche la mention correspondante.
2- Ecrire une fonction (sans paramètre) qui invite un utilisateur à introduire une note,
ensuite elle lit et retourne la note.
3- Ecrire une fonction qui calcule et retourne la moyenne de 3 valeurs réelles.
4- Ecrire un programme principal qui utilise les fonctions et procédures précédentes
pour lire 3 notes, calculer leur moyenne et afficher la mention adéquate.

Exercice 3 :
1- Ecrire une fonction qui calcule le maximum de 2 entiers.
2- Utiliser la fonction précédente pour calculer le maximum de 3, puis 4 entiers à l’aide
d’une seule instruction.
3- Refaire le même travail avec une fonction qui calcule le minimum de 2, 3 et 4
entiers.

Exercice 4 :
1- Ecrire une procédure à 4 paramètres : X, F, D et R. La procédure divise X par F et
retourne la valeur de la division Entière dans D et le reste de la division dans R.
2- Utiliser la procédure pour répartir une somme d’argent donnée (en DH), en billets et
pièces de 100 DH, 50 DH, 10 DH, 5 DH et 1 DH.

Exercice 5 :
1- Ecrire une fonction booléenne qui détermine si son paramètre et premier ou non.
2- Utiliser la fonction précédente pour Ecrire une procédure qui affiche tous les
nombres premiers situés entre deux entiers N et M.
3- Ecrire une autre procédure qui affiche les N premiers nombres premiers
4- Ecrire une fonction qui calcule et retourne la somme des nombres premiers situés
entre deux entiers N et M.

N. Chenfour 58
Exercice 6 :
Cet exercice permettra la gestion d’un certain nombre d’opérations bancaires : Retrait,
Versement et Transfert.
Ecrire une procédure avec 3 paramètres : Total Retiré, Total Versé et Total Transféré. La
procédure doit répéter le traitement suivant pour chaque client jusqu’à ce qu’il n’y est plus de
client.
- Elle demande au client d’introduire le montant et le type d’opération à
réaliser : ‘R’ pour retirer, ‘V’ pour verser et ‘T’ pour transférer. La lecture est
réalisée par une fonction qui retourne le caractère Tapé. On n’accepte que l’un
de ces 3 caractères.
- Ensuite, elle met à jour le paramètre adéquat en fonction de l’opération choisie.
Ce traitement est réalisé par l’intermédiaire d’une procédure à 4 paramètres.
- Enfin, elle demande s’il y a un autre client. Si la réponse est ‘o’ le traitement
sera répété, ‘n’ le traitement se termine, et tout autre caractère déclenche un
message d’erreur et on répète la lecture. Ce traitement est aussi réalisé par
l’intermédiaire d’une fonction qui retourne le caractère saisi.

Exercice 7 :
Un commerçant achète et revend un article dans les conditions suivantes :
 Prix d'achat : à saisir à partir du clavier
 Coût d'achat = Prix d'achat + frais; sachant que les frais sont 8% du prix
d'achat.
 Frais de vente = 10% du coût d'achat.
 Prix de vente Hors Taxe = Coût d'achat + Frais de vente.
En fin il calcul le prix de vente TTC sachant que :
 Prix de vente utilise un taux de TVA = 20%
1- Ecrire une fonction Frais qui calcule et retourne les frais sur un Montant donné et
pour un taux donné. La fonction reçoit 2 paramètres : le Montant et le Taux.
2- Ecrire une fonction Prix qui reçoit un Montant et un Taux, à partir desquels elle
calcule les Frais qu’elle ajoute au montant. La valeur calculée sera ensuite retournée.
Cette fonction devra faire appel à la fonction précédente.
3- Etant donnée un prix d’achat PA, Ecrire un programme principal qui utilise 3 fois la
fonction Prix pour calculer :
- le Coût d’Achat
- le Prix de Vente Hors Taxe
- et le Prix de Vente TTC
1- Reprendre le programme précédent pour calculer le Prix de Vente TTC avec une
seule instruction au lieu de 3.

Exercice 8 :
Un super marché vend 3 types de produits : des produits de classe A, ceux de classe B,
et des produits de classe C. Les produits de classe A sont facturés avec un taux de TVA de
25%, les produits de classe B : 20% et les produits de classe C : 5%.
1- Ecrire une fonction Taux qui reçoit un caractère (‘A’, ‘B’ ou ‘C’) et retourne le taux de
TVA correspondant sous forme d’un réel.

N. Chenfour 59
2- Ecrire une fonction LireChar sans paramètre qui invite l’utilisateur à taper l’un des 3
lettres (‘A’, ‘B’ ou ‘C’). Si le caractère tapé est différent de ces 3 caractères la fonction
répète la lecture jusqu’à ce que la réponse soit correcte. A la fin, la fonction retourne le
caractère tapé.
3- Lorsqu’un client se présente à la caisse pour payer, on doit introduire: le prix unitaire hors
taxe, la quantité et la classe de chaque produit acheté. Ecrire alors une fonction
CalculPrix qui reçoit en entrée ces 3 paramètres : Real, Real et Char. La fonction calcule
et retourne le montant TTC (on utilisera la fonction Taux).
4- Ecrire le programme principal qui lit 3 informations : le prix unitaire hors taxe, la quantité
et la classe du produit acheté (on utilisera la fonction LireChar). Le programme appelle
ensuite la fonction CalculPrix et affiche le montant TTC calculé.

Exercice 9 :
On veut réaliser une calculatrice permettant les opérations suivantes :
- Addition : +
- Soustraction : -
- Division : /
- Multiplication : *
- Puissance : ^
- Résultat : =
Le programme lit alternativement une valeur numérique (de type float) suivit d’un opérateur
(de type char). Chaque valeur et chaque opérateur est saisi sur une ligne séparée. Par
exemple :
20
+
30
=
Lorsqu’on tape = le résultat final est affiché sur la ligne suivante et le programme affiche le
message : ‘Nouvelle opération ? ‘. Si on répond par ‘o’ ou ‘O’ une nouvelle opération
démarre. Sinon le programme se termine.
Le programme correspondant sera réalisé à l’aide des fonctions suivantes :
1. Ecrire une fonctions avec 3 paramètres : 2 réels et un opérateur de type caractère. La
fonction doit appliquer l’opérateur aux deux réels et retourner le résultat
correspondant. Les opérateurs acceptés sont +, - , * , / et ^.
2. Ecrire une fonction qui lit et retourne un caractère. Celui-ci doit obligatoirement être
l’un des opérateurs acceptés. Dans le cas contraire le traitement est répété jusqu’à la
réception du bon caractère.
3. Ecrire une procédure qui lit une séquence d’opérateurs et de réels et calcule et affiche
le résultat correspondant lorsqu’on tape le caractère =. La procédure utilise les 2
fonctions précédentes.

N. Chenfour 60
Exercice 10 :

1- Résoudre d’une manière récursive le problème suivant :


U(0)=1
U(n)=V(n−1)+W(n)
 U(n)
V(n)=
 2
2×V(n)+U(n−1)
W(n)=
 n

2- Ecrire une fonction récursive qui calcule le maximum d’une séquence d’entiers lus
au clavier. La lecture est réalisée dans la fonction, et après chaque lecture on pose
la question : ‘encore un entier ? ’. Si la réponse et ‘o’, le traitement est répété,
sinon on retourne la valeur du max.

Exercice 11 :
4. Définir un type fonction avec 2 paramètres de type réel.
5. Ecrire 4 fonctions : plus, moins, multiplier et divisez qui réalisent successivement,
chacune sur ces 2 paramètres, les opérations +,- , * et /. Le résultat est retourné par la
fonction.
6. Ecrire une fonction qui reçoit 2 paramètres en entrée : un entier N et une fonction F.
La procédure lit N entiers sur lesquels elle applique la fonction F. par exemple :
20 + 25 + 8 + 7 … si F est égale à plus
ou
20 * 25 * 8 * 7 … si F est égale à multiplier
7. Ecrire le programme principale qui réalisent les opérations suivantes :
- Lire un entier N,
- Lire un caractère Op obligatoirement égal ‘+’ ou ‘-‘ ou ‘*’ ou ‘/’.
- Donner à une variable globale F de type fonction le nom de la procédure
adéquate en fonction de l’opérateur saisi.
- Appeler la fonction 3 et afficher le résultat de calcul.

N. Chenfour 61
Série N° 5

Exercice 1 :
On demande la réalisation d’un ensemble de procédures et de fonctions de gestion
d’un tableau d’entiers :
1- Saisie des éléments du tableau.
2- Affichage du tableau (les éléments sont affichés sur la même ligne, séparés par des
virgules).
3- Calcul et retour de la somme des éléments du tableau.
4- Calcul et retour du plus petit élément du tableau.
5- Calcul et retour du nombre d’occurrences d’un élément dans le tableau.

Exercice 2 :
Ecrire une procédure qui reçoit en entrée un tableau d’entiers. La procédure doit
ranger les pairs dans un tableau et les impaires dans un autre tableau.

Exercice 3 :
1- Ecrire une procédure qui supprime un élément (donné par sa position) d’un tableau.
2- Ecrire une procédure qui supprime d’un tableau d’entiers tous les éléments pairs.
3- Ecrire une procédure qui insère un élément dans un tableau à une position donnée.

Exercice 4 :
1- Ecrire une procédure qui permute 2 éléments d’un même tableau, donnés par leurs
positions.
2- Ecrire une fonction qui cherche et retourne la position du plus petit élément du
tableau à partir d’une position donnée.
3- Ecrire une procédure qui pour un indice i donnée elle cherche la position p du plus
petit élément à partir de i. Ensuite elle permute les deux éléments donnés par les
positions i et p.
4- Ecrire une procédure qui répète le travail de la procédure précédente pour un i allant
de 1 jusqu’au dernier élément du tableau.
5- Déduire.

Exercice 5 :
Un produit étant caractérisé par son code, nom, quantité, prix unitaire et date d’entrée.
Ecrire un programme qui réalise successivement les taches suivantes :
1- Construire un tableau de produits saisis à partir du clavier.
2- Lire un code de produit et une valeur entière et ajouter la valeur à la quantité du
produit correspondant.
3- Afficher tous les produits dont la quantité est inférieure à un seuil saisi au clavier.

N. Chenfour 62
4- Supprimer du tableau tous les produits dont la date d’entrée est inférieure à une date
donnée au clavier.

Exercice 6 :
1- Ecrire un programme qui fait la saisie d’une liste de personnes dont chacune est
caractérisée par le nom, le prénom, la date de naissance (jour, mois et année) et le sexe (le
caractère ‘F’ pour féminin et ‘M’ pour masculin). Après chaque lecture d’une personne, celle-
ci doit être insérée dans un tableau de manière à obtenir après chaque insertion un tableau trié
par ordre alphabétique croissant des noms puis les prénoms dans le cas d’égalité des noms. Le
programme pose ensuite la question ‘Encore ?’, si la réponse est ‘O’ ou ‘o’ il lit les
informations de la personne suivante.
2- le programme doit ensuite réaliser les opérations suivantes :
a- Calculer le nombre de personnes dont l’âge et < 20, celles dont l’âge et entre 20 et 45 et
celle dont l’âge et > 45.
b- Construire et afficher 3 nouveaux tableaux à partir du tableau précédent pour répartir les
personnes suivant leurs âges en trois catégories (<20, entre 20 et 45, au delà de 45).
c- Le programme doit enfin calculer le pourcentage des hommes et des femmes dans chacune
des 3 catégories.

Exercice 7 :
Une petite entreprise commerciale envisage l’informatisation des préparations de
facturation. Son stock sera désigné par un tableau de produits, où chaque produit est
caractérisé par sa référence, sa désignation, sa quantité en stock son seuil (quantité minimale
acceptée) et son prix unitaire hors taxe.
Ecrire un programme qui fait dans une première phase la saisie des produits. Ensuite il fait la
saisie des commande clients. Dans une commande, on lit pour chaque produit les deux
informations suivantes :
La Référence Produit
La Quantité commandée
En fin, pour chaque client le programme établit et affiche la facture correspondante sous la
forme :

Référence Désignation Quantité achetée Prix unitaire HT Montant HT


... ... ... ... ...

Total Hors Taxe : ...


Total Toute Taxe Comprise ...

Le programme doit mettre à jour le stock au fur et à mesure des facturations et doit vérifier si
les quantités commandées dépassent les quantités en stock et afficher après chaque commande
les produits en rupture de stock (c à d : dont la quantité est ≤ au seuil).

Exercice 8 :
Un examen comprend une série de 5 épreuves; l’algèbre avec un coefficient 3, la
géométrie avec un coefficient 2, l’anglais avec un coefficient 2, les équations différentielles le
coefficient 1 et l’informatique le coefficient 4.

N. Chenfour 63
Pour réussir l’examen, il faut obtenir une moyenne générale ≥ 10 et ne pas avoir eu la note
éliminatoire qui est de 0 dans toutes les matières sauf en algèbre où elle est de 5 et en
informatique de 6.
1) réaliser les types suivants :
Matière : caractérisé par le numéro (de 1 à 5), le nom, le coefficient et la note
éliminatoire.
Epreuve : caractérisé par le numéro de la Matière et la note.
Examen : est un tableau de 5 Epreuves.
Etudiant : le nom, l’Examen, la moyenne générale, la mention et le résultat (admis ou
non admis)
Classe : un tableau d’Etudiants
2) Ecrire un programme qui fait en un premier temps la saisie des notes de N
étudiants. Pour chaque étudiant on lit le nom et les notes des 5 matières. ensuite on calcule la
moyenne générale et on détermine la mention correspondante. Toutes les informations seront
insérées dans le tableau d’Etudiants par ordre alphabétique croissant des noms. En fin, le
programme affiche les moyennes générales de tous les étudiants et le résultat (admis ou non
admis) dans un tableau sous la forme:
Nom Etudiant Moyenne générale Mention Résultat

N. Chenfour 64
Série N° 6
Exercice 1 :
Ecrire un programme qui affiche les caractères de codes ASCII entre 0 et 255, 24 par
24 chacun dans une ligne. Devant chaque code on écrit le caractère correspondant.
Exercice 2 :
Ecrire un programme qui lit un texte de plusieurs lignes. L’arrêt de la saisie est
effectué lorsqu’on termine par un point. La lecture est réalisée par la fonction getch().
Exercice 3 :
Ecrire un programme qui lit une chaîne binaire (formée de ‘0’ et de ‘1’), et transforme
les ‘0’ en ‘1’ et les ‘1’ en ‘0’. Le programme doit signaler une erreur si un caractère de la
chaîne est ≠ ‘0’ et ≠ de ‘1’.
Exercice 4 :
Ecrire une programme qui lit une chaîne binaire caractère par caractère à l’aide de la
fonction getch() et détermine sa valeur décimale. Le programme n’accepte et affiche que les 2
caractères binaires. Tout autre caractère sera ignoré.
Exercice 5 :
Ecrire un programme qui lit une chaîne de caractère et calcule le nombre d’espaces
dans la chaîne.
Exercice 6 :

Ecrire un programme qui lit une chaîne de caractère et détermine le nombre de


voyelles contenues dans la chaîne.

Exercice 7 :
Ecrire un programme qui lit un texte et un mot est détermine le nombre d’occurrence
du mot dans le texte.
Exercice 8 :
Ecrire un programme qui détermine le plus petit caractère dans une chaîne donnée.
Exercice 9 :
Ecrire un programme qui remplace les blancs d’une chaîne de caractères par des
retours chariot.
Exercice 10 :
Ecrire un programme qui lit une chaîne d’au maximum 80 caractères, et qui la réécrit
dans une autre en changeant tout espace par deux points (..).

Exercice 11 :
Ecrire un programme qui élimine les blancs d’une chaîne donnée.
Exercice 12 :
Ecrire un programme qui lit une chaîne de caractères et fait la suppression des espaces
redondants (c’est à dire : s’il existe un groupe de caractères espace successifs, on les supprime
tous sauf un).
Exercice 13 :
Ecrire un programme qui lit une chaîne d’au maximum 80 caractères, et qui la réécrit
dans une autre en éliminant le premier caractère de chaque mot.

N. Chenfour 65
Exercice 14 :
Le mot miroir d’un mot donné est le mot obtenu en lisant le mot donné à partir de la
fin. Ecrire un programme qui:
1- Donne le mot miroir d’un mot saisi au clavier.
2- Vérifie si le mot Saisi est un mot palindrome, c’est-à-dire identique à son mot
miroir.
Exercice 15 :
Ecrire un programme qui lit une chaîne de caractère et l’affiche dans une table à une
ligne et N colonnes. N étant la longueur de la chaîne.
Exp : la chaîne est = ’abcdef'’, sera affichée comme suit :
a b c d e f
Exercice 16 :
Ecrire un programme qui affiche dans une table de 10 colonnes les caractères des
codes ASCII (entre 32 et 255) avec la forme suivante :
32 : 33 : ! 34 : " 35 : # 36 : $ 37 : % 38 : & 39 : ’ 40 : ( 41 : )
42 : * 43 : + 44 : , 45 : - 46 : . 47 : / 48 : 0 49 : 1 50 : 2 51 : 3

Exercice 17 :
Ecrire un programme qui calcul le nombre de mot d’une chaîne
Exercice 18 :
Ecrire un programme qui lit une chaîne de caractères et remplace dans la chaîne
chaque caractère par son code ASCII.
Exercice 19 :
Ecrire un programme qui lit une chaîne constituée de parenthèses et détermine si elles
sont équilibrées. c à d chaque parenthèse ouvrante possède une parenthèse fermente associée,
et on ne doit pas trouver une parenthèse fermante sans avoir à l’avance une parenthèse
ouvrante.

N. Chenfour 66
Exercice 20 :
Ecrire un programme qui lit une suite de N produits, donnés par le Code, le Nom, le
Prix hors taxes et la quantité. Les 4 informations sont insérées dans une même chaîne de
caractères, séparées l’une de l’autre par un espace. Exemple : ’C201 Ordinateur 9500 12 C202
Imprimante 1800 5 …’. c à d 12 ordinateurs et 5 imprimantes.
Ensuite le programme lit un code donné et affiche le nom et le prix TTC du produit
correspondant, avec 20% la valeur du taux de TVA. Si le code n’existe pas un message
d’erreur est affiché. Après chaque lecture la quantité doit diminuer (de 1) comme si on a
réalisé la vente d’un article du produit. La chaîne doit alors être modifiée en conséquence
pour mettre à jour la quantité. Après chaque opération on affiche la chaîne résultante.
Ce traitement doit être répété jusqu’à ce que l’utilisateur tape le code 0000.

N. Chenfour 67
Mini Projet en langage C

On veut réaliser une application de gestion de courriers électroniques. Pour cela, on réalise
les 4 étapes suivantes :

Etape N° 1 :
On veut réaliser une application de gestion de courriers électronique. Pour cela, on réalise
les procédures suivantes :
1- Ecrire une procédure MailTo, qui reçoit en paramètre le nom d’un utilisateur à qui on veut
envoyer un mail. La procédure crée, dans un répertoire ‘mail’, un fichier qui porte le
même nom que celui de l’utilisateur s’il n’existe pas déjà. Ensuite y copier un texte saisie
au clavier caractère par caractère à l’aide de la fonction getch() jusqu’à taper la touhe F2.
Dans le fichier du mail, on écrit le texte tapé, à partir d’une nouvelle ligne et précédé par
les symboles >> pour indiquer le début de chaque email (car dans le même fichier, on peut
inscrire plusieurs mails successifs).
Utiliser cette procédure pour envoyer quelques emails à un même utilisateur ou des
utilisateurs différents.
2- Ecrire une fonction ExistMail qui teste si pour un utilisateur donné, il existe des emails et
affiche le nombre de mails existants.
3- Ecrire une procédure ConsultMail qui reçoit un nom utilisateur et un numéro de mail, et
affiche le mail correspondant.
4- Ecrire une procédure DeleteMail qui reçoit un nom utilisateur et un numéro de mail, et
supprime, après confirmation, le mail correspondant. On utilise les procédure prédéfinies :
Erase(Nom du fichier) et Rename(Ancien Nom, Nouveau Nom)

Etape N° 2 :
Dans le but de la sécurité des mails utilisateurs, on se propose de crypter chaque
message avant de le stocker. Puis de réaliser une procédure de décryptage qui permet la
lecture du fichier crypté.
1- Ecrire une procédure Crypter à deux paramètres, le premier est un caractère à coder, le
deuxième est le code associé au caractère (à déterminer). Sachant que le code est une
chaîne de caractère déterminée en fonction du caractère en respectant les étapes
suivantes :
- On détermine le code ASCII du caractère
- On ajoute une valeur V=51 au code
- On détermine la chaîne binaire sur 8 bits associée au code (en complétant par des 0 à
gauche si nécessaire).
- On remplace chaque ‘0’ par ‘.’ et chaque 1 par ‘-‘. La chaîne résultante constitue le
code associé au caractère.

N. Chenfour 68
2- Refaire la procédure MailTo de l’exercice précédant. La procédure doit crypter chaque
caractère (en utilisant la fonction crypter) avant de le stocker dans le fichier
correspondant.
3- Ecrire une fonction décrypter qui reçoit en paramètre une chaîne de 8 caractères (le code),
et détermine le caractère correspondant.
4- Refaire la procédure ConsultMail de l’exercice précédant pour permettre la lecture d’un
mail crypté.

Etape N° 3 :
Le but de cette étape est d’enrichir le travail des 2 étapes précédentes en ajoutant une
gestion des mots de passes. Ainsi on définit un utilisateur par son nom, son mot de passe et sa
date d’enregistrement.
1- Ecrire une procédure qui permet la saisie d’un mot de passe (de nombre de caractère ≤ 20)
et le retourne comme paramètre. Au cours de la saisie, des étoiles sont affichées à la place
des caractères tapés.
2- Ecrire une procédure qui permet de crypter le mot de passe (en utilisant la fonction
Crypter) et retourne en 2ème paramètre le mot crypté dans une chaîne.
3- Ecrire une procédure qui lit le nom, le mot de passe et la date d’un utilisateur et l’ajoute
dans un fichier binaire ‘USERS.DAT’ après avoir crypté le mot de passe.
4- Ecrire une procédure à deux paramètres qui permet de décrypter un mot de passe. Le
premier paramètre de la procédure est la chaîne cryptée associée au mot de passe. Le
deuxième paramètre est le mot de passe à déterminer.
5- Ecrire une fonction booléenne qui reçoit un Nom et un Mot de passe non crypté et vérifie
si le mot de passe est correct.
6- Ecrire une procédure qui lit le Nom d’un utilisateur et son Mot de passe, est lui permet de
lire ses mails si le mot de passe est correct.
7- Ecrire une procédure qui permet à un utilisateur de changer son mot de passe. La
procédure doit demander l’ancien mot de passe, vérifier qu’il est correct, ensuite lire est le
nouveau mot de passe et remplace l’ancien sur le fichier (après cryptage).
8- Ecrire une procédure qui permet la suppression d’un utilisateur.

Etape N° 4 :
On demande de réaliser une interface générale de manipulation des emails d’un
utilisateur :
1- Inscription Utilisateur
2- Changement de mot de passe
3- Consultation des emails
4- Suppression
5- Envoie d’emails aux autres utilisateurs

N. Chenfour 69
Application :
Pour la gestion des comptes clients d’une banque, on considère les deux fichiers
suivants :
- Un fichier de Clients (clients.dat), où chaque client est caractérisé par son nom,
prénom, adresse et CIN. Un autre champ Etat (de type char) est utilisé pour
marquer si le client est supprimé (Etat = ‘*’).
- Un fichier de comptes (comptes.dat), où chaque compte est caractérisé par le
Numéro de compte, Date de création, Montant, et CIN du client possédant ce
compte. Un autre champ Etat (de type char) est utilisé pour marquer si le compte
est supprimé (Etat = ‘*’).
Sachant qu’un même client peut avoir deux ou plusieurs comptes. Dans ce cas on peut avoir
dans le fichier des comptes plusieurs enregistrements ayant une même valeur de CIN et des
numéros de compte différents.
1- Ecrire une Fonction booléenne ExisteClient qui reçoit le code CIN d’un client et
vérifie s’il existe dans le fichier des clients.
2- Ecrire une Fonction booléenne ExisteCompte qui reçoit un seul paramètre : numéro de
compte et vérifie s’il existe déjà dans le fichier des comptes.
3- Ecrire une procédure NouveauCompte qui reçoit en paramètre un code CIN, un
Numéro de compte et un montant. La procédure doit créer le compte correspondant,
càd ajouter un nouvel enregistrement dans le fichier des comptes (en se basant sur la
date système). Avant de réaliser cette opération, il faut vérifier (on utilisant les
fonctions ExisteClient et ExisteCompte) que le client existe bien et que le numéro de
compte n’est pas déjà attribué.
4- Ecrire une procédure NouveauClient sans paramètres, qui lit les informations
suivantes : CIN, nom, prénom, adresse, Numéro de compte et Montant. Puis ajoute un
nouveau client dans le fichier des clients ensuite lui crée un compte en utilisant la
procédure NouveauCompte. Le Client doit être ajouté de manière a garder le fichier
des clients trié par ordre alphabétique croissant des noms, ensuite des prénoms dans le
cas d’égalité des noms.
5- Ecrire une procédure Virement et une procédure Retrait qui reçoivent en paramètre un
numéro de compte et une valeur réelle et ajoute/retire la valeur au montant
correspondant. L’opération sera enregistrée dans un fichier binaire (operations.dat).
Une opération est caractérisée par les informations : date d’opération, type
d’opération, montant de l’opération.
6- Ecrire une procédure Infos qui reçoit en paramètre un code CIN et construit un fichier
texte contenant les informations suivantes sur le client, sur une même ligne et séparée
par des espaces. Le fichier texte et ouverts en mode ajout.
- le code CIN.
- Nom et prénom.
- Le nombre de comptes dont il dispose.
- Le montant total sur les différents comptes.
7- Ecrire une procédure AllInfos sans paramètres qui utilise la procédure précédente pour
construire un fichier texte contenant les informations successives sur tous les clients
de la banque (chacune dans une ligne).
8- Ecrire une autre procédure pour afficher le contenu du fichier créé dans une table à 4
colonnes (CIN, Nom et Prénom, Nombre de comptes, Montant total).

N. Chenfour 70
9- Ecrire une procédure SupprimeCompte qui reçoit en paramètre un numéro de compte
et fait la suppression logique du compte correspondant. Càd, marquer dans la valeur
du champ Etat avec le caractère ‘*’.
10- Ecrire une procédure UndoSupprimeCompte qui reçoit en paramètre un numéro de
compte et élimine la suppression logique du compte correspondant. Càd, marquer dans
la valeur du champ Etat avec le caractère espace ‘ ’.
11- Ecrire une procédure PackComptes qui supprime physiquement tous les comptes
supprimés logiquement. Càd les élimine complètement du fichier des comptes.
12- Ecrire une procédure SupprimeClient qui reçoit en paramètre un code CIN et fait la
suppression logique de tous les comptes du client correspondant, ainsi que
l’enregistrement qui lui est associé dans le fichier des clients.
13- Ecrire une procédure UndoSupprimeClient qui reçoit en paramètre un code CIN et
élimine toutes les suppressions logiques correspondantes.
14- Ecrire une procédure PackClients qui supprime physiquement tous les clients et
comptes correspondants supprimés logiquement.
15- On veut établir des statistiques concernant l’état et les opérations de la banque. Pour
cela, on réalise les procédures suivantes :
1- Une procédure qui détermine le nombre de clients de la banque.
2- Une procédure qui calcule le montant total de tous les clients créditeurs et celui des
clients débiteurs.
3- Une procédure qui affiche tous les clients qui ont ouvert leurs comptes avant une date
donnée en paramètre.
4- Une procédure qui affiche le nombre et la liste des opérations (virement/retrait)
réalisées à une date donnée.
5- Une procédure qui affiche le nombre et la liste des opérations réalisées pendant un
mois donné.
6- Une procédure qui affiche le nombre et la liste des opérations réalisées pendant un an
donné.
7- Une procédure qui affiche le montant total viré pour les clients pendant un an ou un
mois donné.
8- Une procédure qui affiche le montant total retiré par les clients pendant un an ou un
mois donné.
9- Ecrire une procédure qui affiche la liste des noms et prénoms des clients débiteurs
(c.à.d. ayant un Montant négatif).

N. Chenfour 71

Vous aimerez peut-être aussi