0% ont trouvé ce document utile (0 vote)
11 vues63 pages

Introduction à la programmation en C

Transféré par

johnleysaintthomas6
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
11 vues63 pages

Introduction à la programmation en C

Transféré par

johnleysaintthomas6
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Programmation I

Langage C
2

Plan du cours
CHAPITRE 1 : Introduction. ___________________________________________________ 5
1.1) Les données et les résultats. ________________________________________________ 5
1.2) Le codage. _____________________________________________________________ 6
1.3) Le compilateur.__________________________________________________________ 6
1.4) Comment exécuter un programme avec Dev-C++ ? _____________________________ 7
1.5) Comment obtenir de l’aide lorsqu’on programme en C ? _________________________ 7

CHAPITRE 2 : Les variables. __________________________________________________ 8


2.1) Le nom. _______________________________________________________________ 8
2.2) Le type.________________________________________________________________ 8
2.3) Instruction de déclaration d’une variable. _____________________________________ 9
2.4) Valeur d’une variable. ___________________________________________________ 10

Chapitre 3 : Communication entre le programme et l’utilisateur. ____________________ 11


3.1) Affichage à l’écran. _____________________________________________________ 11
3.2) Notion de précision d’affichage. ___________________________________________ 12
3.3) Lecture au clavier. ______________________________________________________ 12

CHAPITRE 4 : Instructions et expressions. ______________________________________ 14


4.1) Les opérateurs mathématiques. ____________________________________________ 14
4.2) Incrémentation et décrémentation unitaire. ___________________________________ 15
4.3) Expressions simples et expressions mixtes. ___________________________________ 15
4.4) Conversions forcées. ____________________________________________________ 16
4.5) Le type char. ___________________________________________________________ 17
4.6) Conversion int / char et char / int : __________________________________________ 17

Chapitre 5 : Structures conditionnelles. _________________________________________ 18


Conditions composées. ______________________________________________________ 21

Chapitre 6 : Structures de répétition (les boucles). ________________________________ 23


6.1) Boucles While et Do While.. ______________________________________________ 23
6.2) Boucle For. ____________________________________________________________ 23

Chapitre 7 : Les tableaux. _____________________________________________________ 25


Introduction _______________________________________________________________ 26
7.1) Déclaration d’un tableau _________________________________________________ 26
7.2) Insertion des valeurs dans un tableau ________________________________________ 26
7.3) Affichage des valeurs d’un tableau _________________________________________ 27

Chapitre 8 : Les fonctions. ____________________________________________________ 29


Introduction _______________________________________________________________ 29
8.1) L’en-tête de la fonction. __________________________________________________ 29
8.2) Le corps de la fonction ___________________________________________________ 30
8.3) Le positionnement d’une fonction par rapport au programme qui doit l’appeler. ______ 30
8.4) Le prototype d’une fonction. ______________________________________________ 30
8.5) L’appel d’une fonction. __________________________________________________ 30

2
3
8.6) Retour d’une valeur. _____________________________________________________ 30
8.7) Passage d’un tableau en paramètre d’une fonction. _____________________________ 31

Chapitre 9 : Notions de variable locale et globale. _________________________________ 34


9.1) Variable locale _________________________________________________________ 34
9.2) Variable globale ________________________________________________________ 34

Chapitre 10 : Les erreurs. _____________________________________________________ 35


Les types d’erreur. __________________________________________________________ 35

Chapitre 11 : Chaîne de caractères


1. Préambule
2. Lecture et écriture de chaînes
2.1- Avec les fonctions usuelles printf et scanf
2.2- Avec les fonctions spécialisées gets et puts
3. Comparaison de deux chaînes
4. Copie d’une chaîne
5. Longueur d’une chaîne
6. Concaténation de chaîne

Chapitre 12 : Structure
1. Préambule
2. Déclaration d’une structure
3. Déclaration d’une variable de type structure
4. Utilisation d’une structure
4.1- Utilisation des champs d’une structure
4.2- Utilisation globale d’une structure
5. Initialisation de structures
6. La porté du modèle de structure
7. Imbrication de structures
7.1- Structure comportant des tableaux
7.2- Tableaux de structures
7.3- Structures comportant d’autres structures

Chapitre 13 : Pointeur
1. Préambule
2. Déclaration d’un pointeur
3. Désignation de l’adresse d’une variable (Operateur &)
4. Désignation de la valeur pointée par un pointeur (Opérateur *)
5. Les paramètres de type pointeur.
6. Retour d'une adresse à l'issue d'une fonction.
7. Désignation d'un champ d'une variable structurelle à partir de son adresse.
8. Précautions

Chapitre 14 : Tableaux dynamiques


1. Préambule
2. Création d’un tableau dynamique.
3. Parcours d’un tableau dynamique.

3
4
4. Retour ou non du premier élément du tableau.

Chapitre 15 : Accès aux fichiers


1. Préambule
2. Ouverture / fermeture d’un fichier et principe du « stream ».
 Ouverture d’un fichier
 Fermeture d’un fichier
3. Notion de curseur :
4. Lecture et écriture d’un caractère :
5. Lecture et écriture d’une chaîne de caractères
6. Lecture et écriture de valeurs pouvant être accompagnées d’une chaîne de caractères
7. Test de la position du curseur par rapport à la fin du fichier
8. Suppression d’un fichier
9. Réinitialisation du curseur

4
5

CHAPITRE 1 : Introduction.

Programmation :
La programmation c’est le moyen de créer sur un ordinateur une très grande variété d’outils
informatiques, c’est-à-dire des logiciels.

Programme :
Un programme c’est un enchaînement d’opérations élémentaires permettant d’atteindre un
résultat précis à partir de données précises.

Pour réaliser un programme qui fonctionne correctement, il faut donc :


1- déterminer les données du programme (c’est-à-dire les informations sur lesquelles le
programme va être exécuté)
2- déterminer le résultat attendu (c’est-à-dire le but du programme)
3- décider des opérations à utiliser et les ordonner afin que les données soit traitées de telle
manière qu’on obtienne systématiquement le résultat attendu (c’est le principe de
l’algorithmique)
4- s’assurer que chaque instruction respecte rigoureusement sa syntaxe
5- tester le programme et corriger toutes les erreurs de syntaxe et de logique

1.1) Les données et les résultats.

Une des premières difficultés que rencontre un débutant en programmation ou en


algorithmique, c’est de décider d’où vont provenir les données de départ, et que va-t-on faire des
résultats ?
Les données ont deux origines possibles : soit elles proviennent de l’utilisateur du
programme (notion de communication), soit elles proviennent d’une autre partie du programme
(notion d’archivage). Ces deux notions sont à maîtriser absolument.

Exemple : un professeur souhaite créer un programme qui calcule la moyenne de ses élèves en
fonction de leurs notes. Ici, le but recherché, c’est-à-dire le résultat, c’est la moyenne de chaque
élève. Quant aux données de départ, c’est-à-dire ce qui permettra de calculer cette moyenne, ce
seront les notes de chaque élève. Le professeur a donc deux possibilités pour introduire les notes
dans le programme. Première possibilité : il donne les notes au programme en les tapant au
clavier pendant que celui-ci est en cours d’exécution. C’est la technique dite de
« communication » (l’utilisateur va communiquer les données au programme). Deuxième
possibilité : il enregistre préalablement les notes des élèves dans la mémoire ou sur un disque de
l’ordinateur, puis il exécute le programme qui va aller chercher ses données là où elles ont été
stockées. C’est la technique dite d’« archivage » (les données ont été archivées dans la mémoire
ou sur le disque).

Généralement, la technique de l’archivage est inévitablement utilisée quel que soit le


programme que l’on écrit. En effet, dès que l’on utilise la moindre variable, on fait de l’archivage
puisqu’on met une valeur dans la partie de la mémoire allouée à cette variable. D’autre part, il est

5
6
quasiment inévitable de faire suivre une communication d’un archivage, car il faut bien conserver
les données que l’utilisateur a donné au programme.

A la base, l’archivage se fait avec des variables auxquelles on affecte une valeur, mais on
verra qu’il existe d’autres façons d’archiver des données, par exemple en les inscrivant dans un
fichier (c’est-à-dire non plus dans la mémoire vive de l’ordinateur, mais sur un disque).

Puis va venir la question concernant les résultats du programme : que va-t-on en faire ? Là
encore, la question se pose en terme de communication ou d’archivage : va-t-on communiquer les
données à l’utilisateur (en les affichant, par exemple) ? Va-t-on les conserver dans un fichier pour
une utilisation ultérieure ? Va-t-on les mettre à disposition pour que d’autres programmes
puissent s’en servir ?

1.2) Le codage.

On sait que l’ordinateur code toutes les données sous la forme d’enchaînement de « 0 » et
de « 1 ». Chaque valeur (0 ou 1) est placée dans une cellule de la mémoire qu’on appelle un
« bit ». En rassemblant les bits par 4, on forme des quartets, et par 8, on forme des octets. Cette
façon est la plus courante de comptabiliser l’espace mémoire occupée par une donnée. Mais il y a
une notion très importante à bien comprendre dans le codage de l’ordinateur : un code seul
représente une valeur, mais on ne sait pas quel est le type de cette valeur (nombre entier, nombre
flottant, caractère, booléen, image, son, instruction de programme, etc ? ). C’est pour cette raison
que la programmation nécessite une grande attention dans la manipulation des types des données,
qui est d’ailleurs une grande source d’erreurs de logique.

D’autre part, il est bon de rappeler qu’un bit ne peut contenir que 0 OU 1. Il ne peut
contenir les deux en même temps et il ne peut pas ne rien contenir. Par conséquent, tout ce qui
fait référence à une partie de la mémoire ne peut pas être vide (une variable, par exemple,
contient obligatoirement une valeur, même si on ne lui a rien affecté, d’où un risque d’erreur
fréquent chez les débutants en programmation).

1.3) Le compilateur.

On appelle compilateur un logiciel qui traduit les algorithmes écrits dans un langage de
programmation en langage machine.
D’une certaine manière, on peut dire qu’il rend compréhensible pour l’ordinateur les programmes
écrits par un programmeur. Généralement, on lance le compilateur sur un programme pour
vérifier si l’ordinateur le comprend ou s’il repère des erreurs. Attention, l’ordinateur n’est pas
capable de repérer toutes les erreurs d’un programme, mais il s’aperçoit toujours des erreurs de
syntaxe, car ces erreurs rendent le programme inexploitable pour lui. D’autre part, il peut
également signaler tous détails qui lui paraissent douteux au moment de la compilation. C’est ce
qu’on appelle des « warnings » (ou avertissements).

6
7

1.4) Comment exécuter un programme avec Dev-C++ ?

Voici une façon de faire :


- Lancer le logiciel Dev-C++
- Ouvrir le fichier source d’un programme existant ou créer un nouveau fichier source et y
écrire un programme

Ici donner l’exemple du programme « hello world » :

HELLO_WORLD en C

#include <stdio.h>
main()
{
printf("hello, world");
}

- Lancer le compilateur pour vérifier la présence d’éventuelles erreurs (s’il n’y a pas
d’erreur, le compilateur va créer un fichier exécutable de votre programme dans le
répertoire de votre fichier source)
- Corriger les éventuelles erreurs
- Dans le menu Start, lancer « Run »
- Taper « command » ou « cmd » et cliquer sur « Ok », ce qui ouvrira une fenêtre DOS
- Ouvrir le répertoire dans lequel votre fichier source a été enregistré, avec la commande
« cd »
Utilisez quelques commandes DOS si nécessaire. (dir, cd, …)
- Lancer l’exécutable créé à partir de votre fichier source : c’est là que votre programme
s’exécute réellement

1.5) Comment obtenir de l’aide lorsqu’on programme en C ?

Tout d’abord, le logiciel de développement utilisé possède probablement des fichiers


d’aide généralement accessibles par le menu « Aide » ou « Help ». Dev-C++ contient
effectivement ce genre de fichier, mais cette documentation est en anglais et relativement
incomplète. Par contre TcLite contient, lui des fichiers d’aide très précis, en particulier pour tout
ce qui concerne l’utilisation des fonctions prédéfinies. Il suffit donc de lancer TcLite pour
accéder à l’index dans le menu « Help » et y retrouver la page d’explication de chaque fonction
prédéfinie du C (en anglais également). Enfin, dans le cas où ces fichiers n’apportent pas de
réponse satisfaisante, il existe sur Internet divers moyens de trouver de l’aide auprès des
communautés virtuelles de développeurs en C.

7
8

CHAPITRE 2 : Les variables.


Comme en algorithmique, tout le travail de la programmation s’articule autour des notions
de variable et de type. On sait qu’une variable est identifiée par son nom et définie par son type et
sa valeur.

2.1) Le nom.

Bon à savoir
Il est laissé au choix du programmeur au moment de la déclaration, mais avec les contraintes
suivantes :
 les caractères autorisés sont les suivants : toutes les lettres minuscules, toutes les lettres
majuscules, tous les chiffres et le symbole « _ ». Les lettres accentuées (é, è, à, etc…) ou
modifiées (ç, ï, etc…) ne sont pas admises.
 le premier caractère ne doit pas être un chiffre.
 un nom ne doit pas comporter plus de 32 caractères (si on le fait, le compilateur l’accepte,
mais sans tenir compte des caractères superflus, d’où un risque d’erreurs).
 aucun espace n’est admis.
 le langage C respecte la casse, c’est-à-dire que les lettres en minuscules sont différentes
des mêmes lettres en majuscules.
NB : De plus, il est conseillé d’utiliser des noms de variables explicites afin d’améliorer la
lisibilité du code.

Exemples
Identificateurs corrects: Identificateurs incorrects:
nom1 1nom
nom_2 nom.2
_nom_3 -nom-3
Nom_de_variable Nom de variable
deuxieme_choix deuxième_choix
mot_francais mot_français

2.2) Le type.

Le type d’une variable précise l’ensemble des valeurs qu’elle peut contenir, la taille de
son emplacement dans la mémoire de l’ordinateur, la manière dont l’information y est codée et
les opérations autorisées.

8
9

Bon à savoir
Les premiers types de variables disponibles en C sont les suivants :
 int : nombres entiers signés (autrement dit, ce sont les nombres relatifs)
 short : nombres entiers signés codés sur un nombre plus restreint de bits que le type int
 long : nombres entiers signés codés sur un plus grand nombre de bits que le type int
 float : nombres à virgule flottante (approximation des nombres réels)
 double : nombres à virgule flottante codés sur un plus grand nombre de bits que le type
float
 long double : nombres à virgule flottante codés sur un plus grand nombre de bits que le
type double
 char : caractères
Les tailles varient selon les machines. Pour le type int, on peut trouver une taille allant de -
32768 à +32768 ce qui pour donne pour le type unsigned int une taille allant de 0 à 65535.

A lire
De plus, les types int, short et long peuvent être précédés du mot-clef « unsigned » qui
supprime la prise en charge des valeurs négatives. Ainsi, on dispose d’une marge deux fois plus
grande pour les valeurs positives.
D’autre part, on peut remarquer qu’il n’y a pas de type booléen. En fait, en C, les
variables booléennes doivent être simulées avec une variable d’un autre type dont on ne
considérera que deux valeurs possibles. Sachez cependant que le type booléen a été introduit dans
les compilateurs C, mais il est préférable de savoir simuler ce type à l’aide d’une variable d’un
autre type.
Le nombre de bits utilisés pour le codage dépend de la puissance de l’ordinateur utilisé
pour compiler et exécuter le programme, et il peut arriver que deux types proches comme short et
int ou comme float et double, disposent du même nombre de bits sur certaines machines.

2.3) Instruction de déclaration d’une variable.

Bon à savoir

Comme en algorithmique, les instructions de déclaration précèdent les autres instructions.

Syntaxe : <type> <nom> ;

Exemple : int X ;

A lire

La plupart des instructions du langage C sont terminées par un point virgule. L’oubli de ce
symbole engendre inévitablement une erreur de syntaxe lors de la compilation. Par contre, grâce

9
10
à cette contrainte syntaxique, il est tout à fait possible de mettre autant d’instructions que l’on
veut sur la même ligne.

Egalement comme en algorithmique, il est tout à fait possible de déclarer plusieurs


variables de même type dans la même instruction en les séparant par une virgule. Exemple : int
X, Y, Z ;

2.4) Valeur d’une variable.

Lors de sa déclaration, une variable reçoit forcément une valeur, mais une valeur complètement
imprévisible. Il est important de bien comprendre cet aspect, car si on oublie d’initialiser une
variable, on va travailler sur une valeur aléatoire, ce qui fait que l’on obtiendra forcément un
résultat également aléatoire, d’où un important risque d’erreur de logique.

Pour éviter ce genre d’erreur, le langage C autorise l’initialisation des variables à


l’intérieur de l’instruction de déclaration en complétant la syntaxe de la façon suivante :

<type> <nom> = <valeur d’initialisation> ;

Exemple : int X = 5 ;

Au cours du reste du programme, l’affectation de valeur aux variables se fait avec les
mêmes règles qu’en algorithmique, selon la syntaxe suivante :

<nom de la variable> = <valeur> ;

Bon à savoir
Une variable peut recevoir une valeur de deux façons :

Par initialisation :
Syntaxe : <type> <nom> = <valeur d’initialisation> ;

Par affectation :
Syntaxe : <nom de la variable> = <valeur> ;

10
11

Chapitre 3
Communication entre le programme et
l’utilisateur.
Un programme est capable de communiquer à travers tous les périphériques dont dispose
un ordinateur de manière à obtenir les données dont il a besoin et à transmettre les résultats qu’il
trouve. Dans un premier temps, nous nous limiterons aux deux périphériques de communication
avec l’utilisateur les plus courants : l’écran et le clavier.

3.1) Affichage à l’écran.

L’affichage de texte et de valeurs se fait grâce à la fonction printf. Cette fonction est
légèrement plus complexe que la fonction « ecrire » utilisée en algorithmique.

Bon à savoir
Affichage d’un texte :
Syntaxe : printf (« <texte> ») ;
Ex : printf(« Entrez une valeur entière quelconque : » ) ;

Affichage de valeurs des variables et des expressions


Ce type d’affichage se fait en deux temps : d’abord indiquer l’emplacement et le type de la
variable ou de l’expression dans la partie appelée « format d’affichage », ensuite donner la
variable ou l’expression elle-même dans la partie appelée « liste ». Le type est indiqué grâce aux
codes de format suivants :
- %d : types int, short et long
- %c : type char
- %e : types float, double et long double sous la forme exponentielle
- %f : types float, double et long double sous la forme décimale

Syntaxe : printf(« <code de format> », <variable(s) ou expression(s)>) ;


Ex : printf(« %d », x) ;

Affichage du texte et de valeurs des variables et des expressions


Syntaxe : printf(« < le texte puis, le(s) code(s) de format > », < variable(s) ou expression(s)
>) ;
printf (« Voici la valeur de X : %d », X) ;

Pour indiquer l’emplacement où sera affichée la valeur de la variable, il suffit de placer le


code de format correspondant à l’endroit voulu.

11
12
La fonction printf permet également d’afficher le résultat d’une ou plusieurs expressions.
Dans ce cas, il faut bien déterminer le type de l’expression pour pouvoir décider du code de
format que l’on va utiliser.
Exemple : pritnf (« %d », X+ Y) ;

3.2) Notion de précision d’affichage.

Les valeurs de type float sont affichées par défaut avec 6 chiffres après la virgule. Il est
possible de modifier cette précision en indiquant le nombre de chiffres souhaités, précédé d’un
point, après le symbole « % »
Exemples :

x = 1.2345 ;
printf (« %.2f », x) ; On obtient : «1.24»

Une autre façon d’améliorer le gabarit d’affichage consiste à placer des sauts de ligne
grâce au symbole « \n » de manière à améliorer la présentation des données affichées.

Mettre une ligne en commentaire


Syntaxe : // (au début de la ligne)

Mettre plusieurs lignes en commentaire


Syntaxe : /* (au début de la première ligne)
*/ (à la fin de la dernière ligne)
3.3) Lecture au clavier.

La lecture des valeurs tapées au clavier par l’utilisateur se fait avec la fonction scanf. Son
rôle est de recevoir la valeur venant du clavier, de la convertir dans le type voulu et de la placer
dans la variable qui lui a été assignée.

syntaxe : scanf (« <type de la valeur lue> », &< variable d’accueil de la valeur lue>) ;
Exemple : scanf (« %d », &X) ;

Lorsqu’on veut lire plusieurs variables dans une seule instruction, il suffit de répéter la
syntaxe autant de fois que nécessaire.
Exemple : scanf (« %d%d%d », &X, &Y, &Z) ;
Cette instruction lit au clavier trois valeurs de type int et les affecte successivement aux variables
X, Y et Z.
Au moment de l’exécution du programme, si jamais l’utilisateur ne fournit pas
suffisament de données, le programme restera en attente jusqu’à ce que toutes les données
attendues soient fournies par l’utilisateur.
La lecture au clavier lors de l’exécution du programme est assez naturelle : l’utilisateur
tape sa valeur et la valide avec la touche « Entrée ». Tant qu’il ne l’a pas validée, il peut la
modifier à volonté. Lorsqu’il y a plusieurs valeurs à lire, l’utilisateur peut passer de l’une à

12
13
l’autre avec les touches « Entrée », « Espace » ou « Tabulation », mais la dernière doit forcément
être validée par la touche « Entrée ».
En ce qui concerne la lecture des valeurs de type flottant, les codes de format %e et %f
sont équivalents et les valeurs peuvent être lues sous n’importe quelle forme.
Pour la lecture des valeurs de type char, on rencontre certaines difficultés lorsque l’on
souhaite en lire plusieurs successivement : en effet, ici les caractères « Espace », « Tabulation »
ou « le saut de ligne entrée » sont considérés comme des séparateurs et en même temps comme
des caractères. Par conséquent, au moment de la lecture, lorsque l’utilisateur tape par exemple la
touche Entrée pour valider sa saisie, le caractère « saut de ligne » devient disponible pour la
lecture d’un caractère.
Il est possible dans certains cas d’esquiver ce genre de problème en prévoyant
l’introduction d’un séparateur entre deux caractère à lire. Pour cela, il suffit d’introduire un
espace entre les codes de format.
Exemple : scanf (« %c %c », &c1, &c2) ;
scanf (« %d %c », &N, &C) ;

13
14

CHAPITRE 4
Instructions et expressions
 Une instruction est un ordre donné à l’ordinateur selon une syntaxe de programmation.

 Une expression a souvent un type et une valeur qu’il faut savoir déterminer pour prévenir
ou corriger les erreurs de calcul ou de conversion de type.

 Un programme est simplement un enchaînement ordonné d’instructions.

 Une instruction est composée d’opérateurs et d’opérandes (valeurs constantes, variables


ou expressions elles-mêmes composées d’opérateurs et d’opérandes).

 Il est important de bien distinguer l’instruction complète des expressions qui la


composent.

Exemple : X = Y + 5 est une instruction d’affectation composée d’une variable (X), de


l’opérateur d’affectation (=) et d’une expression (Y + 5).

4.1) Les opérateurs mathématiques.

 Les opérations mathématiques de base s’effectuent avec les symboles suivants :


 addition : +
 soustraction et opposé : -
 multiplication : *
 division : /

 Le langage C propose également un autre opérateur appelé « modulo », correspondant au


reste de la division entière. Son symbole est : « % ».
Exemple : 11%4 vaut 3, car la division de 11 par 4 a pour reste 3.

Le symbole modulo n’est pas utilisable avec les valeurs de type Flottant / float.

 Lorsque plusieurs opérateurs mathématiques apparaissent dans la même expression, les


règles de priorité sont les même qu’en algèbre et les parenthèses peuvent être utilisées de
la même manière.
Exemple : dans l’opération A + B * C, on multiplie d’abord B par C, puis on ajoute A. De
plus, l’opérateur % a la même priorité que la multiplication.

Ordre de priorité :
* et / : la priorité se trouve dans l’ordre de placement des opérateurs
Ex : 10 * 2 / 4 = 5
20 / 4 * 2 = 10
+ et - : la priorité se trouve dans l’ordre de placement des opérateurs.

14
15
Ex : 10 + 2 - 4 = 8
14 - 2 + 1 = 13

« * » et « / » sont prioritaires par rapport à « + » et « - »

10 + 5 * 2 = 20
15 – 5 * 2 = 5
20 – 8 / 2 = 16
11 + 6 / 3 = 13

4.2) Incrémentation et décrémentation unitaire.


 Pour l’incrémentation et la décrémentation unitaire d’une variable de type numérique, les
instructions utilisées en algorithmique sont basées sur le schéma de l’exemple suivant : X
<-X + 1 ou X <- X – 1.
En C, il existe une instruction spéciale pour l’incrémentation et la décrémentation unitaire,
dont voici les différentes syntaxes :
Incrémentation : ++ <variable> ou <variable> ++ Ex : ++X, X++
Décrémentation : -- <variable> ou <variable> -- Ex : --X, X--

L’opération X++ ; est entièrement équivalente à celle-ci : X = X + 1 ;

 Ces deux syntaxes ne présentent aucune différence si on les utilise seules en tant
qu’instruction. Ainsi, les instructions X++ ; et ++X ; sont équivalentes. Par contre, si on
utilise ces syntaxes en tant qu’expression à l’intérieur d’une autre instruction, on doit
prendre en compte la distinction suivante :
- ++ <variable> ou -- <variable> : la valeur de cette expression est celle de la variable après
l’incrémentation ou la décrémentation.
- <variable> ++ ou <variable> -- : la valeur de cette expression est celle de la variable avant
l’incrémentation ou la décrémentation.

 De la même manière, il existe en C pour chaque opération mathématique, un opérateur


rassemblant l’affectation et l’opération mathématique. Exemples :

X = X + K ; peut être remplacé par X += K ;


Y = Y * X ; peut être remplacé par Y *= X ;

4.3) Expressions simples et expressions mixtes.

 Une expression simple est une opération ne contenant qu’un seul type de valeurs ou de
variables.
Exemple : l’instruction X = X * 2 ; où X est une variable de type int, est une expression
simple.

 Par opposition, les expressions mixtes sont des opérations dans lesquelles on fait
intervenir des valeurs ou varaiables de type différent, en particulier int et float.

15
16
 Il est important de tenir compte des conversions de type, car elles peuvent être à l’origine
d’une perte de données au niveau du résultat.

 De façon générale, on parle du type d’une expression pour désigner le type du résultat
d’une opération.

 Exercice : soient X et Y de type int, et A et B de type float. Donner le type des


expressions suivantes :

- X+Y
- A*B
- X/Y
- X+A
- X+B*A
- X+Y*B
- X+5
- X + 2.3
- Y*3
- B/2

 Une conversion de type a également lieue lors d’une affectation si la valeur affectée est de
type différent que la variable qui la reçoit. Là encore, il faut donc y être attentif, car cela
peut produire des effets inattendus si la conversion est faite involontairement.

4.4) Conversions forcées.

 Il est tout à fait possible de forcer la conversion d’une variable à l’intérieur d’une
expression de manière à éviter de perdre des données. Il existe un opérateur de conversion
forcée (appelé opérateur de « cast ») pour chaque type. En voici la syntaxe : <variable
d’accueil>= (<Type>) <expression ou variable> ;
Exemple : X= (float) Y / Z ; (on considère que les variables Y et Z sont de type int et X
de type float).

 Par exemple, dans le programme suivant, la division est de type int et on risque donc
d’obtenir un résultat imprécis :

{
int n=5, p=9;
float x;

x = p / n;
printf ("%f\n",x); /* Ici, on obtiendra donc 1 comme résultat */
}

Pour éviter cette perte de données, on va forcer le type de l’expression en float en ajoutant
ce type entre parenthèses à l’intérieur de l’expression elle-même :

16
17
int n=5, p=9;
float x;

x = (float) p / n;
printf ("%f\n",x); /* Ici, on obtiendra 1.8 comme résultat */
}

4.5) Le type char.

 Ce type correspond au type « car » utilisé en algorithmique pour les caractères. Les
valeurs constantes doivent impérativement être placées entre les symboles ‘ et ’ faute de
quoi elles seraient considérées par le compilateur comme des variables et non comme des
valeurs de type char.

 Exemple : lorsqu’on écrit l’instruction « a = ‘e’; » , cela signifie que la variable a reçoit la
valeur « e », alors que l’instruction « a = e ; » signifie que la variable a reçoit la valeur de
la variable e.
4.6) Conversion int / char et char / int :

On peut remarquer que chaque lettre de l’alphabet possède une correspondance de type int.
Ainsi, il est tout à fait possible d’effectuer des opérations arithmétiques sur des valeurs ou des
variables de type char qui seront d’abord converties au type int.

17
18

Exercices
1. Ecrire un programme qui demande deux nombres entiers quelconques, puis qui affiche
leur somme.

2. Ecrire un programme qui lit au clavier deux nombres entiers et un nombre décimal et qui
affiche leur somme, puis leur produit.

3. Ecrire un programme qui demande deux nombres entiers (X et Y) et qui affiche le


quotient de X par Y.

4. Ecrire un programme qui demande deux nombres entiers et qui affiche, le premier après
son incrémentation unitaire et le second après sa décrémentation unitaire.

5. Ecrire un programme qui demande deux nombres entiers, qui incrémente le premier de
trois (3) et décrémente le second de cinq (5), puis qui affiche leur somme.

6. Ecrire un programme qui lit un nombre décimal et qui affiche uniquement la partie
entière.

7. Ecrire un programme qui lit au clavier deux valeurs de type caractère, qui affiche leurs
correspondances numériques, puis leur somme.

8. Ecrire un programme qui lit au clavier trois valeurs de type caractère, qui affiche leurs
correspondances numériques sous la forme décimale, avec deux chiffres après la virgule,
puis leur produit.

18
19

Chapitre 5
Structures conditionnelles
En c il existe deux sortes d’instructions : les instructions simples ( Exemples : affectation,
printf, scanf) et les instructions structurées( Exemples : if, for, while,…).

Pour conditionner l’exécution de certaines instructions sur un test, il existe en C


l’équivalent du « si, alors, sinon, fin si » de l’algorithmique. Voici sa syntaxe :

if (<Condition>)
{
bloc d’instructions 1
}
else
{
bloc d’instructions 2
}

Exemple :
if (x < y)
{
printf (« %d »,x) ;
}
else
{
printf (« %d »,y) ;
}

 Ce que l’on appelle « bloc d’instructions » est simplement un ensemble d’instructions


contenues entre { et }.

 Comme en algorithmique, un bloc d’instructions peut contenir d’autres structures


conditionnelles et donc d’autres blocs d’instructions.

 De plus, le bloc introduit par « else » peut tout à fait être ignoré, c’est-à-dire ce n’est pas
obligatoire d’avoir le bloc d’instruction « else »
 Le bloc d’instruction « else » ne peut être utilisé que si le résultat d’un test a deux
valeurs.
 Le bloc d’instruction « else » tient compte uniquement du « if » qui le précède.

 La condition peut porter aussi bien sur des valeurs numériques que des caractères, à
condition de bien distinguer la signification des opérateurs de comparaison dans chaque
cas. Voici les opérateurs que l’on peut utiliser, avec leurs différentes significations :

Signification pour les valeurs


Opérateur Signification pour les caractères
numériques

19
20
== Egal identique
< strictement inférieur de code inférieur
> strictement supérieur de code supérieur
<= inférieur ou égal de code inférieur ou égal
>= supérieur ou égal de code supérieur ou égal
!= non égal différent

 Tous ces opérateurs de comparaison sont moins prioritaires que les opérateurs
arithmétiques. Par conséquent, il est tout à fait possible de faire porter une condition sur
des expressions.

Exemple :

if (x / 3 == y + 2)
{
Bloc d’instruction
}

 Remarque : il peut arriver qu’une comparaison utilisant l’opérateur « == » sur des valeurs
flottantes donne un résultat inattendu dû au fait que les flottants ne sont que des
approximations des nombres réels.

Autres syntaxes

Un bloc d’instruction peut comporter une seule instruction.

 if(condition)
Instruction1 ;
else
Instruction2 ;

 if(condition)
{
bloc d’instructions1;
}

 if(condition1)
{
bloc d’instructions1;
}

if(condition2)
{
bloc d’instructions 2;
}

if(condition n)
{

20
21
bloc d’instructions n;
}

 if(condition)
{
bloc d’instructions 1;
}

else if
{
bloc d’instructions 2
}

else if
{
Bloc d’instructions 3;
}

else if
{
Bloc d’instructions n;
}

Conditions composées.

Encore comme en algorithmique, il est possible d’utiliser des opérateurs logiques pour
introduire plusieurs tests à l’intérieur d’une condition. Voici la notation de ces opérateurs :

Opérateur Signification
&& Et
|| ou (inclusif)
! Non

« && » et « || » sont moins prioritaires que les opérateurs de comparaisons, alors que « ! »
l’est plus.

21
22

Exercices
1- Ecrire un programme qui demande la moyenne d’un élève (sur 10) et qui affiche le
message « Admis » si sa moyenne est supérieure ou égale à cinq (5) ou « Echec » si sa
moyenne est inférieure à cinq (5)

2- Ecrire un programme qui lit au clavier un nombre entier quelconque et qui affiche le
message « le nombre est pair » si le nombre entré est pair ou « Le nombre est impair » s’il
est impair.

3- Ecrire un programme qui demande deux nombres entiers et qui affiche le plus grand des
deux s’ils sont différents f et un message indiquant s’ils sont égaux dans le cas contraire.

4- Même exercice que précédemment, mais en affichant le plus petit des deux.

5- Ecrire un programme qui demande deux nombres entiers et qui affiche leur différence.
(Eviter d’avoir un résultat négatif).

6- Ecrire un programme qui demande deux nombres entiers et qui affiche un message
indiquant si les deux nombres sont égaux ou différents.

7- Ecrire un programme qui demande deux nombres entiers, qui compare leur somme et leur
produit et qui affiche le résultat correspondant par les suivants :
- « La somme est supérieure au produit »
- « Le produit est supérieur à la somme ».
- « La somme est égale au produit ».
La condition doit être portée sur des expressions.

8- Ecrire un programme qui demande deux nombres entiers et qui affiche un message
indiquant si le plus grand des deux est pair ou impair.

9- Ecrire un programme qui demande un nombre compris entre 1 et 25 et qui affiche le


message « Vous avez gagné » si le nombre se termine par un zéro (0) ou « vous avez
perdu » dans le cas contraire.

10- Ecrire un programme qui demande deux nombres relatif à l’utilisateur, puis qui affiche un
message indiquant si le produit est positif, négatif ou nul.

NB : On ne doit pas calculer le produit.

11- Ecrivez un programme qui demande trois nombres entiers et qui affiche le plus grand des
trois.

12- Ecrivez un programme qui demande trois nombres entiers et qui affiche un message
indiquant si le plus grand des trois est pair ou impair.

22
23

Chapitre 6
Structures de répétition (les boucles)
Les structures de répétition appelées aussi boucles, sont considérées comme les structures les plus
puissantes de la programmation, elles consistent à exécuter à plusieurs reprises une suite
d’instructions. En langage C comme dans la plupart des autres langages de programmation, ces
répétitions sont de deux sortes :
Conditionnelle (ou indéfinies) ; la poursuite ou l’interruption de la répétition des instructions
concernées dépend d’une certaine condition ;
Inconditionnelles (ou avec compteur ou définies) : les instructions concernées sont répétées un
nombre donné de fois.
En langage C il existe deux instructions permettant de réaliser des répétitions conditionnelles
L’instruction do…while et l’instruction while.

6.1) Boucles While et Do While..

L’instruction do…. while permet de réaliser une structure de répétition conditionnelle, dans
laquelle la décision de poursuite de la répétition est effectuée à la fin de l’exécution des
instructions concernées. En langage C il existe une autre instruction appelée while, analogue à la
précédente, dans laquelle la décision de poursuite de la répétition est effectuée avant l’exécution
des instructions concernées.

L’équivalent en C de la boucle « Faire tant que » de l’algorithmique utilise la syntaxe suivante :

do
{
<Bloc d’instructions>
}
while (<Condition>) ;

L’équivalent en C de la boucle « Tant que » de l’algorithmique utilise la syntaxe suivante :

while (<Condition>)
{
<Bloc d’instructions>
}

Ces boucles s’utilisent en C exactement comme en algorithmique et comme dans la


grande majorité des langages de programmation.

6.2) Boucle For.

23
24
Comme nous l’avons dit l’instruction for permet de réaliser des répétitions inconditionnelles,
c’est-à-dire dont le nombre de tours est déterminé.

L’équivalent en C de la boucle « Pour » de l’algorithmique utilise la syntaxe suivante :

for (<affectation de départ> ; <test d’arrivée> ; <instruction d’incrémentation>)


{
<Bloc d’instructions>
}

Attention, contrairement à l’algorithmique, la limite de la boucle for n’est pas une


« valeur d’arrivée », mais un « test d’arrivée ».

Exemple de boucle « for » utilisant comme compteur la variable comp de type int :

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


{
printf(« %d », comp) ;
}

24
25
1. Ecrivez un programme qui affiche le message bonjour 10 fois.

2. Ecrivez un programme qui demande un nombre décimal quelconque à l’utilisateur, puis


qui l’affiche 8 fois.

3. Ecrivez un programme qui demande un nombre entier N à l’utilsateur, puis qui affiche le
message « Bonjour » N fois.

4. Ecrivez un programme qui demande deux nombres entiers X et Y, puis qui affiche le
nombre Y x fois.

5. Ecrivez un programme qui demande un nombre entier supérieur à 50, et qui le redemande
(s’il est incorrect) jusqu’à ce que l’utilisateur donne un nombre correct.

6. Ecrivez un programme qui demande un nombre entier quelconque, puis affiche les entiers
compris entre ce nombre et 100.

7. Ecrivez un programme qui demande un nombre entier quelconque, puis affiche les entiers
pairs compris entre ce nombre et 100.

8. Ecrivez un programme qui demande un nombre entier quelconque, puis affiche les entiers
impairs compris entre ce nombre et 100.

9. Ecrivez un programme qui affiche les carrés des nombres pairs compris entre 12 et 20.

25
26

Chapitre 7
Les tableaux
Introduction
Dans ce chapitre, nous allons essentiellement étudier les tableaux statiques à une dimension. Le
principe des tableaux en C est le même qu’en algorithmique, avec les mêmes notions de
dimension, de taille, de cellule et d’indice.
Cellule
C’est le plus petit élément constitutif d’un tableau
Dimension
C’est le nombre de cellules que contient un tableau.
Taille
C’est le nombre de cellules pleines dans un tableau
Indice
C’est un numéro qui identifie chaque cellulle d’un tableau.

N.B: En C, la première cellule d’un tableau est forcément d’indice 0.

7.1) Déclaration d’un tableau


Syntaxe : <type> <nom> [<dimension>] ;
Exemple : int Tab [5] ;
C’est la déclaration d’un tableau de type int et de dimension 5
7.2) Insertion des valeurs dans un tableau
Les valeurs peuvent être inésrées dans un tableau de trois facons différentes :

1- Par l’initialisation
Syntaxe : <type> <nom> [<dimension>] = {<liste des valeurs séparées par des virgules>} ;
Exemple : int Tab [5] = {1,5,3,4,7}

N.B : L’initialisation peut ne remplir qu’une partie du tableau si on affecte moins de valeur qu’il
ne peut en contenir. Evidement, ce sont les premières cellules qui recevront ces valeurs.

Exemple : int Tab [5] = {1, 5, 3}

2- Par affectation
Syntaxe : <nom du tableau> [<indice>] = <la valeur> ;
Exemple : tab[1]=9 ;

3- Par l’utilisateur
Syntaxe : scanf(« symbole du type du tableau », &<Nom du tableau> [<indice>]) ;

26
27

Technique classique pour le remplissage d’un tableau par l’utilisateur, technique


aussi appelée « lecture d’un tableau au clavier ») :

for (<compteur> = 0 ; <compteur> < <Dimension> ; <compteur> ++)


{
printf (« Donnez la valeur de la cellule %d, SVP : \n », <compteur>) ;
scanf (« <Symbole du type du tableau> », &<Nom du tableau> [<compteur>]) ;
}

Exemple :

int Tab [10] ;


for (c = 0 ; c < 10 ; c++)
{
printf (« Donnez la valeur de la cellule %d, SVP\n », c) ;
scanf (« %d », &Tab [c]) ;
}

7.3) Affichage des valeurs d’un tableau


Syntaxe : printf(« symbole du type du tableau », <Nom du tableau> [<indice>]) ;

Techniques classiques pour l’ affichage du contenu d’un tableaux.

for (<compteur> = 0 ; <compteur> < <Dimension> ; <compteur> ++)


{
printf (« <Symbole du type du tableau>\n », <Nom du tableau> [<compteur>]) ;
}

Exemple :
int Tab [10] = {1,2,3,4,5,6,7,8,9,10};
for (c = 0 ; c < 10 ; c++)
{
printf (« %d\n », Tab [c]) ;
}

27
28

Exercices
1. Ecrire un programme qui initialise un tableau d'entier de dimension 7 avec les valeurs
suivantes : 15, 23, 34, 12, 65, 34, 76 et qui affiche ensuite le contenu du tableau.

2. Ecrire un programme qui initialise un tableau de caractère de dimension 6 avec les valeurs
suivantes : d, e, q, t, y,s, puis qui affiche le contenu du tableau.

3. Ecrire un programme qui lit au clavier les valeurs d'un tableau de type flottant, de
dimension 5, et qui affiche ensuite les valeurs du tableau.

4. Ecrire un programme qui demande les valeurs d’un tableau d'entier de dimension 7, puis
qui affiche les valeurs de la 1ère, 3ème et dernière cellule.

5. Ecrire un programme qui demande les valeurs d’un tableau d'entier de dimension 8, puis
qui affiche les valeurs paires du tableau.

6. Même exercice que précédemment mais en affichant les valeurs impaires du tableau.

7. Ecrire un programme qui lit au clavier les valeurs d'un tableau d'entier de dimension 6 et
qui affiche ses valeurs dans l'ordre inverse, c'est-à-dire de la dernière cellule à la première.

8. Ecrivez un programme qui demande les valeurs d’un tableau d’entiers de dimension 5,
puis qui affiche la plus grande valeur du tableau.

9. Ecrivez un programme qui demande les valeurs d’un tableau d’entiers de dimension 5,
puis qui affiche la plus petite valeur du tableau.

10. Ecrivez un programme qui demande les valeurs d’un tableau d’entiers de dimension 6,
puis qui calcule et affiche la somme des valeurs du tableau.

11. Ecrire un programme qui lit au clavier les moyennes de 6 étudiants et qui affiche la
moyenne du meilleur étudiant.

12. Ecrire un programme qui demande en fin de session les notes finales de 8 étudiants. On
considère que les tous les étudiants qui étaient en reprise (c'est-à-dire qui avaient une note
comprise entre 59 et 65) ont réussi, c'est-à-dire qu'ils ont comme note finale 65. Donc il
faut modifier toutes les cellules qui ont une note comprise entre 59 et 65, en leur
attribuant la note 65.

28
29

Chapitre 8
Les fonctions
Introduction
 Les fonctions en C reprennent le même principe qu’en algorithmique, mais il faut prendre
ici en compte l’organisation des fonctions par rapport aux programmes qui les appellent.
Il existe deux situations principales : l’appel d’une fonction prédéfinie et la définition
d’une fonction particulière en vue d’un appel ultérieur.

 Les fonctions prédéfinies sont stockées dans des fichiers biliothèques qui possèdent
l’extension « .h ». L’appel d’une telle fonction nécessite donc que l’on sache à quelle
bibliothèque elle appartient et que l’on introduise cette bibliothèque au programme. Pour
cela, on utilise l’instruction « #include » au tout début du programme avec la syntaxe
suivante : #include < <chemin d’accès de la bibliothèque> >

 En ce qui concerne les fonctions particulières définies uniquement dans le cadre du


développement d’un programme, elles font généralement partie du programme et sont
donc placées directement dans le fichier source du programme.

Pour tout ce qui concerne la déclaration, la définition et l’utilisation (appel) d’une fonction, toutes
les notions suivantes sont à connaître et à maîtriser :

8.1) L’en-tête de la fonction.

Syntaxe : <Type de la valeur retournée> <Nom de la fonction> (<Paramètres>)


Exemple : int Test (int x, float y, char z)

N.B :
 On utilise le mot-clef « void » pour signaler l’absence de valeur de retour ou de
paramètre.
Exemples :
 void Test (int x, int y)
 int Test_2 (void)

 Attention, il n’est pas possible en C de rassembler les paramètres de même type en


indiquant une seule fois le type. C’est-à-dire que pour chaque paramètre, il faut
indiquer le type, même si le paramètre précédent est du même type.
Exemple : int Test (int x, int y, float z)

29
30
8.2) Le corps de la fonction

L’ensemble du corps de la fonction doit être encadré par des accolades comme pour tout
bloc d’instructions.

8.3) Le positionnement d’une fonction par rapport au


programme qui doit l’appeler.

Il existe deux façons de faire :


 on place la fonction avant le programme qui va l’appeler.
 Ou on la place après le programme qui va l’appeler et on introduit dans ce dernier le
prototype de la fonction.

Dans les deux cas, l’idée est la même : faire en sorte que le programme qui doit appeler une
fonction la connaisse ou ait au moins une référence à celle-ci.

8.4) Le prototype d’une fonction.

Syntaxe : <Type de la valeur retournée> <Nom de la fonction> (<Type des paramètres>) ;


Exemple : int Test (int, float, char)
Attention, ici, on n’indique pas le nom des paramètres, mais seulement le type de chacun
d’entre eux (en répétant le type si plusieurs paramètres de même type se suivent).

Exemple : int Test (int, int) ;

8.5) L’appel d’une fonction.

Deux cas peuvent se présenter :


 Si la fonction ne retourne aucune valeur.
Syntaxe : <nom de la fonction> (<paramètre (s)>) ;
Exemple : Test (x, y, z) ;
 Si la fonction retourne une valeur.
Syntaxe : <variable d’accueil de la valeur> = <nom de la fonction> <paramètre (s)>

Exemple : r = Test (x, y, z) ;

la valeur de chaque paramètre doit être fournir dans l’ordre prévu dans la définition de la
fonction.
La valeur d’un paramètre peut être une varaiable, une constante, une expression ou le retour
d’une fonction.
8.6) Retour d’une valeur.
Une fonction peut en plus retourner une valeur du type défini dans son en-tête.

Syntaxe : return <valeur de retour> ;


Ou : return (<valeur de retour>) ;

30
31
 Contrairement à l’algorithmique, la valeur à retourner n’a pas forcément besoin d’être
placée entre parenthèses. Il peut s’agir là encore d’une constante, d’une variable ou de
n’importe quelle expression.

 Par contre, le principe du retour est exactement le même qu’en algorithmique : lorsqu’on
exécute l’instruction return, on sort immédiatement de l’exécution de la fonction en cours,
ce qui empêche le retour simultané de plusieurs valeurs pour une même fonction.

Exemples
 void somme (int x, int y)
{
printf(« La somme de x et y est : %d »,x+y) ;
}

 int somme (int x, int y)


{
return x+y ;
}

 int somme ()
{
int x, y ;
printf(« Donnez la valeur de x et y ») ;
scanf(« %d%d »,&x,&y) ;
return x+y ;
}

 void somme ()
{
int x, y ;
printf(« Donnez la valeur de x et y ») ;
scanf(« %d%d »,&x,&y) ;
printf(« Leur somme est : %d »,x+y) ;
}

8.7) Passage d’un tableau en paramètre d’une fonction.

Comme en algorithmique, on peut indiquer ou pas la dimension du tableau selon les


besoins de la fonction, mais c’est toujours la présence des crochets qui indique qu’on a à faire à
un tableau et non à une variable classique. Il en va d’ailleurs de même pour le prototype d’une
fonction prenant un tableau.

Exemple de prototype d’une telle fonction : int Test (int [ ], int) ;

31
32

Lorsqu’on passe un tableau en paramètre, on le transmet sous la forme d’une adresse, ce qui
apporte comme avantage que le tableau n’a pas besoin d’être retourné : toute modification faite
sur le tableau à l’intérieur de la fonction appelée modifie le tableau qui a été fourni en paramètre
à cette fonction.

Appel d’une fonction prenant un tableau en paramètre :


Syntaxe : <Nom de la fonction> (<Nom du tableau>) ;
Exemple : test (tab) ;

32
33

Exercices
1. Ecrire une fonction qui affiche le message bonjour.
NB : Placez la fonction avant et après la fonction principale.

2. Ecrire une fonction qui prend deux nombres entiers constants en paramètre, qui calcule et
retourne leur somme. Le résultat doit être affiché dans le main (ou la fonction principale).

3. Ecrire une fonction qui prend deux nombres décimaux en paramètre, qui calcule et retourne
leur somme. Le résultat doit être affiché dans le main.
NB : Les deux nombres doivent être fournis par l’utilisateur.

4. Ecrire une fonction qui prend deux nombres entiers quelconque, qui calcule et affiche leur
différence
NB : Les deux nombres doivent être fournis par l’utilisateur.

5. Ecrire une fonction qui prend en paramètre le taux par heure et le nombre d’heure de travail
d’un employé par mois, puis qui calcule et affiche :
Son salaire mensuel.
Son économie annuelle, sachant que l’employé dépense 40 % de son salaire.
Son salaire annuel
Son économie annuelle

6. Même exercice que précédemment, mais en affichant la dépense annuelle dans la fonction
principale.

7. Ecrire une fonction qui demande le prix d’un crédit et le nombre de cours choisi par
étudiant pour une session, puis qui calcule et affiche le montant à verser par l’étudiant dans
la fonction principale.

8. Ecrire une fonction qui demande le prix unitaire et la quantité vendue d’un produit, puis qui
calcule et affiche le prix de vente total.

Tableaux

9. Ecrire une fonction qui calcule et retourne la somme des valeurs d’un tableau de type
entier, reçu en paramètre. Le résultat doit être affiché dans la fonction principale.
NB : les valeurs du tableau doivent être fournies par l’utilisateur.

10. Ecrire un programme se servant d’une fonction pour incrémenter de 2, la valeur de chaque
cellule d’un tableau d’entier de dimension 5. Afficher les valeurs du tableau après
l’incrémentation dans la fonction principale.
NB : les valeurs du tableau doivent être fournies par l’utilisateur.

33
34

Chapitre 9
Notions de variable locale et globale.
9.1) Variable locale
Une variable « locale » est une variable déclarée à l’intérieur d’une fonction. Sa valeur ne
peut être considérée que lors de l’appel de la fonction et elle est indisponible pour tout autre
fonction, y compris pour le main. De plus elle perd sa valeur dès que l’on sort de la fonction et
elle ne peut en recevoir une qu’au moment de l’appel de la fonction.

9.2) Variable globale


Une variable « globale » est une variable déclarée au début d’un fichier source et en
dehors de toute fonction. Elle n’appartient pas à une fonction particulière et est disponible pour
toutes les fonctions du fichier, y compris pour le main. De plus, lorsqu’on passe d’une fonction à
une autre lors d’un appel ou lorsqu’une fonction a fini de s’exécuter, les variables globales
conservent leur valeur actuelle. Enfin, une variable globale qui n’est pas initialisée lors de sa
déclaration reçoit automatiquement la valeur 0 contrairement aux variables locales qui reçoivent
une valeur aléatoire lorsqu’elles ne sont pas initialisées.

Du fait de leur disponibilité très large, les variables globales risquent souvent de créer des
conflits. C’est pour cette raison qu’il faut limiter au maximum l’utilisation de ces variables et
privilégier l’utilisation des paramètres et des retour de fonction pour échanger des valeurs entre
les fonctions.

De plus, une variable globale peut être cachée : cela se produit lorsqu’une variable locale
d’une fonction possède le même nom qu’une variable globale. Dans ce cas, la variable globale
n’est plus accessible pour cette fonction.

34
35

Chapitre 10
Les erreurs
Lors de l’écriture d’un programme, il y a de fortes chances pour qu’on rencontre des
erreurs de différents types que l’on devra corriger pour que le programme fonctionne
correctement. Ces corrections supposent que l’on soit capable de distinguer les différents types
d’erreur et de diagnostiquer chacune d’entre elle (c’est-à-dire de repérer en quoi elles consistent
et où est-ce qu’elles se situent dans le programme).

Les types d’erreur.


On distingue les différents types d’erreur par la façon dont elles se manifestent :

10.1- Erreurs de syntaxe :


Ce type d’erreur apparaît lors de la compilation, et c’est le compilateur qui va indiquer chacune
d’entre elles, généralement dans une fenêtre prévue à cet effet. Ce type d’erreur bloque la
compilation et empêche la création ou la mise à jour du fichier exécutable. Elles consistent en une
mauvaise mise en place des instructions qui ne respectent pas la syntaxe du langage C. Les cas
les plus courants : fautes d’orthographe dans les noms de fonction, omission d’un point-virgule,
d’une parenthèse, des accolades, ect…
 N.B : La compilation d’un fichier source dont l’éxécutable est en cours d’éxécution vous
affiche un message également.

10.2- Erreurs de logique :

Ce type d’erreur apparaît lors de l’exécution, mais pas sous la forme d’un message d’erreur. Elle
se traduit par l’apparition d’un résultat incohérent par rapport aux données sur lesquelles on a
exécuté le programme. C’est pour cette raison qu’il faut toujours tester un programme dans toutes
les situations possibles (en particulier sur les cas particuliers) pour vérifier s’il ne contiendrait pas
ce genre d’erreur.
Les cas les plus courants : se tromper de variable lors d’un l’afichage, se tromper de code de
format, se tromper dans l’utilisation des opérateurs ( +,-, *, /, ( = et = = dans les conditions)), etc.

10.3- Erreurs de mémoire :


Ces erreurs sont des erreurs de logique qui peuvent se manifester d’une façon particulière. Soit
elles vont apparaître comme une simple erreur de logique par un résultat incohérent, soit c’est le
système d’exploitation qui va arrêter l’exécution du programme et afficher un message d’erreur
« système ». En effet, les erreurs de mémoires sont appelées ainsi car elles sont issues d’une
mauvaise gestion de la mémoire de l’ordinateur contrôlée par le système d’exploitation. Les
causes de ces erreurs sont généralement liées à une mauvaise manipulation d’un tableau ou d’un
pointeur.

35
36
Les cas les plus courants sont les suivants : omission du symbole « & » dans un « scanf »,
tentative d’accès à une cellule d’indice supérieur à la dimension d’un tableau et tentative d’accès
à une donnée d’un pointeur qui ne pointe sur rien ou sur NULL.

36
37

Chapitre 11
Les chaînes de caractères

11.1- Préambule

Une chaîne de caractères est une suite de caractères quelconques. Jusqu’ici nous avons
utilisé de telles chaînes dans les formats des instructions scanf et printf, qui permettent de lire ou
d’écrire un seul caractère.

Dans certaines situations, on aimerait disposer de variables capables d’accueillir des


chaînes de caractères susceptibles d’évoluer (à la fois en contenu et en nombre de caractères) au
fil de l’exécution du programme. Certains langages disposent à cet effet d’un « type chaîne ».

Le langage C, quant à lui, ne comporte pas de véritable chaîne ; certes, avec ce que nous
avons étudié jusqu’ici, il est possible de placer une suite de caractères dans un tableau de
caractères (éléments de type char). Cependant, quelques contraintes apparaissent alors :

 Nous ne savons pas comment gérer des chaînes dont la longueur serait différente de la
dimension du tableau.
 La lecture des caractères de notre tableau devraient se faire caractère par caractère et non
globalement.

En fait, le langage C, vous offre quelques outils facilitant la manipulation de telles chaînes,
pour peu qu’on respecte une convention particulière pour leur représentation, à savoir
« marquer » leur fin d’un caractère spécial de code 0. Dans ce cas, en effet, vous pourrez :

 lire ou écrire globalement une chaîne, en faisant appel, soit aux fonctions printf ou scanf
et à un code de format approprié, soit à de nouvelles fonctions spécifiques (gets et puts).

 réaliser des traitements propres aux chaînes, tels que les comparaisons, la recopie, la
concaténation, en faisant appel à des fonctions prévues à cet effet.

11.2- Lecture et ecriture de chaînes

11.2.1- Avec les fonctions usuelles printf et scanf

Soit un tableau de caractères déclaré par :


Char nom[30] ;
L’instruction : scanf(« %s », nom) ; ou scanf(« %s »,&nom[0]) ;

va lire une suite de caractères au clavier pour les ranger dans le tableau nom, en
commençant à partir de nom[0] et en ajoutant automatiquement, à la suite, un caractère de fin de
chaîne (caractère de code nul).

37
38
Le code de format %s fonctionne comme les codes de format numériques et non comme
le code de format %c. Autrement dit, il commence par sauter les délimiteurs éventuels (espace ou
fin de ligne) et il s’interrompt à la rencontre de l’un de ces délimiteurs ; il ne permet pas donc de
lire des chaînes contenant des espaces. Nous verrons que, pour y parvenir, il faut utiliser une
fonction spécialisée nommée « gets ».

De même l’instruction :
printf(« %s »,nom) ; ou printf(« %s »,&nom[0]) ;

va afficher à l’écran, les caractères trouves dans le tableau nom, en commençant par
nom[0] et en s’interrompant à la rencontre d’un caractère de fin de chaîne.

Lorsque vous lisez une chaîne de n caractères, il faut prévoir un emplacement d’au moins
n+1 caractères, compte tenu du caractère supplémentaire de fin de chaîne.

Une chaîne peut bien ne contenir aucun caractère (autre que celui de fin) ; on parle de
« chaîne vide ».

Ne confondez pas le caractère de fin de chaîne, qui est introduit automatiquement par
scanf pour indiquer, en mémoire, la fin d’une chaîne, avec le délimiteur (espace ou fin de ligne)
qui a servi à détecter la fin de donnée fournie par l’utilisateur ; ce délimiteur n’étant d’ailleurs pas
recopié en mémoire.

11.2.2- Avec les fonctions spécialisées gets et puts

Il existe deux fonctions manipulant exclusivement des chaînes (une seule à la fois), qui
complètent utilement les possibilités du code de format %s.

Ainsi, toujours la déclaration précédente, l’instruction :


gets(nom) ;

Lit une suite de caractères en la rangeant dans le tableau nom, terminée par un caractère
de fin de chaîne ; cette fois :
 Aucun délimiteur n’est sauté avant la lecture.
 Les espaces sont lues comme les autres caractères
 La lecture se termine à la rencontre d’un caractère de fin de ligne.

De même, l’instruction :
puts(nom) ;

Affiche les caractères trouvés à partir de nom[0], en s’interrompant à la rencontre de du


caractère de fin de chaîne et réalise un changement de ligne (il s’agit, somme toute, de la seule
différence de comportement avec le code de format %s dans printf).

11.3- Comparaison de deux chaînes (strcmp)

Syntaxe : strcmp(chaîne1, chaîne2) ;

38
39
Cette fonction (Abréviation de STRing CoMParison, en français « comparaison de
chaînes » et dont le prototype figure, cette fois, dans string.h) permet de comparer deux chaines
de caractères et fournit en résultat une valeur entière qui peut être :

 Positive si chaîne1 arrive après chaîne2.


 Nulle si chaîne1 est égale à chaine2.
 Négative si chaîne1 arrive avant chaîne2.

Exemple : x=strcmp(mot1,mot2) ;
Avec x une variable de type int et mot1, mot2 deux tableaux de caractères.

11.4- Copie d’une chaîne (strcpy)

Cette fonction permet de recopier globalement (d’un coup) une chaîne de caractères dans
une autre. (Abréviation de STRing CoPY, en français « copie de chaîne »).

Comme on peut s’y attendre, il n’est possible d’affecter directement une chaîne à une
autre, pas plus qu’il n’était possible d’affecter globalement le contenu d’un tableau à un autre.

Syntaxe : strcpy(destination, source) ;

Cette fonction recopie la chaîne source dans la chaîne destination.

Il est nécessaire que la taille du tableau réservé pour la chaîne « destination » soit
suffisante pour accueillir la chaîne à recopier.

La fonction strcpy recopie tous les caractères qu’elle trouve, jusqu’à la rencontre d’un
caractère de fin de chaîne, et ceci quel que soit le nombre de caractère en question. Il existe une
autre fonction, nommée strncpy, analogue à strcpy qui permet, grâce à un paramètre
supplémentaire, de limiter le nombre de caractères pris en compte.

Syntaxe : strncpy(Destination, Source, nombre de caractères) ;


Exemple : Strncpy(mot1, mot2, 5) ;

On ne recopiera pas plus de 5 caractères de mot2 dans mot1.

11.5- Longueur d’une chaîne

Pour obtenir la longueur d’une chaîne, on utilise la fonction strlen


Abréviation de STRing LENgth, en français « longueur de chaîne »

Syntaxe : strlen(chaîne) ;
x=strlen(mot) ;
Considérant x comme une variable de type int et mot comme une chaîne de caractères.

11.6- Concaténation de chaîne (strcat)

39
40
Dans tous les langages disposant d’un type chaîne, on nomme concaténation l’opération
qui consiste à fabriquer une chaîne en mettant bout à bout deux autres chaînes. Par exemple, le
résultat de la concaténation de « mon » et « sieur » serait « monsieur ».

Syntaxe : strcat(destination, source) ;

Assez curieusement, cette fonction concatène la chaîne source (sans la modifier) à la


chaîne destination qui se trouve donc, quant à elle, modifiée (sauf si la chaine source est de
longueur nulle). Dans certains cas, il pourra être nécessaire de recopier la chaîne destination,
avant d’appeler cette fonction.

La fonction strcat concatène à la chaîne destination tous les caractères qu’elle trouve dans
la chaîne source, et ceci quelle que soit la longueur de cette dernière. Il existe une fonction,
nommée strncat, analogue à strcat qui permet, grâce à un paramètre supplémentaire, de limiter le
nombre de caractères concaténés.

Syntaxe : strncat(destination, source, nombre de caractères) ;


Exemple : strncat(mot1, mot2, 5) ;
On ne concatènera pas plus de 5 caractères de mot2 à mot1.

40
41

Exercices
1- Ecrivez un programme qui demande les informations d’un employé comme : son nom, son
prénom, sa fonction et son salaire, puis qui les affiche.

2- Ecrivez un programme qui demande le nom, le prénom et la note de programmation d’un


étudiant qui les stocke, puis qui les affiche.

3- Ecrivez un programme qui demande le numéro de compte d’un client (d’une banque), son
nom, son prénom et son solde, qui les stocke puis qui les affiches.

4- Ecrivez un programme qui demande deux chaînes de caractère, qui les compare puis qui
affiche l’un des sages suivants :
Les deux chaînes sont identiques
Les deux chaînes sont différentes

5- Ecrivez un programme qui demande deux chaînes de caractères, qui les compare puis qui
affiche l’un des messages suivants :
:
 Les deux chaînes de caractères sont identiques
 La 1ere chaîne se trouve avant la 2eme, au sens de l’ordre défini par le code des
caractères
 La 1ere se trouve après la 2eme, au sens de l’ordre défini par le code des caractères.

6- Ecrivez un programme qui demande deux chaînes de caractères, qui échange les valeurs des
tableaux contenant ces chaînes, puis qui les affiche.

7-Reprenez l’exercice trois (3), mais en utilisant à chaque lecture des chaînes de caractères le
tableau X (char x [20], puis le programme doit transmettre le contenu du tableau X dans un autre
tableau avant la lecture d’une prochaine chaîne de caractères.

8- Ecrivez un programme qui demande le nom et le prénom d’une personne, qui crée une adresse
électronique (yahoo) pour cette personne avec son nom, suivi de son prénom, puis qui affiche
l’adresse électronique.
Exemple : Nom : bateau Prénom : denis adresse électronique : bateaudenis@[Link]

9-Ecrivez un programme qui demande le nom et le prénom d’une personne, qui crée une adresse
électronique (yahoo) pour cette personne constituée des trois premiers caractères du nom et des
deux premiers caractères du prénom, puis qui affiche l’adresse électronique.
Exemple : Nom : bateau Prénom : denis adresse électronique : batde@[Link]

9- Ecrivez un programme qui demande une chaîne de caractères, puis qui affiche le nombre de
caractères de la chaîne.

10- Ecrivez un programme qui demande une chaîne de caractère, qui copie les trois (3) premiers
caractères dans un tableau Y ( char y [4]), puis qui affiche le tableau Y.

41
42

Chapitre 12
Les structures

12.1- Préambule

Une structure permet de designer sous un seul nom un ensemble de valeurs pouvant être de types
différents.

La structure est constituée d’un ensemble d’éléments appelés champ. Comme une variable
scalaire, chaque champ a un type et un nom.

L’accès à chaque élément (nommé champ) de la structure se fait, cette fois, non plus par une
identification de position, mais par son nom au sein de la structure.

12.2- Déclaration d’une structure


Syntaxe
struct <Nom de la structure>
{
<Type champ1> <Nom champ1> ;
<Type champ2> <Nom champ2> ;
<Type champ3> <Nom champ3> ;
……………….
<Type champ n> <Nom champ n> ;
};

Exemple :
struct article
{
int numero ;
int qte ;
float prix ;
};

Celle-ci définit un modèle de structure, mais ne réserve pas de variable correspondant à cette
structure. Une fois un modèle défini, nous pouvons déclarer des variables du type correspondant.

12.3- Déclaration d’une variable de type structure

Syntaxe : struct <nom de la structure> <nom de la variable> ;


Exemple : struct article art1, art2, x ;

Bien que ce soit peu recommandé, sachez qu’il est possible de regrouper la définition du modèle
de structure et la déclaration des variables dans une seule instructions, comme dans cet exemple :

42
43

struct article
{
int numero;
int qte;
float prix;
} art1, art2, x ;

Dans ce dernier cas, il est même possible d’omettre le nom de modèle (article), à condition, bien
sûr, que l’on n’ait pas à déclarer par la suite d’autres variables de ce type.

12.4- Utilisation d’une structure


Il est possible d’utiliser une variable d’un type structure de deux manières :
 En travaillant individuellement sur chacun des champs de la structure
 En travaillant de manière globale sur l’ensemble de la structure.

12.4.1- Utilisation des champs d’une structure


Chaque champ d’une structure peut être manipulé comme n’importe quelle variable du type
correspondant. La désignation d’un champ se note en faisant suivre le nom de la variable
structure d’un point, puis du nom de champ, tel qu’il a été défini dans le modèle.
Voici quelques exemples utilisant le modèle Article et les variables art1 et art2 déclarées de ce
type.

[Link] = 15 ;
printf(« %f »,[Link]) ;
scanf(« %f »,&[Link]) ;
[Link] = [Link]+1 ;

12.4.2- Utilisation globale d’une structure


Il est possible d’affecter à une structure le contenu d’une autre structure définie à partir du même
modèle. Par exemple si les structures art1 et art2 ont été déclarées suivant le modèle article défini
précédemment, nous pourrons écrire :
Art1 = Art2 ;
Notez bien qu’une telle affectation n’est cependant possible que si les structures ont été définies
avec le même nom de modèle ; en particulier, elle sera impossible avec des variables ayant une
structure analogue mais définies sous deux noms différents.
En dehors de l’affectation, il n’existe pas d’autre possibilité d’utilisation globale d’une structure.
Rappelons que, pour les tableaux, on ne dispose d’aucune possibilité d’utilisation globale, pas
même au niveau de l’affection.
12.5- Initialisation de structures
Il est possible d’initialiser une structure, lors de sa déclaration.

43
44

Exemple : struct article art1 = {100, 285, 49.95} ;

La description des différents champs se présente sous la forme d’une liste de valeurs séparées par
des virgules, chaque valeur étant une constante (ou une expression constante) ayant le type du
champ correspondant. La encore il possible d’omettre certaines valeurs ; ces derniers seront
indéterminés, sauf dans le cas d’une structure définie en variable globale (auquel cas ces valeurs
seront placées à zéro).

13.6- La porté du modèle de structure


Nous avons déjà vu que les déclarations de variables ou de fonctions pouvant être soit globales
(accessibles à toutes les fonctions), soit locales (accessibles à une seule fonction). Bien entendu,
cette règle s’applique aux variables au sens large que sont les structures ; mais elle s’applique
également aux déclarations de modèles de structures.

Voici un exemple d’un modèle de structure nommé article déclaré de façon globale et accessible
depuis les fonctions main et calculmoy.

# include <stdio.h>
# include <conio.h>
# include <string.h>

struct article
{
int numero;
int qte;
float prix;
}

main( )
{
struct x;


}

void calculmoy ( )
{

struct article y, z;


}

Nous verrons que cette possibilité se révèle indispensable pour les structures transmises en
argument d’une fonction.

44
45
13.7- Imbrication de structures
Dans nos exemples d’introduction de structures, nous nous sommes limités à une structure simple
ne comportant que des trois champs d’un type de base. Mais chacun des champs d’une structure
peut être d’un type absolument quelconque : pointeur, tableau, structure … de même, un tableau
peut être constitué d’éléments qui sont eux mêmes des structures. Voyons ici quelques situations
classiques.

13.7.1- Structure comportant des tableaux


Soit les déclarations suivantes

struct personne
{
Char nom[30] ;
Char prenom[20] ;
Float heures[31] ;
};

struct personne employe ;


On peut par exemple, imaginer que ces structures permettent de conserver pour un employé d’une
entreprise les informations suivantes : nom, prénom et le nombre d’heures de travail effectuées
pendant chacun des jours du mois courant.

12.7.2- Tableaux de structures


Nous avons déjà utilisé des tableaux ; cependant, leurs éléments étaient alors d’un type scalaire
(entier, flottant ou caractère). En langage C, il est possible de définir des tableaux dont les
éléments sont d’un type structure.

Voyez ces déclarations :

main( )
{
struct article
{
int numero ;
int qte ;
float prix ;
};

struct article tab[10] ;

tab[0].numero = 20 ;

tab[0].prix = 20.66 ;
}

12.7.3- Structures comportant d’autres structures

45
46
Supposons qu’à l’intérieur d’une structure, nous ayons besoin d’introduire deux dates (la date de
naissance et la date d’embauche d’un employé), et si ces dates sont elles-mêmes des structures
comportant trois champs correspondant au jour, au mois et à l’année, nous pouvons alors
procéder aux déclarations suivantes :

struct date
{
int jour ;
int mois ;
int annee ;
};

struct employe
{
char nom[20] ;
char prenom[20] ;
struct date datenaissance ;
struct date dateembauche ;
};

46
47

Exercices
N.B : Créez une structure pour chacun des exercices suivants, et utilisez une seule variable (de la
structure définie) pour stocker les valeurs qui seront fournies par l’utilisateur.

1. Ecrivez un programme qui demande le numéro d’un article, son prix unitaire et la quantité
en stock, puis qui les affiche.

2. Ecrivez un programme qui demande la date de naissance d’une personne (Jour, mois et
année), puis qui affiche la date.

3. Ecrivez un programme qui demande deux dates puis affiche le nombre d’années de
différence entre ces deux dates.

4. Ecrivez un programme qui demande le numéro d’un étudiant, puis une note pour chacun
des logiciels suivants : Windows, Word, Excel et Access, qui ajoute 5 sur chaque note,
puis qui affiche le code et les notes (après l’augmentation), puis la note totale.

5. Ecrivez un programme qui demande le numéro d’un employé, son taux horaire, son
nombre d’heures mensuel, puis qui affiche son salaire annuel, sa dépense annuelle et
économie annuelle, sachant qu’il dépense 30% de son salaire.

6. Ecrivez un programme qui demande le numéro d’un employé, son salaire mensuel, son
âge et son nombre d’enfants, puis qui affiche son nouveau salaire, sachant qu’on lui
donne une augmentation, selon les conditions suivantes:

2% si son salaire est inférieur à 30000.


3% si son nombre d’enfants est supérieur à 6.
1% s’il est âgé de plus de 50 ans.e

7. Ecrivez un programme qui demande le code d’un employé, son nom, son prénom, sa
fonction et son salaire, puis qui les affiche.

8. Ecrivez un programme qui demande l’adresse d’une personne c’est-à-dire le pays, la ville,
le nom de la rue et le numéro de l’appartement, puis qui affiche l’adresse de la façon
suivante : Numéro, rue, ville, pays
Exemple : 8, Rue du quai, Cayes, Haïti.

9. Ecrivez un programme qui demande le code d’un article, son nom, son prix d’achat
unitaire et la quantité en stock, puis qui affiche le code et le prix d’achat total de l’article.

10. Même exercice que le précédent, mais qui affiche le prix de vente total et unitaire de
l’article, sachant que le vendeur veut gagner 10% de bénéfice.

11. Ecrivez un programme qui demande les caractéristiques d’un ordinateur c’est-à-dire la
marque, le modèle, la vitesse du processeur (en GHz), la capacité de la mémoire vive (en
Megabyte), la capacité du disque dur (en gigabyte), puis qui les affiche.

47
48
12. Reprenez l’exercice 1 mais en demandant un deuxième code, et qui affiche les
informations de l’employé si les codes sont identiques, ou un message indiquant que les
codes sont différents.

13. Ecrivez un programme qui demande le code d’un étudiant, son nom, son prénom, sa date
de naissance, sa date d’inscription et son adresse, puis qui les affiche.

14. Ecrivez un programme qui demande le nom d’un employé, son prénom, sa fonction, son
salaire, sa date d’embauche, son adresse, son numéro de tel et son NIF, puis qui les
affiche.

15. Ecrivez un programme qui permet d’enregistrer les informations suivantes concernant un
étudiant en bureautique à BTI,
Le code de l’étudiant, son nom, son prénom, son sexe, sa date de naissance, sa date
d’inscription, son adresse et ses notes (Windows, Word, Excel, Access).

 Utilisez quatre structures pour ce programme : date, adresse, notes, étudiant


 La structure date avec les champs : jour, mois et année.
 La structure adresse avec les champs : numéro, rue et ville.
 La structure note avec les champs : Windows, Word, Excel et access.
 La structure etudiant avec les champs : code, nom, prénom, sexe, datenaissance,
dateinscription, adresse et notes.

16. Ecrivez un programme qui demande le code, le nom, le prénom et le nombre d’heures de
travail d’un employé, puis qui affiche le code, le nom, le prénom et le salaire mensuel de
l’employé, sachant qu’on lui paie 60 dollars par heure.
N.B : Le nombre d’heures doit être fourni par semaine. (Pour un mois)

48
49

Chapitre 13
Pointeur

13.1- Préambule
Toute variable quelle qu’elle soit, possède une adresse mémoire qui définit l’emplacement
qui lui a été alloué dans la mémoire de l’ordinateur lors de sa déclaration. A partir de cette
information, on peut définir le type « pointeur » : les variables de type pointeur (ou pointeur) sont
prévues pour recevoir comme valeur une adresse mémoire, c’est-à-dire généralement l’adresse
d’une autre variable (les pointeurs peuvent contenir leur propre adresse, mais cela ne représente
aucun intérêt). Lorsqu’un pointeur possède l’adresse d’une variable, on dit qu’il « pointe » sur
cette variable.

13.2- Déclaration d’un pointeur.


En C, lorsqu’on déclare un pointeur, il faut nécessairement préciser le type de donnée
qu’on trouvera aux adresses qu’il peut contenir. C’est pourquoi, on parle souvent de « pointeur
sur <type> », par exemple : pointeur sur int.

Syntaxe : <type de donnée « pointable » > * <nom du pointeur> ;

Exemples :
Déclaration d’un pointeur sur int : int * x ;
Déclaration d’un pointeur sur char : char * x ;
Déclaration d’un pointeur sur float : float * x ;

Attention, lorsqu’on déclare plusieurs pointeurs sur une même ligne (si ce sont des
pointeurs sur un même type), il faut mettre l’opérateur « * » à chaque pointeur.

Exemple : int *x, *y, *z ;

Comme pour les autres variables, un pointeur non initialisé possède une valeur aléatoire et
donc imprévisible. D’autre part, il est très rare qu’on affecte à un pointeur une adresse sous la
forme d’une valeur constante puisqu’il est impossible de déterminer de façon sûre ce qui se
trouve à une adresse mémoire donnée.
Pour donner une valeur à un pointeur, on va donc généralement lui affecter soit l’adresse
d’une autre variable, soit la valeur contenue dans un autre pointeur.

13.3- Désignation de l’adresse d’une variable (Operateur &).


Syntaxe : & <nom de la variable>

Exemple : soit une variable x de type int, son adresse est : &x. On peut donc l’affecter au
pointeur sur int P de la façon suivante : P = &x ;

49
50
Quant aux échanges d’adresses entre pointeurs (sur même type), ils se font de la même
manière qu’entre n’importe quelles variables puisqu’il s’agit finalement d’un simple échange de
valeur.

Exemple : soit deux pointeurs P et Q, on affecte à P l’adresse contenue dans Q de la façon


suivante : P = Q ;

13.4- Désignation de la valeur pointée par un pointeur


(Opérateur *).
Syntaxe : * <nom du pointeur>

Exemple : soit un pointeur sur int P, la valeur située en mémoire à l’adresse contenue dans P est :
*P. On peut donc l’utiliser ainsi comme une valeur désignée de n’importe quelle autre façon.
Exemples : x = *P + 10 ;
*P = 10 ;
printf(« %d », *P) ;

Attention : lorsqu’on effectue le produit d’une valeur pointée par un pointeur, on va


utiliser l’opérateur « * » deux fois de suite, mais avec deux significations différentes. Exemple : x
= 2 * *P ; Le premier « * » correspond à l’opérateur de multiplication, alors que le second
correspond à l’opérateur de la syntaxe de désignation propre aux pointeurs. Pour écrire de façon
plus claire cette instruction, on peut le faire ainsi : x = 2 * (*P) ;

Remarque importante : lorsqu’on déclare un pointeur, on déclare une variable qui contiendra une
adresse mémoire et qui en contient actuellement une aléatoire. Par conséquent, si on affecte une
valeur à l’emplacement pointé par un pointeur sans avoir préalablement affecté une adresse à ce
pointeur, la valeur en question va donc être placée en mémoire à un endroit inconnu. Cette
anomalie n’est généralement pas détectée par le compilateur et, selon les circonstances, peut
aboutir à différents problèmes :
- dans le meilleur des cas, l’adresse en question n’est pas accessible au programme et une
simple erreur de mémoire bloque l’exécution.
- dans les autres cas, la valeur ainsi placée aléatoirement dans la mémoire va écraser une
autre valeur, entrainant des conséquences imprévisibles et plus ou moins désastreuses.

Voici un schéma récapitulatif :


int n =20 ;
int p ;
int * adi ;

Etat initial adi = &n ; p =* adi ; *adi = 30 ; adi= &p ;

n 20 n 20 n 20 n 30 n 30

p ? p ? p 20 p 20 p 20

adi ? adi adi adi adi

50
51

On ne peut pas attribuer une signification unique à une notion telle que *adi ; en effet :
Dans une expression, la notation *adi désigne la valeur de l’information pointée par adi ; c’est le
cas dans l’affectation p =*adi ;

A gauche d’une affectation, la notation *adi désigne l’information pointée par adi ; c’est le cas
dans l’affectation *adi=30 ;.

En effet, la même remarque s’applique à un nom de variable ; dans une expression il en


représente une valeur, a gauche d’une affectation, il désigne la variable qu’on souhaite modifier.
Mais, dans ce cas, les choses paraissent naturelles.

En revanche, il y a bien équivalence entre *adi et une variable entière, y compris au niveau de la
mise en place d’éventuelles conversions. Ainsi notamment, avec : *adi=4.6 ;

Il y a bien conversion de la valeur flottante 4.6 en entier, et le résultat (4) est affecté à adi . De
même, si x, est supposé de type float avec :
X=* adi ;
Il y a conversion en float de la valeur entière pointée par adi avant l’affectation à la variable x.
La priorité de l’opérateur unaire * est plus élevée que celle des opérateurs arithmétiques, de sorte
que, par exemple, l’expression :
2 * * adi
est interprétée comme :2 * (* adi)
C’est-à-dire comme le produit de * adi par 2. Pour rendre une telle expression plus lisible, en
général, plutôt que de placer des parenthèses inutiles comme dans la deuxième écriture, on joue
sur la présence ou l’absence d’espace supplémentaire, en l’écrivant ainsi (pour bien montrer que
les ecritures 2**adi, 2 **adi ou 2** adi sont correctes mais relativement illisibles.

13.5- Les paramètres de type pointeur.


Lorsqu’une fonction possède des paramètres de type pointeur, on utilise l’opérateur « * »
pour indiquer dans son en-tête et dans son prototype les paramètres concernés.

Exemple :
En-tête : int test (int *x, int *y)
Prototype : int test (int *, int *) ;

D’autre part, lorsqu’on donne à une fonction des paramètres de type pointeur, cela signifie
que la valeur à donner à chacun d’entre eux au moment de l’appel de la fonction sera donc
l’adresse d’une variable de type correspondant. Ce genre de pratique comporte un avantage
important, car on travaille ainsi sur l’adresse d’une variable et non directement sur sa valeur, et
grâce à cette adresse, on va pouvoir accéder à la valeur et même la modifier. Autrement dit, dans
une fonction dont certains paramètres sont des pointeurs, lorsqu’on va modifier les valeurs
pointées par ces pointeurs, on retrouvera ces modifications dans la fonction (ou le main) qui a
effectué l’appel.

51
52
L’exemple du programme suivant permet de comprendre ce mécanisme : on va appeler
dans le main la fonction Echange dont le but est de prendre les adresses de deux variables de type
int et d’inverser leur valeur.

#include <stdio.h>
main()
{
void echange (int *, int *) ;
int a = 10, b = 20 ;
printf(« avant appel : a = %d b = %d\n », a, b) ;
echange (&a, &b) ;
printf(« apres appel : a = %d b = %d », a, b) ;
}

void echange (int *P1, int *P2)


{
int x ;

x = *P1 ;
*P1 = *P2 ;
*P2 = x ;
}

Avec cet exemple, on observe un important bénéfice apporté par l’utilisation des pointeurs
en tant que paramètres : comme on peut modifier depuis une fonction appelée la valeur des
variables d’une fonction appelante, on peut ainsi simuler le retour de plusieurs valeurs, alors
qu’on ne peut normalement retourner qu’une seule valeur à l’issue d’une fonction.

13.6- Retour d'une adresse à l'issue d'une fonction.


Lorsqu'une fonction doit retourner une adresse, on utilise là encore l'opérateur « * » pour
indiquer le type de valeur retournée dans son en-tête et son prototype.

Exemple : int* Test (int *P) /* En-tête de la fonction Test */


int* Test (int *) /* Prototype de la fonction Test */

13.7- Pointeurs et structures : désignation d'un champ d'une


variable structurelle à partir de son adresse.

Pour désigner un champ d'une variable structurelle dont un pointeur contient l'adresse, on
utilise l'opérateur « -> » composé des symboles « - » et « > ».

Syntaxe : <pointeur> -> <champ>

Exemple :

struct Date /* Création globale de la structure Date */


{
int Jour ;

52
53
int Mois ;
int Annee ;
};

main()
{
struct Date *P, D; /* On déclare une date D et un pointeur sur date P */

P = &D; /* On fait pointer P sur D */


P->Jour = 10;
P->Mois = 9;
P->Annee = 1999; /* On initialise D à partir de son adresse qu'on a donnée au pointeur P */
}

13.8- Quelques précautions


a) Lorsqu’on déclare simultanément plusieurs pointeurs
Lorsqu’on souhaite déclarer, dans une même instruction, plusieurs pointeurs de même type, par
exemple des pointeurs sur des caractères, il ne faut surtout pas écrire :
Char * adc1, adc2 ;
En effet dans ce cas adc1 serait certes un pointeur sur des caractères ( car *adc1 est de type char)
mais en revanche, adc2 serait tout simplement une variable de type char, si l’on souhaite que
adc2 soit également un pointeur sur des caractères, il faudra écrire :
Char *adc1, *adc2 ;

B) Réserver un pointeur ne réserve pas un emplacement pour une information pointée

Lorsqu’on réserve l’emplacement pour une variable pointeur comme dans :


Int * adi ;
On ne réserve pas pour l’instant un emplacement pour un entier. D’ailleurs comme nous l’avons
déjà dit, la valeur (donc l’adresse) contenue alors dans adi est imprévisible. Si suite à notre
déclaration nous introduisons une affectation telle que :
* adi=12 ;

Alors que nous n’avons affectée aucune valeur à adi, nous allons donc demander de placer la
valeur 12 à un emplacement quelconque. Généralement, ce genre d’anomalie n’est pas détecté
par le compilateur et ça peut engendrer des conséquences imprévisibles et même désastreuses
(écrasement d’une autre donnée, destruction d’une instruction…).

53
54

Exercices
1. Ecrivez un programme qui se sert d’une fonction qui permet l’échange des valeurs de
deux variables.
N.B : Les valeurs des variables doivent être fournies par l’utilisateur et elles doivent être
affichées avant et après l’appel de la fonction, dans la fonction principale.

2. Ecrivez une fonction qui demande trois nombres entiers, qui affiche ces nombres dans la
fonction principale.
N.B : L’utilisation des tableaux est interdite.

3. Ecrivez un programme qui demande deux nombres entiers, puis utilisez une fonction (qui
ne retourne aucune valeur) qui permet d’incrémenter le premier de 5 et décrémenter le
second de 3.
N.B : - N’utilisez pas de tableau
-N’oubliez pas d’afficher les valeurs dans la fonction principale, après l’appel
de la fonction.

4. Ecrivez une fonction nommée minmax permettant de déterminer la valeur minimale et la


valeur maximale d’un tableau de flottants. La fonction ne fournira aucun résultat ; elle
devra donc comporter en paramètre, outre que le tableau et son nombre d’élément, deux
pointeurs sur des variables de type flottant, destinées à recevoir la plus grande et la plus
petite valeur du tableau.

Dimension du tableau : 6
La plus grande et la plus petite valeur doivent être affichées dans la fonction principale.

54
55

Chapitre 14
Les tableaux dynamiques.

14.1- Préambule
Les programmes utilisant des tableaux dynamiques nécessitent avant tout de créer au
moins une structure pour définir le type des éléments qui formeront les tableaux dynamiques. Il
est tout-à-fait possible de créer plusieurs types d’éléments et de manipuler des tableaux
dynamiques contenant ainsi des éléments différents, mais il est préférable de commencer par des
tableaux simples à partir d’une seule structure. Généralement, une telle structure contient au
moins un champ de type « classique » (c’est-à-dire un champ qui contiendra une valeur
numérique ou un caractère) et au moins un pointeur sur l’élément suivant. Pour cette étude des
tableaux dynamiques, nous allons utiliser la structure suivante :

struct elem
{
int val ; /* Unique valeur de l’élément */
elem *suiv ; /* Pointeur sur l’élément suivant */
};

A quelques nuances près, la manipulation des tableaux dynamiques se fait en C comme en


algorithmie.

14.2- Création d’un tableau dynamique.


La création d’un tableau dynamique (liste) se fait généralement à partir d’un simple
pointeur sur élément qui, au départ, ne pointe sur rien. Ensuite, on va créer successivement des
éléments et les « attacher » pour former une liste. Le premier sera pointé par le pointeur de
départ, puis chaque nouvel élément sera pointé par le pointeur du dernier élément créé.
La création d’un élément suppose de lui réserver la partie de mémoire nécessaire selon sa
taille. Pour cela, on utilise les fonctions malloc et sizeof. La fonction malloc permet de faire
pointer un pointeur sur un élément correspondant à son type qu’elle créée en lui allouant la
mémoire nécessaire. Son paramètre est donc une valeur correspondant à l’espace mémoire
nécessaire au type de l’élément créé. C’est pourquoi on a besoin en même temps de la fonction
sizeof qui prend en paramètre un type, et qui retourne l’espace mémoire nécessaire à ce type.
Ainsi, le retour de la fonction sizeof permet de fournir la valeur nécessaire au paramètre de la
fonction malloc.

Exemple de création d’un élément de type struct elem : malloc(sizeof (struct elem))

La fonction malloc retourne une adresse que l’on dit « générique », c’est-à-dire qu’elle
peut être récupérée par un « pointeur sur n’importe quel type ». Il est donc préférable d’imposer à
ce retour le type du pointeur qui va recevoir cette adresse. Pour cela, il suffit d’indiquer entre
parenthèses devant l’appel de la fonction malloc le type qu’on souhaite lui imposer.

55
56

Exemple de fonction de création d’une liste sans sentinelle :

void Crea_liste (struct elem *l) /* on prend en paramètre un pointeur sur le premier élément
(considéré comme déjà
{ existant) à partir duquel on va créer le reste de la liste */
int x, c;

printf ("Combien d'elements ?\n"); /* On demande à l’utilisateur combien d’éléments il


veut avoir dans sa liste */
scanf ("%d",&x);

if (x != 0)
{
for (c=1; c<=x-1; c++) /* On va créer x – 1 éléments, car le premier existe
déjà */
{
printf ("Valeur de l'element %d ?\n",c); /* On commence par demander
la valeur de
scanf ("%d", &l->val); l’élément, car on considère que
le premier, même
s’il existe déjà, n’a pas encore reçu sa
valeur */
l->suiv = (struct elem*) malloc (sizeof (struct elem)); /* Création d’un
nouvel élément à la suite
de l’élément actuel */
l = l->suiv ; /* Positionnement de l sur le dernier élément créé */
}

printf ("Valeur de l'element %d ?\n",x); /* Comme l’affectation de la valeur d’un


élément se fait juste avant la
scanf ("%d",&l->val); création du suivant, le dernier n’a donc pas
encore reçu sa valeur */
l->suiv = NULL; /* Le dernier élément doit pointer sur NULL */
}
}

14.3- Parcours d’un tableau dynamique.


On accède généralement à l’ensemble des éléments d’un tableau dynamique par l’adresse
du premier élément contenue dans un pointeur, en tenant compte du fait que chaque élément
possède l’adresse de l’élément suivant. Le parcours d’un tableau se fait donc en donnant
successivement à un pointeur l’adresse de chaque élément.
Dans les cas où on aurait besoin de parcourir un tableau plusieurs fois de suite, il faut
donc penser à toujours conserver dans un autre pointeur (« tampon ») l’adresse du premier
élément.

56
57
D’autre part, lorsqu’on utilise des éléments qui ne contiennent qu’un pointeur sur
l’élément suivant (c’est-à-dire pour une liste unidirectionnelle), il est impossible de « revenir en
arrière » pendant un parcours de tableau. C’est pourquoi il faut parfois prévoir plusieurs pointeurs
répartis sur plusieurs éléments qui se suivent lorsqu’on doit avoir accès en même temps à un
élément et à celui ou ceux qui le précèdent. L’autre solution est de travailler sur une liste
bidirectionnelle plutôt que sur une liste unidirectionnelle.

14.4- Retour ou non du premier élément du tableau.

Comme les fonctions prennent généralement leur tableau en paramètre en récupérant


l’adresse du premier élément, il n’est nécessaire de retourner ce dernier à l’issue de la fonction
que s’il peut avoir changé au cours de l’exécution des instructions. C’est en particulier le cas des
fonctions qui permettent la suppression ou l’ajout d’un élément ou encore le tri d’un tableau
dynamique. Cependant, l’utilisation d’une sentinelle de début permet de résoudre ce problème
puisque celle-ci occupe toujours la première place, et c’est donc par son adresse que l’on
transmet l’ensemble du tableau.

Exemples :

- dans le cas d’une fonction qui se contente d’ajouter un élément à la fin d’un tableau, il
n’est pas nécessaire de retourner le tableau à la fin puisque le premier élément n’a pas
changé.
- dans le cas d’une fonction qui effectue le tri d’un tableau dynamique, il est possible que le
premier élément change de place selon le tri que l’on va effectuer, et il faut donc prévoir
de retourner à l’issue de la fonction, l’élément qui sera finalement en première place.
Dans ce cas, le retour final du premier élément nécessite de prévoir un pointeur qui aura
pour rôle de pointer constamment sur le premier élément, et qui ne changera donc de cible
que lorsqu’un autre élément deviendra premier.

57
58

Chapitre 15

l’accès aux fichiers.


15.1- Préambule
On connaît pour l’instant deux façons de rassembler les données de départ d’un
programme et de fournir le(s) résultat(s) à l’arrivée : lecture au clavier et passage en paramètre
d’une fonction pour les données de départ, affichage à l’écran et retour de fonction pour les
résultats. Mais ces techniques ont comme principal défaut qu’elles ne sont utilisables que tant que
le programme est en cours d’exécution car toutes ces informations sont placées uniquement dans
la mémoire de l’ordinateur : On ne peut donc pas rassembler les données de départ avant que le
programme soit lancer, et lorsque le programme s’arrête, les résultats sont perdus.
L’accès aux fichiers offre une nouvelle façon de rassembler les données et les résultats, et
ce de façon permanente puisqu’un fichier se trouve toujours sur un disque. On va donc pouvoir
rassembler les données de départ dans un ou plusieurs fichiers bien avant l’exécution du
programme, et les résultats pourront eux aussi être sauvegardés par le programme lui-même dans
un ou plusieurs fichiers. C’est ce qu’on appelle la lecture et l’écriture dans un fichier.
C’est le principe utilisé par les logiciels qui proposent de sauvegarder des fichiers :
lorsqu’on utilise le logiciel, on travaille sur la mémoire de l’ordinateur, et lorsqu’on fait une
sauvegarde, les données traitées sont inscrites dans un fichier.

Pour obtenir de l’aide sur la lecture et l’écriture dans les fichiers en C, chercher "file
handling" dans l'aide de Dev-C++.

15.2- Ouverture / fermeture d’un fichier et principe du


« stream ».

On appel « stream » en C une interface logique liée à un fichier dans le but de le contrôler
selon des besoins précis. Le langage C distingue deux types de « stream » : le « stream texte »
utilisant les codes ASCII des caractères et le « stream binaire » permettant un transfert des
informations bit par bit entre le fichier et la mémoire.

15.2.1- Ouverture d’un fichier.

Lorsqu’on ouvre un fichier, on l’associe donc à un stream en décidant de la façon dont on


va le manipuler. La fonction utilisée pour cette opération d’ouverture / association est fopen(),
définie dans la librairie « stdio.h » et dont l’en-tête est la suivante :

FILE* fopen (char *fname, char *mode)

FILE est un type défini dans stdio.h et dont l’objectif est de contenir diverses informations
au sujet d’un fichier. On voit donc que fopen retourne un « pointeur sur FILE » qui servira de
référence pour l’exploitation du fichier ouvert. Ce pointeur servira dans toutes les autres
fonctions de manipulation des fichiers, c’est pourquoi il ne doit pas changer de valeur tant qu’on
manipule le même fichier.

58
59
Le pointeur *fname représente une chaîne contenant l’adresse de fichier que l’on souhaite
ouvrir. Il peut s’agir de l’adresse absolue du fichier ou de son adresse relative par rapport au
programme lui-même. Attention, si jamais le fichier à ouvrir est déplacé après que ce genre
d’instruction ait été écrite, le programme ne parviendra plus à l’ouvrir si l’adresse indiquée n’est
plus la bonne.
Quant au pointeur *mode, il représente une chaîne déterminant de quelle façon on va
ouvrir le fichier. Voici la liste des différents modes d’ouverture :

Mode Signification

r Ouvre un fichier texte en lecture


w Crée un fichier texte en écriture (si un fichier de même nom existe déjà, il est
automatiquement
écrasé)
a Ouvre un fichier texte en ajout (ajout = écriture à la fin du fichier)
rb Ouvre un fichier en binaire en lecture
wb Crée un fichier en binaire en écriture (si un fichier de même nom existe déjà, il est
automatiquement écrasé)
ab Ouvre un fichier en binaire en ajout
r+ Ouvre un fichier texte en lecture et en écriture
w+ Crée un fichier texte en lecture et en écriture
a+ Ouvre un fichier texte existant en lecture et en ajout ou crée un fichier texte en
lecture et en écriture
si le fichier demandé n’existe pas encore
r+b Ouvre un fichier en binaire en lecture et en écriture
w+b Crée un fichier en binaire en lecture et en écriture
a+b Ouvre un fichier en binaire existant en lecture et en ajout

Si l’exécution de fopen() réussi, on récupère donc un « pointeur sur le fichier ouvert ». Si


l’exécution échoue, on récupère la valeur NULL.

Exemple : f = fopen (« Fichier [Link] », « r ») ; /* Exemple d’un fichier ouvert en lecture et


associé au
pointeur f */

15.2.2- Fermeture d’un fichier.

Pour fermer un fichier et le désassocier du stream auquel on l’avait attaché avec fopen(),
on utilise la fonction fclose() également définie dans « stdio.h » et dont voici l’en-tête :

int fclose (FILE *fp)

Le pointeur *fp doit pointer sur un fichier précédemment ouvert avec fopen(), et la valeur
retournée sera 0 si l’exécution de fclose() s’est bien passée.

Exemple : fclose (f) ; /* Fermeture du fichier précédemment ouvert et associé au pointeur


f */

59
60

15.3- Notion de curseur :

Une fois qu’un fichier a été ouvert, les fonctions suivantes permettent de lire les données
qu’il contient ou de le modifier selon le mode d’ouverture choisi. Pour comprendre le
fonctionnement de ces fonctions, on utilisera le concept de « curseur » : on appelle curseur la
position sur laquelle on se trouve dans un fichier à un instant donné. Quand on vient d’ouvrir un
fichier en lecture ou en écriture, le curseur se trouve sur le premier caractère du fichier. Quand on
vient d’ouvrir un fichier en ajout, le curseur se trouve après le dernier caractère du fichier. A
chaque fois qu’on lit un caractère ou une chaîne de caractères, le curseur se positionne sur le
caractère suivant.

15.4- Lecture et écriture d’un caractère :

int fgetc (FILE *fp) : permet de lire un caractère dans un fichier texte ouvert en lecture. Le
pointeur fp correspond au fichier à ouvrir, et le caractère lu obtenu par le retour de fgetc() peut
être interprété aussi bien comme un caractère que comme un nombre. Si une erreur se produit ou
si on essaie de lire un caractère alors qu’on a déjà atteint la fin d’un fichier, la valeur retournée
sera EOF, qui est une valeur spéciale indiquant la fin d’un fichier.

Exemple : x = fgetc (f) ; /* x reçoit le caractère lu dans le fichier associé au pointeur f */

Note : lorsqu’on lit une donnée dans un fichier, le curseur avance automatiquement à la donnée
suivante. Il est donc impossible de lire plusieurs fois de suite la même donnée sans revenir au
début du fichier (cf. fonction rewind()).

int fputc (int ch, FILE *fp) : permet d’écrire le caractère contenu dans ch dans le fichier pointé
par fp ouvert en écriture ou en ajout. En cas de succès, cette fonction retourne le caractère écrit,
sinon, elle retourne EOF. Ici encore, même si ch est de type int, on peut lui fournir aussi bien un
caractère qu’un nombre, et il en va de même pour le retour.

fputc (‘g’, f) ; /* Ecriture dans le fichier associé au pointeur f du caractère g */

15.5- Lecture et écriture d’une chaîne de caractères :


char *fgets (char *str, int num, FILE *fp) : permet de lire une chaîne de caractères dans un fichier
pointé par fp (et ouvert en lecture) à partir du curseur et de la faire pointer par str. La lecture de la
chaîne s’arrête dès que l’on rencontre un des critères suivants :
- on a lu le nombre de caractères précisé dans num moins 1
- on a atteint la fin d’une phrase
- on a atteint la fin du fichier

Les deux derniers caractères de la chaîne ainsi lue sont systématiquement le saut de ligne
et NULL. Cette fonction retourne str en cas de succès et NULL en cas d’échec, mais compte tenu
du fait que str est un pointeur, il n’est généralement pas nécessaire de se préoccuper du retour.

Exemple : fgets (ph, 10, f) ; /* La chaîne ph reçoit les 10 premiers caractères de du fichier
associé au pointeur f à

60
61
partir du curseur */

int fputs (char *str, FILE *fp) : permet d’écrire la chaîne pointée par str dans le fichier pointé par
fp et ouvert en écriture ou en ajout. En cas de succès, fputs retourne une valeur positive ou nulle.
En cas d’échec elle retourne EOF.

Exemple : fputs (« bonjour », f) ; /* Ecriture de la chaîne « bonjour » dans le fichier associé au


pointeur f */

15.6- Lecture et écriture de valeurs pouvant être ccompagnées


d’une chaîne de caractères :

Dans certains cas, on peut souhaiter lire dans un fichier un caractère que l’on utilisera en
tant que valeur numérique. De même, on peut souhaiter écrire dans un fichier une chaîne de
caractères comportant des valeurs de variable. Pour réaliser ce type d’opérations, on dispose de
fonctions semblables aux printf et scanf, et qui fonctionnent de façon similaire. Les différences
entre ces nouvelles fonctions et les fameux printf et scanf sont qu’il faut ici préciser dans quel
fichier on souhaite écrire (grâce qu pointeur fp) et que l’on récupère le résultat de l’opération
sous la forme d’une valeur numérique (on obtient une valeur positive ou nulle en cas de succès et
EOF en cas d’échec).

int fscanf (FILE *fp, char *control-string, ...) : permet de lire un ou plusieurs caractères dans un
fichier ouvert en lecture et de les interpréter selon les besoins.

Exemple : fscanf (f, « %d », &x) ;

int fprintf (FILE *fp, char *control-string, ...) : permet d’écrire dans un fichier ouvert en écriture
ou en ajout un ou plusieurs caractères fournis sous n’importe quelle forme.

Exemple : fprintf (f, « J’ecris la valeur de y dans le fichier : %f », y) ;

15.7- Test de la position du curseur par rapport à la fin du


fichier

Dans certains cas, il peut être utile de vérifier si on a atteint la fin du fichier ouvert ou pas.
Pour cela, on utilise la fonction suivante aussi bien avec les fichiers ouvert en mode texte qu’en
mode binaire.

int feof (FILE *fp) : retourne une valeur non nulle si on a atteint la fin du fichier, et 0 dans les
autres cas.

15.8- Suppression d’un fichier.

Lorsqu’on souhaite supprimer un fichier, il faut d’abord s’assurer que celui-ci n’est pas
actuellement ouvert par le programme qui doit le supprimer ou par une autre application, faute de
quoi la suppression sera impossible. D’autre part, il faut avoir conscience que la fonction utilisée
pour ce genre d’opération n’utilise évidemment pas le protocole de la corbeille de Windows et
que par conséquent, tout fichier supprimer par un programme l’est définitivement.

61
62

int remove (char *fname) : la chaîne de caractères fname doit contenir l’adresse du fichier à
supprimer. En cas d’erreur (mauvaise adresse, fichier en cours d’utilisation, etc…), cette fonction
retourne une valeur négative et le fichier n’est pas supprimé. En cas de succès, cette fonction
retourne 0.

main()
{
int x;
chdir("c:\\Exercices");
x=remove("[Link]");

getch();
}

15.9- Réinitialisation du curseur.

Lorsqu’on ouvre un fichier en lecture ou en écriture, le curseur se positionne


automatiquement au début de ce fichier. A chaque opération de lecture ou d’écriture, le curseur
va avancer dans le fichier. Or, dans certains cas, il est nécessaire de repositionner au début du
fichier. Pour cela, on utilise la fonction suivante :

void rewind (FILE *fp) : le pointeur fp correspond au fichier dont on souhaite réinitialiser le
curseur.

Renommer un fichier

Rename(« Fichier source », « Fichier destination) ;

Ex : rename(« [Link] », « [Link] ») ;

62
63

Exercices

1. Ecrivez un programme qui permet d’écrire un caractère quelconque dans un fichier.

2. Ecrivez un programme qui permet d’écrire une chaine de caractère dans un fichier.

3. Ecrivez un programme qui demande un caractère quelconque, puis qui l’écrit dans un
fichier.

4. Ecrivez un programme qui demande un mot quelconque, puis qui l’écrit dans un fichier.

5. Ecrivez un programme qui demande un nombre décimal, puis qui l’écrit dans un fichier.

6. Ecrivez un programme qui demande un nombre entier, puis qui l’écrit dans un fichier.

7. Ecrivez un programme qui demande le code, nom, le prénom, la fonction et le salaire d’un
employé, puis qui les stocke dans un fichier.

8. Ecrivez un programme qui permet la lecture et l’affichage des infos du fichier de


l’exercice précédent.

9. Ecrivez un programme qui demande le code, le nom, le prénom, la fonction et le salaire n


employés, puis qui les stocke dans un fichier.

10. Ecrivez un programme qui permet la lecture et l’affichage des infos du fichier de
l’exercice précédent.

11. Ecrivez un programme qui permet la lecture et l’affichage des infos d’un employé du
fichier de l’exercice 9.

63

Vous aimerez peut-être aussi