Vous êtes sur la page 1sur 100

Le La n g a g e C

Eugne C. EZIN
http://www.imsp-uac.org/eugene/

Table des matires


Gnralits .......................................................................................................................................................... 5
Introduction ............................................................................................................................................................. 5
1.
Historique ..................................................................................................................................................... 5
2.
La programmation ............................................................................................................................................ 6
3.
Les systmes dexploitation................................................................................................................................... 6
4.
Les langages interprts ...................................................................................................................................... 7
5.
Structure dun programme C ................................................................................................................................. 7
5.1.
Premier programme C ........................................................................................................................................ 8
6.
Les expressions ................................................................................................................................................ 8
6.1.
Les types de base ............................................................................................................................................. 8
6.2.
Les modificateurs des types de base......................................................................................................................... 9
6.3.
Importances de connatre la taille des types ............................................................................................................. 10
6.4.
Les commentaires........................................................................................................................................... 11
6.5.
Les identificateurs .......................................................................................................................................... 11
6.6.
Les variables ................................................................................................................................................ 11
6.6.1.
Les variables locales................................................................................................................................... 12
6.6.2.
Les variables globales ................................................................................................................................. 12
6.6.3.
Les paramtres formels ................................................................................................................................ 13
6.7.
Les modificateurs daccs .................................................................................................................................. 13
6.7.1.
Le modificateur static.................................................................................................................................. 13
6.7.2.
Le modificateur register ............................................................................................................................... 14
6.7.3.
Le modificateur extern................................................................................................................................. 14
6.7.4.
Le modificateur const .................................................................................................................................. 15
6.7.5.
Le modificateur volatile ............................................................................................................................... 15
6.7.6.
Les chanes constantes................................................................................................................................. 15
7.
Les oprateurs ............................................................................................................................................... 16
7.1.
Loprateur daffectation ................................................................................................................................... 16
7.2.
Les oprateurs arithmtiques .............................................................................................................................. 16
7.3.
Les oprateurs dincrmentation et de dcrmentation .................................................................................................. 16
7.4.
Les oprateurs logiques .................................................................................................................................... 16
7.5.
Les oprateurs relationnels ................................................................................................................................ 17
7.6.
Loprateur ternaire ........................................................................................................................................ 17
7.7.
Les oprateurs de casting .................................................................................................................................. 17
7.8.
Loprateur sizeof........................................................................................................................................... 17
7.9.
Loprateur squentiel not ,............................................................................................................................... 18
7.10. La table des priorits et des associativits des oprateurs............................................................................................... 18
8.
Les instructions de contrle ................................................................................................................................ 18
8.1.
Linstruction if, if else et loprateur ternaire ............................................................................................................ 18
8.2.
Linstruction switch......................................................................................................................................... 19
8.3.
Linstruction for............................................................................................................................................. 21
8.4.
Linstruction while.......................................................................................................................................... 21
8.5.
Linstruction do-while ...................................................................................................................................... 22
8.6.
Linstruction break ......................................................................................................................................... 22
8.7.
Linstruction return ......................................................................................................................................... 23
8.8.
La fonction exit()............................................................................................................................................ 23
8.9.
Linstruction continue ...................................................................................................................................... 24
Conclusion ............................................................................................................................................................. 25
Prsentation du compilateur Visual C++ ................................................................................................... 26
Introduction ........................................................................................................................................................... 26
1.
Le compilateur .............................................................................................................................................. 26
2.
La cration de projet Win32 console application .......................................................................................................... 26
3.
Le dbogueur ................................................................................................................................................ 29
4.
Les fonctionnalits du dbogueur .......................................................................................................................... 33
Conclusion ............................................................................................................................................................. 34
Prsentation du compilateur gcc ................................................................................................................ 35

Dr. Eugne C. EZIN.

Introduction ........................................................................................................................................................... 35
Les entres-sorties conversationnelles....................................................................................................... 36
Introduction ........................................................................................................................................................... 36
1.
Gnralits................................................................................................................................................... 36
2.
Sorties lcran : printf()................................................................................................................................... 36
3.
Spcifications du gabarit daffichage ...................................................................................................................... 38
4.
Spcification de la prcision ............................................................................................................................... 39
5.
Les erreurs de programmation ............................................................................................................................. 40
6.
Complment de lecture : la macro putchar() .............................................................................................................. 40
7.
Entres au clavier : scanf() ................................................................................................................................. 41
8.
Principaux codes de conversion de scanf() ................................................................................................................ 41
9.
Notion de tampon et de sparateur ........................................................................................................................ 41
10.
Les premires rgles utilises par scanf() ................................................................................................................. 42
a.
Gabarit maximum .......................................................................................................................................... 43
b.
Rle dun espace dans le format ........................................................................................................................... 43
11.
Arrt prmatur de scanf() ................................................................................................................................. 44
12.
Syntaxe de scanf() ........................................................................................................................................... 45
13.
Problmes de synchronisation entre lcran et le clavier ................................................................................................. 45
14.
Complment de lecture : la macro getchar() ............................................................................................................... 49
15.
Complment de lecture : validit des donnes ............................................................................................................ 49
16.
Les assertions ............................................................................................................................................... 49
17.
Filtrage des donnes ........................................................................................................................................ 50
Conclusion ............................................................................................................................................................. 52
Les tableaux, les pointeurs et les structures ............................................................................................. 53
Introduction ........................................................................................................................................................... 53
1.
Vecteur monodimensionnel ................................................................................................................................ 53
2.
Les pointeurs ................................................................................................................................................ 54
3.
Vecteur bidimensionnel .................................................................................................................................... 54
4.
Chanes de caractres ....................................................................................................................................... 55
4.1.
Vecteur de chanes de caractres .......................................................................................................................... 57
4.2.
Initialisation des vecteurs .................................................................................................................................. 57
4.3.
Initialisation dun vecteur sans dimension ............................................................................................................... 58
5.
Variable pointeur ........................................................................................................................................... 58
5.1.
Indexation des pointeurs ................................................................................................................................... 59
5.2.
Arithmtique des pointeurs ................................................................................................................................ 59
5.3.
Pointeur des pointeurs...................................................................................................................................... 60
5.4.
Pointeur NULL ............................................................................................................................................... 61
6.
Les structures ............................................................................................................................................... 61
6.1.
Accs aux membres dune structure ....................................................................................................................... 62
6.2.
Affectation une structure ................................................................................................................................. 62
6.3.
Vecteur de structures ....................................................................................................................................... 63
Conclusion ............................................................................................................................................................. 63
Les fonctions .................................................................................................................................................... 64
Introduction ........................................................................................................................................................... 64
1.
Dfinition et dclaration dune fonction ................................................................................................................... 64
2.
Appel par valeur ............................................................................................................................................ 64
3.
Appel par adresse ........................................................................................................................................... 65
4.
Vecteur comme paramtre dune fonction ................................................................................................................. 65
5.
Les arguments spciaux de main() : argc et argv ......................................................................................................... 66
6.
Restitution dun pointeur ................................................................................................................................... 67
7.
Fonction rcursive .......................................................................................................................................... 67
8.
Vecteur monodimensionnel comme paramtre dune fonction ........................................................................................... 68
9.
Vecteur bidimensionnel comme paramtre dune fonction ............................................................................................... 69
10.
Pointeurs aux fonctions : adresse dune fonction ......................................................................................................... 71
Conclusion ............................................................................................................................................................. 72
Les oprateurs dentre-sortie sur fichier .................................................................................................. 73
Introduction ........................................................................................................................................................... 73
1.
Dfinition .................................................................................................................................................... 73

Dr. Eugne C. EZIN.

2.
Fichiers binaires et fichiers de texte ....................................................................................................................... 73
3.
Notion de flot et de fichier ................................................................................................................................. 73
4.
Flot de type binaire ......................................................................................................................................... 74
5.
Flot de type texte ........................................................................................................................................... 74
6.
Modalit douverture de fichier ............................................................................................................................ 77
7.
Flots prdfinis.............................................................................................................................................. 77
8.
Techniques de gestion de fichiers.......................................................................................................................... 77
9.
Quelques fonctions utiles pour les fichiers de type texte ................................................................................................. 78
9.1.
Prsentation de fputc() et de fgetc() ....................................................................................................................... 78
10.
Prsentation de feof() ....................................................................................................................................... 79
10.1. Prsentation des fonction fputs() et fgets() ................................................................................................................ 81
10.2. Prsentation des fonctions fread() et fwrite() ............................................................................................................. 81
10.3. Prsentation des fonctions ftell() et fseek() ................................................................................................................ 83
Conclusion ............................................................................................................................................................. 84
La gestion dynamique de la mmoire ........................................................................................................ 85
Introduction ........................................................................................................................................................... 85
1.
Importance des donnes dynamiques ...................................................................................................................... 85
2.
Pointeur gnrique ......................................................................................................................................... 85
3.
Prsentation de la fonction malloc() ....................................................................................................................... 85
4.
Prsentation de la fonction free() .......................................................................................................................... 86
4.1.
Exemple dutilisation des fonctions malloc() et free() .................................................................................................... 86
5.
Prsentation de la fonction calloc() ........................................................................................................................ 87
6.
Prsentation de la fonction realloc() ....................................................................................................................... 87
7.
Application la manipulation des matrices ............................................................................................................... 87
Conclusion ............................................................................................................................................................. 88
Etude du prprocesseur ................................................................................................................................ 89
Introduction ........................................................................................................................................................... 89
1.
Etudes des directives ....................................................................................................................................... 89
1.1.
La directive #define ........................................................................................................................................ 89
1.2.
La directive #error ......................................................................................................................................... 90
1.3.
La directive #include ....................................................................................................................................... 90
2.
Les directives #if #elif #else #endif .................................................................................................................... 91
3.
La directive #undef ......................................................................................................................................... 93
4.
Les macros prdfinies...................................................................................................................................... 94
5.
Les oprateurs du prprocesseur : # et ## .............................................................................................................. 94
Exercices proposs .......................................................................................................................................... 96
Conclusion ............................................................................................................................................................. 98
Bibliographie .................................................................................................................................................. 100

Dr. Eugne C. EZIN.

Gnralits
Introduction
Le Langage C est un langage de niveau moyen. Cela signifie que le langage C runit tous les
meilleurs lments des langages de programmation de haut niveau avec les possibilits de contrle
et la flexibilit du langage Assembler. Le C permet la manipulation des bits, des octets et des
adresses, lments sur lesquels se base le fonctionnement dun ordinateur. Un code crit en C est
beaucoup plus transportable i.e. offre la facilit dadaptation sur un autre systme. Le langage C na
que 32 mots cls qui constituent les commandes formant le langage tandis que le BASIC compte plus
de 100 mots cls.
Voyons la position du langage C selon la table suivante :

Haut Niveau

Ada
Modulo-2
Pascal
COBOL
FORTRAN
BASIC

Niveau Moyen

C# (C sharp)
Java
C++
C
FORTH

Bas Niveau

Macro assembler
Assembler

1. Historique
En 1967, Martin Richards inventa le langage de programmation BCPL (Basic Combined
Programming Language). Trois annes plus tard, soit en 1970, Ken Thompson inventa le langage B.
En 1972, Dennis Ritchie et Ken Thompson dans leur effort de dvelopper un systme dexploitation
UNIX sur une machine du nom DEC-PDP 11 inventrent le langage C bien que leur ide principale
ne portait pas cet objectif. En 1980, ce langage reu le nom du C traditionnel. Ce nest quen 1990
quil y eut la standardisation du C par American National Standard Institute. Le langage C devint alors

Dr. Eugne C. EZIN.

ANSI C. Ce standard est aussi adopt par ISO (International Standard Organisation) qui est
lorganisation internationale de normalisation. De nos jours, on parle de Standard C ANSI/ISO ou
simplement ANSI C.
Le langage C permet lutilisateur de se rapprocher du matriel et de communiquer de trs prs
avec lordinateur. Cest pourquoi bien que le C soit un langage de programmation structure
gnraliste, il a t originellement associ la programmation dapplications systme et offre de ce
fait lutilisateur une souplesse et une puissance considrables. Mais, pourquoi la programmation
est-elle aussi importante ?

2. La programmation
Les ordinateurs sont des machines parfaitement idiotes dans la mesure o ils ne font que ce
qui leur est demand. Pour rsoudre un problme avec un ordinateur, vous devez formuler la solution
du problme sous forme dinstructions comprhensibles par lordinateur utilis. Un programme nest
quun ensemble dinstructions ncessaires la rsolution du problme pos. La manire ou la
mthode utilise pour rsoudre le problme est appel un algorithme. De manire gnrale, pour
rsoudre un problme donn, vous raisonnez tout dabord en termes dalgorithme et ne dveloppez
quultrieurement le programme permettant de mettre en uvre cet algorithme. Une fois lalgorithme
clairement dfini, on peut se lancer dans lcriture des instructions ncessaires son implmentation
pour un systme particulier. Ces instructions sexpriment dans un langage spcifique comme le
langage C que nous allons prsenter dans la suite de document. Nous avons prcdemment fait
mention dun systme particulier. Il sagit du systme dexploitation.
Il existe fondamentalement deux types de langages : les langages compils et les langages
interprts. Mais rappelons rapidement des notions sur les systmes dexploitation.

3. Les systmes dexploitation


Un systme dexploitation est un programme qui contrle la totalit du fonctionnement dun
ordinateur. Toutes les oprations dentre et sortie sont canalises par le systme dexploitation.
Le systme dexploitation gre galement les ressources du systme et lexcution des programmes.
Du point de vue historique, les systmes dexploitation taient associs un certain type

Dr. Eugne C. EZIN.

dordinateurs. Mais par la suite, cela nest plus vrai. Le systme dexploitation Unix par exemple, crit
compltement en C, est exceptionnel pour la possibilit de linstaller sur diffrents types
dordinateurs. Le systme dexploitation Windows XP de Microsoft est un systme destin aux
processeurs Pentium et compatibles.

4. Les langages interprts


Un interprteur analyse et excute un programme simultanment. Cette mthode facilite
habituellement le dbogage. Les langages interprts sont nettement plus lents que les langages
compils puisque les instructions ne sont pas converties en langage de bas niveau avant leur
excution. Le Basic comme Matlab par exemple sont des langages interprts.

5. Structure dun programme C


Avant daborder concrtement la structure dun programme C, voyons dabord les mots rservs de
ce langage de programmation de niveau moyen. Le C traditionnel a adopt 27 mots rservs. En
1990, la norme ANSI en a ajout 5 pour un total de 32. En voici la liste complte de ces mots cls qui
constituent les commandes essentielles du langage de programmation C.

auto

break

case

char

const

continue

default

do

double

else

enum

extern

float

for

goto

if

int

long

register

return

short

signed

sizeof

static

struct

switch

typedef

union

unsigned

void

volatile

while

Les mots cls souligns sont ceux que la norme ANSI C a rajout lors de la standardisation
tandis que les mots cls non souligns sont ceux du C traditionnel. Voyons maintenant la structure
dun programme C.
Un programme C est form dune ou plusieurs fonctions dont lune de nom main() est
obligatoire. Toutes les fonctions sont de mme niveau. Cela veut dire quaucune fonction nest plus
importante que lautre. Un programme C senregistre sous le nom dun fichier dextension c. Un
diteur de texte suffit pour crer le fichier source dun programme en C.

Plusieurs compilateurs sont proposs pour lexcution des programmes crits en C. Sous
lenvironnement UNIX par exemple, on peut utiliser le compilateur cc (C Compiler), le compilateur gcc
(GNU project C) etc. Les syntaxes sont similaires pour la plupart des cas. Nous verrons plus loin une

Dr. Eugne C. EZIN.

tude plus dtaille du compilateur Visual Studio C++ de Microsoft. Considrant le compilateur gcc,
la syntaxe est la suivante si nous supposons que le programme C est de nom programme.c.
$gcc -o programme programme.c
$./prog1

Pour les initis au systme dexploitation UNIX de SUN, on peut considrer et cest ainsi
dailleurs que les commandes UNIX sont des programmes excutables crits en langage C. Cest
surprenant ? Non, cest ainsi. On en saura davantage travers ce cours.

5.1. Premier programme C


Nous allons un petit dtour en utilisant les fonctions lmentaires du compilateur Visual Studio C++
pour voir la sortie du programme suivant lcran dont le code se prsente comme suit:
#include<stdio.h>
int main()
{
printf("Bienvenu dans le monde de C :") ;
return 0 ;
}

Lorsque tout se passe bien la phase de compilation et la phase dexcution, vous verrez
lcran :
Bienvenu dans le monde de C :

6. Les expressions
Les lments de base du langage de programmation C sont les expressions. Elles sont
composes des lments atomiques de C que sont les donnes et les oprateurs. Les donnes
peuvent tre reprsentes par des variables ou des constantes. Comme la plupart des langages de
programmation, le C offre la possibilit dutiliser plusieurs de types de donnes et le C est aussi dot
dune gamme doprateurs.

6.1. Les types de base


Il existe cinq types de base qui sont : char, int, float, double, et void. Le type void a t
introduit par la norme ANSI C.

Le type char est utilis pour reprsenter les entiers sur 8 bits. Le bit (BInary digiT)
tant linformation binaire la plus lmentaire.

Le type int est utilis pour reprsenter les entiers sur 16 bits.

Le type float est employ pour reprsenter les entiers sur 32 bits.

Le type double est utilis pour reprsenter les entiers sur 64 bits.

Dr. Eugne C. EZIN.

Le type void est un peu spcial. On lutilise soit pour signifier quune fonction na pas
de type, soit pour signifier quune fonction ne reoit aucun argument. Mais attention,
en cas dabsence du type le type par dfaut est le type int. La norme ANSI permet
surtout la portabilit des programmes.

Exemple :
Expliquez les caractristiques des fonctions ci-dessous. Quelle est la norme utilise dans chaque
cas ?
void f(void){

int g(){

h(void){

Norme ANSI C

C traditionnel

Norme ANSI C

6.2. Les modificateurs des types de base


Le modificateur change la signification du type de donnes pour ladapter avec plus de
prcision aux diffrentes situations. Il existe quatre modificateurs pour quatre types de base (char, int,
float, double) que sont : signed

unsigned

long

short

Il est possible dappliquer les quatre modificateurs au type int et les modificateurs signed et
unsigned char. Le modificateur long sapplique au type double.
La table suivante donne les diffrentes combinaisons des types de donnes indiquant aussi les
dimensions en bits et les intervalles.
TYPE
char
unsigned char
signed char
int
unsigned int
signed int
short int
unsigned short int
signed short int
long int
signed long int
unsigned long int
float
double
long double

DIMENSION
8
8
8
16
16
16
16
16
16
32
32
32
32
64
80

INTERVALLE
-128 127
0 255
-128 127
-32768 32767
0 65535
-32768 32767
-32768 32767
0 65535
-32768 32767
-2.147.483.648 -2.147.483.647
-2.147.483.648 -2.147.483.647
0 4.294.967.295
Six chiffres pour prcision
Dix chiffres pour prcision
Dix chiffres pour prcision

Exercice : Dterminer la taille des types de base sur votre machine.


#include <stdio.h>
int main(){

Dr. Eugne C. EZIN.

printf("\
printf("\nLa taille de int est :%d \n",sizeof(int)) ;
return 0 ;
}

6.3. Importances de connatre la taille des types


Il est important que le programmeur choisisse aprs une profonde analyse pour le choix des types de
variables afin dviter les dbordements du domaine de valeur. Voici des exemples qui illustrent les
consquences lies ces problmes.


Nous avions tous entendu parler du fameux bogue de lan 2000 ; il ne sagit pas en fait dun
problme de dbordement de domaine de valeur mais plutt dun codage des annes sur
deux caractres seulement. Ce qui tait insuffisant par exemple, pour faire la distinction entre
1904 et 2004. Ce problme a t anticip plusieurs annes plus tt par les pays du monde
de sorte quaucun incident majeur na t dplor.

Lexplosion dAriane 5 le 4 juin 1996. Un vol de la fuse Ariane 5 sest termin par une
explosion 37 secondes. Des analyses effectues ont permis de comprendre quil sagissait
dune erreur logicielle. En effet, la composante horizontale de la vitesse, stocke en rel
double prcision sur 64 bits, tait convertie en entier 16 bits sign. Or, la valeur dpassait
+32 767 de sorte que la conversion a chou. Le calculateur de bord qui contrlait la
trajectoire du lanceur a alors dcroch, conduisant lexplosion de la fuse. La portion de
code qui comportait lerreur a t rcupre du code qui pilotait le lancement dAriane 4. Or, il
se trouve quAriane 5 a une trajectoire plus rapide et plus incline quAriane 4. Ce qui ne
posait donc aucun problme avec la version prcdente du lanceur, a dgnr avec le tir
dAriane 5.

Janvier 2038, chronique dun bogue annonc. Les systmes dexploitation grent une
horloge interne cadenc toutes les secondes et dont lorigine a t arbitrairement fix au 01
janvier 1970. Cette horloge compte les secondes depuis cette date de rfrence. Il se trouve
que certains systmes mme rcents grent cette horloge interne sous la forme dun entier
31

sign sur 32 bits. On voit donc une possibilit de 2

secondes aprs la date de rfrence.

Avec cette information, on peut calculer la date du prochain bogue qui se produira aprs 68
annes, 35 jours, 3 heures, 14 minutes et 8 secondes. En tenant aussi compte des annes
bissextiles, on en dduit que lanomalie se produira le 19 janvier 2038 3h 14 minutes 8
secondes. Il faut remarquer les systmes dexploitations Windows XP sont vulnrables
cette faille. Par contre, les systmes NetBSD et Linux ne seront pas vulnrables qu partir
de 2106. Pour plus de dtails, on peut visiter le site www.2038bug.com

Dr. Eugne C. EZIN.

10

6.4. Les commentaires


Les commentaires sont un moyen efficace pour la documentation dun programme. Nous
conseillons vivement de bien commenter les programmes pour faciliter leur rutilisation et leur
maintenance. La forme des commentaires en C est /* ceci est un commentaire */ et permet de mettre
en commentaire une ligne ou plusieurs lignes.
Le C++ introduit en plus un autre type de commentaire qui est // qui permet de mettre en
commentaire une seule ligne.

6.5. Les identificateurs


Un identificateur est un

nom au moyen duquel on souhaite manipuler linformation. Dans

lexemple, int nombre ; le compilateur rserve 2 bytes pour y stocker des nombres du type int.
Comme la mmoire de lordinateur est vaste (mais limite), on peut y disposer nimporte quoi et
nimporte o. Il convient alors de savoir o se trouve ses deux bytes : do la notion dadresse.
Pour connatre ladresse dune variable, on utilise loprateur &.
Exemple : printf("ladresse de nombre est %p", &nombre) ;
La longueur dun identificateur nest pas limite mais seule les 32 premiers caractres sont
pris en compte par le compilateur. Voici les qulesques principes adopter pour choisir un
identificateur :

un identificateur doit commencer par une lettre ou le blanc soulign ;

les caractres suivants autoriss sont les chiffres ou tout autre caractre except les
lettres accentus.

Exemple : Indiquer parmi les identificateurs suivants ceux qui sont valides :
a, Somme, prix-de-vente, prix_ de_vente, numro, text23, salut?, valeurprix, toto#.

6.6. Les variables


Une variable correspond une zone de mmoire utilise pour contenir une information et
cette information peut tre modifie par le programme. Toute variable doit tre dclare avant dtre
utilise.
Pour dfinir une variable, (ou mme la dclarer), on utilise la syntaxe suivante :
type id1, id2 ;

La notion de dclaration ou de dfinition dune variable nest pas la mme que la notion de
dclaration ou de dfinition dune fonction. Nous reviendrons sur ce dernier aspect pendant ltude
des fonctions.

Exemple :

int i, j ;
short int i, j ;
unsigned
unsigned int ui ;
double balance, profit ;

Dr. Eugne C. EZIN.

11

char ch1, ch2 ;

On peut initialiser certaines variables lors de leur dclaration :


char ch1=\
ch1=\n, ch2=a ;

6.6.1. Les variables locales


Les variables locales sont dclares lintrieur dune fonction. On parle aussi de variables
automatiques. Lutilisation du mot cl auto est de nos jours obsolte. Les variables locales sont
utilises lintrieur du bloc dans lequel elles sont dclares. La vie dune variable locale est lie
lexcution du bloc de code dans lequel elle est dclare.
void func1(){
int x ;

int x ;

x=10 ;

x=x=-5 ;

void func2(){

La variable x de la fonction func1() ne voit pas celle de la fonction func2().

La dclaration dune variable locale lintrieur dun bloc conditionnel comporte un avantage d
au fait que lespace mmoire sera allou la variable si cela est ncessaire seulement lintrieur du
bloc. Cette technique est trs utile en C++ mais pas en C. En effet, en langage C, les variables
locales sont dclares au dbut du bloc et avant toute instruction.
int func(){
int i ;
i = 5 ;
int j ; /* ceci gnre une erreur */
j=2 ;
}

6.6.2. Les variables globales


Les variables globales sont dclares lextrieur de toute fonction. Chaque fonction ou expression
peut en faire usage indpendamment du bloc de code dans lequel elles se trouvent.
int count ;
void func1() ;
void func2() ;

int main(){
count = 100 ;
return 0 ;

Dr. Eugne C. EZIN.

12

void func1() {
int temp ;
temp = count ;
func2() ;
printf("Count est egale a %d:", count) ;
}

int COUNT = 100 ;


void func2() {
int count, counter ;
count = 5 ;
counter = count + COUNT ;
}

La porte dune variable globale est du haut vers le bas. En dautre terme, la fonction func1()
ne peut faire usage de la variable globale COUNT.

6.6.3. Les paramtres formels


Un paramtre formel est une variable dclare comme paramtre ou argument dune
fonction. Un paramtre formel se comporte exactement comme une variable locale.

6.7. Les modificateurs daccs


Un modificateur daccs est un mot rserv qui permet de modifier le sens et la porte dune
variable. Il existe plusieurs modificateurs daccs qui sont static, extern, const, register, volatile. Nou
ne parlerons que des modificateurs tels que static, extern, const, register dans ce cours pour
simplicit.

6.7.1. Le modificateur static


Une variable static garde sa valeur dun appel lautre du bloc dans lequel elle est dfinie. Lide est
de briser le principe de la variable locale pour quelle se comporte comme une variable globale.
Considrons lexemple suivant :
Exemple :
#include<stdio.h>

int main(){

Dr. Eugne C. EZIN.

13

int j ;
int foo() ;
for(j=1 ;j<9 ;j++)
foo() ;
printf("%d",foo()) ;
return 0 ;
}

int
int foo(){
static int i=0 ;
i= i+1 ;
return i ;
}

Excuter ce code et enlever le modificateur daccs static et expliquer les rsultats.

6.7.2. Le modificateur register


Le modificateur daccs register demande au compilateur de conserver la valeur de la variable dans
un registre du CPU (Central Processing Unit) et non en mmoire RAM (Random Access Memory)
comme les autres variables. Ce qui acclre lexcution du programme.

6.7.3. Le modificateur extern


Dans le corps dune fonction dun fichier source 1, si lon veut accder une variable globale dfinie
dans un autre fichier source 2, il faut alors dclarer la variable globale avec le modificateur extern.
Exemple : extern float val ;
Source 1
float val ;
int main(){
. . .

func1(){
. . .
}

Source 2

Dr. Eugne C. EZIN.

14

extern float val;


func2(){
. . .
}

La dclaration extern neffectue pas une rservation demplacement de variable mais prcise
simplement que la variable globale est dfinie ailleurs et en prcise seulement le type.

6.7.4. Le modificateur const


Les variables de qualificatif const ne peuvent pas tre modifies par le programme mais il est
possible de leur assigner une valeur initiale. Le compilateur est libre de disposer ces variables de
modificateur daccs const dans une zone quelconque de la mmoire.
const int a= 20 ;

Lusage de const dans la dclaration du paramtre formel dune fonction assure que le code
prsent lintrieur de la fonction ne peut modifier lobjet point par le paramtre.
Plusieurs fonctions de la librairie standard utilisent const pour la dclaration des paramtres
formels.

6.7.5. Le modificateur volatile


Le modificateur volatile indique au compilateur que la valeur dune variable peut tre modifie en
mode non spcifi explicitement par le programme.

6.7.6. Les chanes constantes


Une chane constante est forme dun groupe de caractres entre les griffes cest dire " ". Une
chane de caractres se termine par le caractre nul not \0. Cest le dlimiteur. Voici quelques
caractres particuliers :
\a

bip sonore

\b

backspace

\n

pour le caractre newline

\r

pour le carriage return

\t

pour la tabulation horizontale

\0

pour le caractre nul

\\

caractre backslash

\v

pour la tabulation verticale

pour le caractre griffe

\?

pour le caractre ?

\f

pour le saut de page

Dr. Eugne C. EZIN.

15

7. Les oprateurs
Le langage C offre plusieurs oprateurs. Il existe quatre principaux groupes doprateurs. les
oprateurs arithmtiques, les oprateurs relationnels, les oprateurs logiques et les oprateurs bit
bit. Nous ne parlerons pas de ces derniers puisque cest vu dans le cours de Structure Interne des
Ordinateurs.

7.1. Loprateur daffectation


Loprateur = a pour but de modifier le contenu de son oprande en lui affectant la valeur fournie par
lvaluation de son oprande source.
La syntaxe est la suivante :
destination = source ;

Exemple :

x=y=z=0;

Sa priorit est de droite gauche. Cest dire que le compilateur lvalue de la faon suivante : x = (y
= (z = 0)) ;

7.2. Les oprateurs arithmtiques


Les oprateurs arithmtiques sont - + * / et %. Ils ont le sens habituel quon leur connat. Il faut se
rfrer la table des priorits pour voir comment les associer.

7.3. Les oprateurs dincrmentation et de dcrmentation


Ces oprateurs unaires ajoutent ou retranchent une unit leur oprande.
x = x + 1 ; quivaut crire ++x ;
x = x - 1 ; quivaut crire x-x-- ;

Mais la position des oprateurs ++ et -- joue un rle dterminant. Voyons-le par lexemple
suivant :
x = 10 ;

x = 10 ;

y = ++x ;

y = x++ ;

(ici y vaut 11 et x vaut 11)

(ici y vaut 10 et x vaut 11)

Pouvez-vous tirer les conclusions ?

7.4. Les oprateurs logiques


Les oprateurs logiques sont :
&& pour la conjonction et (AND). Cet oprateur est binaire.
|| pour la disjonction ou (OR). Cet oprateur est binaire.
! pour la ngation (NOT). Cet oprateur est unaire.

Dr. Eugne C. EZIN.

16

7.5. Les oprateurs relationnels


Les oprateurs relationnels sont :
<

>

>=

<=

==

!=

7.6. Loprateur ternaire


Loprateur ? : est un oprateur qui accepte trois oprandes. Cest dailleurs le motif pour lequel il est
appel oprateur ternaire.
Sa syntaxe est :
expr1 ? expr2 :expr3 ;

Lexpression expr1 est value. Si le rsultat est vrai alors expr2 devient la valeur de
toute lexpression sinon cest lexpression expr3.
Exemple :
x = 10 ;
y =x > 9

? 20 : 10 ;

Cette dernire instruction affecte la variable y la valeur 20. En effet, (x>10) dans le
cas o la variable x reoit la valeur 10 est une expression vraie. Donc cest la deuxime
expression qui est value i.e. y reoit la valeur 20.

7.7. Les oprateurs de casting


Cet oprateur monadique est trs particulier et permet au programmeur de forcer la conversion dune
quelconque expression dans un type de son choix. Sa syntaxe est la suivante :
(type) (expression) ;

Considrons la dclaration suivante :


int n, p ;
Lexpression (double)(n/p) aura comme valeur celle de lexpression entire n/p. Donc la bonne
expression crire est par exemple (double)n/p qui convertit n en double avant de faire le rapport
n/p. Par consquent le rsultat reflte ce qui est attendu.

7.8. Loprateur sizeof


Cet oprateur dans son emploi ressemble celui dune fonction. Il fournit la taille en octet et peut
sappliquer une variable de mme qu un type. il offre les intrts suivants :

lorsque lon souhaite crire des programmes portables dans lesquels il est ncessaire de
connatre la taille exacte de certains objets ;

il permet dviter davoir calculer soit-mme la taille des objets de type relativement
complexe pour lequel on nest pas certain de la manire dont il sera implant par le
compilateur. Cest le cas des structures que nous verrons plus loin.

Dr. Eugne C. EZIN.

17

7.9. Loprateur squentiel not ,


Cet oprateur permet dexprimer plusieurs calculs successifs au sein dune mme expression. Par
exemple :
val * tot, p + q
est une expression qui value dabord val*tot, puis p + q et qui prend comme valeur la dernire
expression calcule. On verra des exemples pour la pratique de cet oprateur.

7.10. La table des priorits et des associativits des oprateurs


Oprateurs
() []

Associativit
de gauche droite

+ - ++ -- ! ~ * & cast sizeof (monadique)

de droite gauche

* / %

de gauche droite

(diadique)

+ -

de gauche droite

<< >>

de gauche droite

< <= >

>=

de gauche droite

&

de gauche droite

de gauche droite

de gauche droite

&&

de gauche droite

II

de gauche droite

?:

de gauche droite

+=

-=

*=

/=

%= &= ^= I= <<= >>=

de droite gauche
de gauche droite

8. Les instructions de contrle


Pour une meilleure habitude de programmation, il est souhaitable de se familiariser avec les
instructions pour leur bonne manipulation.

8.1. Linstruction if, if else et loprateur ternaire

Pour linstruction if la syntaxe est la suivante :


if (expr) instruct;

Si expr est vraie alors lexpression ou le groupe dexpressions instruct est value.

Pour linstruction if else la syntaxe est la suivante :


if (expr) instruct1;
else

instruct2 ;

Dr. Eugne C. EZIN.

18

Si expr est vrai alors lexpression ou le groupe dexpressions instruct1 est value. Dans le cas
contraire, cest lexpression ou le groupe dexpressions instruct2 qui est value.
Remarque : la syntaxe
if (expr) instruct1;
else

instruct2 ;

est quivalente expr ? instruct1 : instruct2 ;


Exemple : Implmenter lalgorithme pour la rsolution dune quation du second degr dans
2

lensemble des nombres rels : ax +bx +c.

#include<stdio.h>
#include<math.h>

int main(){
float delta,racine1,racine2 ;
delta = b*b - 4*a*c ;
if (delta > 0) {
racine1 = -b-sqrt(delta) ;
racine2 = -b+sqrt(delta) ;
printf("les racines sont : %f, %f",racine1, racine2) ;
}
else
printf("lequation na pas de solution") ;
return 0 ;
}

8.2. Linstruction switch


Linstruction switch permet la slection de plusieurs options. Elle contrle successivement la valeur
de lexpression avec la liste des constantes entires ou caractres. Sa syntaxe est la suivante :
switch(expr){
case constante1 :
instruction 1;
break ;
case constante2 :
instruction 2 ;
break ;

Dr. Eugne C. EZIN.

19

case constante3
constante3 :
instruction 3 ;
break ;

default :
instructionN ;
}

Lutilisation de break est vivement souhaite pour un meilleur contrle des squences. La
suppression dun break fait que linstruction case immdiatement suivante est excute.
Exemple :
void
void menu(void){
char ch ;
printf("1. Verification\
Verification\n ") ;
printf("2. Correction \n ") ;
printf("3. Affichage\
Affichage\n ") ;
printf(" Appuyer sur une autre touche pour sortir\
sortir\n") ;
printf(" Entrer votre choix :

") ;

do{
ch = getchar() ;
switch(ch){
case 1 :
checkSpell() ;
break ;
case 2 :
correctError() ;
break ;
case 3 :
dispError() ;
break ;

default :
printf("Aucune option nest choisie") ;
}
}while(ch !=1 && ch !=2 ch !=3) ;

Dr. Eugne C. EZIN.

20

8.3. Linstruction for


La syntaxe gnrale de linstruction for est la suivante :
for (debut ;condition ;poursuite)

debut est linstruction daffectation initiale ; condition est lexpression relative la larrt de la
boucle ; poursuite permet de prciser le pas pour litration.
Exemple :
#include<stdio.h>

int main(){
int i ;
for(i=1 ;i < 10 ; i++)
printf("\
printf("\nle carre de %d est %d", i,i*i) ;
return 0 ;
}

8.4. Linstruction while


La syntaxe de la boucle while est la suivante :
while(expr)

instruct ;

o instruct dsigne une instruction ou une suite dinstructions.


Linstruction while linstar de la boucle for contrle la condition expr avant lexcution de la boucle.
Exemple : Cet exemple avec linstruction while est une routine qui reoit en entre une touche du
clavier jusqu ce que lutilisateur nait entr le caractre A.
int waitForChar(void){
char ch ;
ch=\
ch=\0 ;
while(ch != A)
ch = getchar() ;
return ch ;
}

Dr. Eugne C. EZIN.

21

8.5. Linstruction do-while


A la diffrence des instructions for et while, linstruction do while contrle la condition de poursuite
des itrations la fin de la boucle. En dautre terme linstruction do while est excute au moins une
fois.
La syntaxe de linstruction do while est la suivante :
do{
instruct ;
} while(expr) ;

Exemple : Cet exemple permet de crer un menu choix pour une interface plus commode
lutilisateur.
void menu(void){
char ch ;
printf("1. Verification\
Verification\n ") ;
printf("2. Correction \n ") ;
printf("3. Affichage\
Affichage\n ") ;
printf(" Faites votre choix : ") ;
do{
ch = getchar() ;
switch(ch){
case 1 :
checkSpell() ;
break ;
case
case 2 :
correctError() ;
break ;
case 3 :
dispError() ;
break ;
}
}while(ch !=1 && ch !=2 ch !=3) ;
}

8.6. Linstruction break


Linstruction break a deux usages :

Dr. Eugne C. EZIN.

22

elle semploie avec un switch

pour sortir dune boucle sautant la condition.

Exemple :
Cet exemple montre un usage de linstruction break dont lobjectif est de terminer une boucle.
#include<stdio.h>
int main(void){
int t ;
for(t=0 ;t<100 ;t++){
printf("%d ", t) ;
if(t==10) break ;
}
return 0 ;
}

8.7. Linstruction return


Cette instruction permet de restituer la valeur dune fonction. Cest le cas de la syntaxe
return expr ;

que lon rencontre la fin des fonctions qui retournent une valeur.

Une fonction de type void ne peut contenir une instruction de la forme return expr;mais
expr;
elle peut contenir seulement return ;

Linstruction return permet aussi de passer le contrle au systme dexploitation aprs


lexcution dun programme.

8.8. La fonction exit()


La fonction exit() de la librairie standard ressemble beaucoup linstruction break sauf que la fonction
exit() provoque une sortie immdiate lintrieur du programme et passe la main au systme
dexploitation. Pour utiliser cette fonction il faut inclure le fichier dentte stdlib.h.
Exemple : Cest une reprise de lexemple du menu.
void menu(void){
menu(void){
char ch ;
printf("1. Verification\
Verification\n ") ;
printf("2. Correction \n ") ;
printf("3. Affichage\
Affichage\n ") ;
printf("4. Sortie du programme\
programme\n") ;
do{
ch = getchar() ;
switch(ch){
case 1 :

Dr. Eugne C. EZIN.

23

checkSpell() ;
break ;
case 2 :
correctError() ;
break ;
case 3 :
dispError() ;
break ;
case 4 :
exit(0) ;
}
}while(ch !=1 && ch !=2 ch !=3) ;
}

8.9. Linstruction continue


Linstruction continue fonctionne comme break mais au lieu de terminer la boucle, provoque
lexcution successive de la boucle.
Exemple : Cet exemple de programme permet de compter le nombre despace dans une phrase.
#include<stdio.h>
int main(void){
char s[80], *str ;
int space ;
printf("Entrer une chane : ") ;
gets(s) ;
str = s ;
for (space =0 ;*str ; str++){
if(*str != )

continue
continue ;

space++ ;
}
printf("Il y a %d espaces", space) ;
return 0 ;
}

Dr. Eugne C. EZIN.

24

Conclusion
Nous avons prsent dans ce chapitre les lments de base du langage C. Une bonne
matrise des arguments exposs est indispensable pour une meilleure comprhension des
arguments de la suite.

Dr. Eugne C. EZIN.

25

Prsentation du compilateur Visual C++


Introduction
Avant daborder ltude approfondie des arguments du langage C proprement dit, nous avons jug utile de
prsenter dabord le compilateur qui sera notre instrument de travail durant ce cours. Le nom du compilateur
est Visual Studio C++ de Microsoft. Le titre de ce chapitre peut donc paratre trompeur car nous navons pas
lintention de prsenter ce produit trs complet de Microsoft pour les dveloppeurs mais plutt vous voulons
indiquez lEtudiant quelques outils pour une meilleure utilisation de Win32 Console Application.

1. Le compilateur
Nous rappelons ici que le compilateur est un traducteur de code source en langage machine. Les
diffrentes de la compilation sont la compilation proprement dite, ldition de liens et lexcution.

La phase de compilation consiste traduire le programme source en module objet. En


langage C, compte tenu de lexistence dun prprocesseur, cette opration de compilation
comporte en fait deux tapes : le traitement par le prprocesseur et la compilation
proprement dite. ce dernier excute simplement les directives qui le concernent (il les
reconnat au fait quelles commencent par un caractre #). Il produit, en rsultat, un
programme source en langage C pur . Notez bien quil sagit toujours dun vrai texte, au
mme titre quun programme source : la plupart des environnements de programme vous
permettent dailleurs, si vous le souhaitez, de connatre le rsultat fourni par le prprocesseur
(nous y reviendrons un peu plus tard). Le rsultat de la compilation proprement dite porte le
nom de module objet.

Ldition de lien consiste crer des liens entre les diffrents modules objets qui sont
obtenus aprs de la compilation dans le but de produire un excutable.

Lexcution dun programme voir lcran ou sur une unit de sortie le rsultat produit par
le programme.

2. La cration de projet Win32 console application


Nous allons dcrire ici les diffrentes tapes pour la cration dune application qui utilise une fentre
interactive avec lutilisateur. Cela se ralise grce au choix du projet Win32 Console Application de
Visual Studio C++.

Crer un rpertoire sur le disque pour contenir les diffrentes tches excuter ;

Lancez le programme de visual C++ ;

Dans le menu "File", choisissez "New". Vous aurez une fentre qui ressemble celle-ci :

Dr. Eugne C. EZIN.

26

Choisissez le type de projet "Win32 Console Application". C'est ce type de projet que
nous ferons tout au long de ce cours. Dans la case "Project name", entrez TD05 par
exemple et dans la case "Location", choisissez le rpertoire que vous avez cr
prcdemment.

Cliquez sur "OK", cliquez ensuite sur "Finish" dans la fentre qui apparatra, et
cliquez encore une fois "OK". Vous avez maintenant cr un projet vide, qui ne contient
pas encore de programme. C'est ce que nous allons ajouter maintenant.

Encore une fois, dans le menu "File", choisissez "New". Vous devriez voir apparatre
cette fentre :

Dr. Eugne C. EZIN.

27

Choisissez "C++ Source File" comme type de fichier. Il s'agit du type de fichier qui sera
utilis pour vos codes sources tout au long de ce cours. Dans la case "File name",
inscrivez "main.c". Attention : l'extension .c ici est importante, si vous l'omettez, le type de
fichier ne sera pas le bon. Vrifier que la fentre que vous avez correspond bien celle de
l'image ci-dessus et cliquez "OK".

Dans la fentre d'dition de Visual C++, reproduisez maintenant le texte suivant :


#include <stdio.h>
int main(void)
{
printf("Bienvenue dans le monde de C.\
C.\n\n");
return 0;
}

Il s'agit de votre premier programme C.


main.c" dans le menu "Build".

Pour le compiler, cliquez sur "Compile

Pour faire l'dition de liens (crer un code

excutable), cliquez sur "Build main.exe" dans le menu "Build". Et enfin, pour
excuter le programme, cliquez sur "Execute main.exe" dans le menu "Build".

Dr. Eugne C. EZIN.

28

Notez que chacune de ces fonctionnalits ont un raccourci clavier et aussi un bouton
dans la fentre de Visual C++.
A lexcution de ce programme, on obtient la nouvelle fentre suivant qui est celle de la
sortie :

3. Le dbogueur
Le dbogueur est un instrument qui aide le programmeur dtecter certaines erreurs dans un code.
Les tapes qui suivent dcrivent comment on peut utiliser le dbogueur pour dboguer ce
programme. Il est clair que beaucoup dentre vous peuvent tout simplement regarder le programme et
trouver assez rapidement le problme sans avoir recours au dbogueur. Le but de cet exercice nest
pas de vous faire croire quil faut absolument utiliser le dbogueur pour dboguer un programme,
mais plutt de vous faire dcouvrir les possibilits que vous offre le dbogueur. Le meilleur outil de
dboguage demeure votre intelligence.

Avant de commencer dboguer le programme, on doit dabord se poser une question. Estce que jai besoin de vrifier tout le programme ou seulement une partie ? Considrons le
programme suivant :

#include <stdio.h>
int main(void){

int n, somme;
printf("\
printf("\nEntrer un entier: ");
fflush(stdin);
scanf("%d",&n);
while (n < 5){
somme = somme + n;
n = n + 1;
}
printf("\
printf("\nLa somme est: %d: ", somme);
return 0;

Dr. Eugne C. EZIN.

29

Dans notre programme, la saisie du premier nombre de la somme sera faite laide du clavier.
Nous allons donc commencer le dboguage partir de la boucle while aprs la saisie.

Placez un breakpoint
breakpoint (point darrt) la ligne o se trouve le while. Pour ce faire, placez
votre curseur cette mme ligne et appuyez la touche F9. Vous devriez voir un point rouge
apparatre tel que sur la figure ci-dessous.

Dmarrez le dbogueur en appuyant sur la touche F5 ou en allant dans le menu Build et en

choisissant Start Debug Go. Ce que vous venez de faire est tout simplement dexcuter le
programme et darrter son excution au premier breakpoint. Prenez note quil peut y avoir plus dun
breakpoint dans un programme et que pour sarrter au prochain breakpoint on na qu appuyer la
touche F5 encore une fois. Notez aussi que sil ny a pas de breakpoint, lexcution se rendra jusqu
la fin du programme.

Avant que le programme puisse sarrter au breakpoint, il faut dabord faire les saisies.
Entrez les nombres demands avant de passer ltape 5. Une fois les nombres entrs,
votre fentre devrait ressembler la fentre ci-dessous. Notez la flche jaune au-dessus du
point darrt. Cette flche indique que vous tes rendu excuter cette ligne, mais quelle
nest pas encore excute. Notez aussi dans le bas les deux champs Name et Value qui ont

Dr. Eugne C. EZIN.

30

pour valeurs n2 et 3. a signifie tout simplement que la variable n2 a la valeur 3. Les


variables places ici sont seulement les variables qui apparaissent la ligne o nous
sommes rendus dans lexcution du programme. Dans ce cas-ci seule la variable n apparat.

Une autre chose qui intresse lorsquon dbogue un programme est de pouvoir surveiller les
valeurs des variables tout moment du programme. Pour ce faire, allez dans le menu View
et choisissez loption Debug Windows Watch. Votre cran devrait ressembler la fentre
ci-dessous. Dans la case Name, inscrivez somme, ensuite n tel quillustr.

Dr. Eugne C. EZIN.

31

Nous pouvons maintenant commencer dboguer proprement dit. Tout ce que nous avons
fait jusqu maintenant est tout simplement de la prparation. Nous allons continuer
lexcution du programme ligne par ligne de pour pouvoir ainsi vrifier o peut se trouver le
problme.

Appuyez sur la touche F10 ou choisissez loption Step Over dans le menu Debug. Cela
fera avancer la flche jaune jusqu la prochaine instruction. Donc, ce moment-ci nous
venons de vrifier la condition de la boucle while, et comme nous sommes entrs dans la
boucle, la condition tait vraie.

Appuyez encore une fois sur F10 et arrtez-vous ici. Que remarquez-vous ? Trouvez-vous
que la valeur de somme a un sens ? Le problme vient du fait que somme na pas t
initialis !!!. Apportez la correction ncessaire en initialisant somme 0 (vous pouvez faire
ceci la dclaration de somme). Arrtez le dbogueur en appuyant sur Shift + F5 ou en
choisissant loption Stop Debug du menu Debug.

Vous pouvez maintenant observer le fonctionnement correct de votre programme.

Dr. Eugne C. EZIN.

32

4. Les fonctionnalits du dbogueur


Le dbogueur du compilateur Visual C++ comporte plusieurs fonctionnalits qui ont mme des
raccourcis au clavier dont notamment
Raccourcis
Fonctionnalits

vers le clavier

Signification

Excute le programme jusqu'au premier point d'arrt

GO

F5

(Breakpoint). S'il y a plusieurs Breakpoints, le programme


sera excut jusqu'au prochain Breakpoint en appuyant
encore une fois sur la touche F5. S'il n'y a pas de
Breakpoint, le programme s'excute jusqu' la fin.
Entre l'intrieur d'une fonction. Si vous arrivez devant un

Step into

F11

appel de fonction et que vous voulez faire une excution


pas pas de cette fonction vous devez faire un Step into
Excute la ligne de code, mais n'entre pas dans les

Step over

F10

fonctions. Si vous ne voulez pas entrer dans le corps d'une


fonction, par exemple printf(), vous devez faire un Step
over.
Sort d'une fonction. Cette fonctionnalit est pratique si vous

Step out

Shift + F11

tes entr dans une fonction et que vous voulez en sortir


avant d'avoir excut pas pas chacune de ses
instructions.

Run to cursor

Ctrl + F10

Excute le programme jusqu'o le curseur est situ. Cette


fonctionnalit est similaire celle qui utilise les Breakpoints.
Ajoute ou enlve un Breakpoint la ligne o se trouve le

Insert/Remove

F9

curseur. S'il n'y a pas de Breakpoint, un Breakpoint sera


ajout et s'il y en a dj un, il sera enlev.

Breakpoint

Redmarre le dbogueur et excute le programme jusqu'au

Restart

Ctrl + Shift + F5

premier Breakpoint, ou jusqu' la fin s'il n'y a pas de


Breakpoint.

Stop Debugging

Shift + F5

Arrte le dbogueur.
Affiche la fentre de QuickWatch. Dans le champ
Expression, vous entrez la valeur de la variable calculer et

Quick watch

Shift + F9

vous cliquez sur Recalculate pour en connatre la valeur. Si


vous cliquez sur Add Watch, cette variable, ainsi que sa
valeur, sera affiche dans le bas de la fentre de Visual
C++.
Ajoute / Enlve un signet (bookmark) dans le programme.
Cette fonctionnalit est utile si vous avez un gros

Bookmarks

Ctrl + F2

programme et que vous voulez souvent revenir un point


particulier dans le code. Il faut appuyer sur la touche F2
pour atteindre le signet.

Dr. Eugne C. EZIN.

33

Ouvre l'aide en ligne de Visual Studio. Lorsqu'un mot cl

Help

F1

dans le code source est slectionn, la documentation sur


ce mot cl est affiche.

Conclusion
Nous avions travers ce chapitre prsent lenvironnement de dveloppement de Visual C++. Nous avions
surtout prsent le projet Win32 Console Application.

Dr. Eugne C. EZIN.

34

Prsentation du compilateur gcc


Introduction
Dans ce chapitre, nous allons prsenter le compilateur gcc de GNU Project.

Une commande gcc repose habituellement sur la syntaxe suivante :


gcc [option] fichier1 [fichier2 ]

Dr. Eugne C. EZIN.

35

Les entres-sorties conversationnelles


Introduction
Un moyen efficace pour dialoguer avec lordinateur est dutilise le clavier et lcran. Le langage C
propose des fonctions pour bien manipuler les donnes. Le langage C tant fortement typ,
lutilisation des entres sorties conversationnelles ncessite une bonne connaissance des formats.
Dans ce chapitre, nous allons exposer ces arguments.

1. Gnralits
Jusquici, nous avons utilis de faon intuitive les fonctions printf() et scanf() pour afficher des
informations lcran ou pour en lire au clavier. Nous allons maintenant tudier en dtail les
diffrentes possibilits de ces fonctions. Ce qui nous permettra de rpondre des questions telles
que :


Quelles sont les critures autorises pour des nombres fournis en donnes ?

Que se passe-t-il lorsque lutilisateur ne les respecte pas ?

Comment organiser les donnes lorsque lon mlange les types numriques et les
types caractres ?

Que se produit-il lorsque, en rponse scanf(), on fournit trop ou trop peu


dinformations ?

Comment agir sur la prsentation des informations lcran ?

En ce qui concerne la lecture au clavier, nous serons amen mettre en vidence certaines lacunes
dans le comportement de scanf() pouvant entraner des rponses incorrectes et vous fournir
quelques ides sur la manire dy remdier.

2. Sorties lcran : printf()


Nous avons dj vu travers des exemples et des travaux dirigs, que le premier argument de
printf() est une chane de caractres qui spcifie la fois


des caractres afficher tels quels, ou/et

des codes de formats, reprs par %. Un code de conversion (qui fait partie du code de
format) tel que c, d ou f prcise le type de linformation afficher. Un code de format peut
aussi contenir des informations complmentaires agissant sur le cadrage (ou alignement), le
gabarit ou la prcision de la donne afficher.

Voici un tableau qui prcise les codes de formats et les types transforms pour lutilisation de printf().

Dr. Eugne C. EZIN.

36

Code de format

Type transform

%d

int

%i

int

%li

long int

%hi

short int

%u

unsigned int

%hu

unsigned short int

%lu

unsigned long int

%f

double

%e

double scientifique

%c

char

%%

pour le caractre %

%s

pour les chanes de caractres

Voyons quelques exemples :


printf ("Bonjour ");

affiche le mot Bonjour sur lcran.


printf ("Bonjour \n");

affiche le mot Bonjour se terminant par un saut de ligne (le curseur se dplace au dbut de la ligne
suivante).
CODE DE FORMAT TYPE TRANSFORM
printf ("Message > ");

affiche Message > .


printf ("%i", nbreElts);
nbreElts);

utilise un format de conversion pour afficher la valeur entire de la variable nbreElts.


printf ("\
("\n");

effectue un saut de ligne sur lcran.


printf ("le nb dtudiants est : %i\
%i\n", nbEtuds);

affiche dun message accompagnant la valeur de la variable nbEtuds.


printf ("%i %i %i\
%i\n", nbEtuds, nbInt, nbExt);

utilise plusieurs formats de conversion (ici on a 3 formats qui sont utiliss) pour afficher le contenu de
nbEtuds, nbInt et nbExt. Le curseur se dplace au dbut de la ligne suivante.

Dr. Eugne C. EZIN.

37

printf ("%i %f %f %s", nbMontants, somme, moyenne, "ok");

utilise des codes de format de types diffrents pour afficher une valeur entire, deux valeurs relles et
une chane de caractres.

3. Spcifications du gabarit daffichage


Par dfaut, les entiers sont affichs avec le nombre de caractres ncessaires (sans espaces avant
ou aprs). Les flottants sont affichs avec 6 chiffres aprs le point (aussi bien pour le code e que f).
Un nombre plac aprs % dans le code de format prcise un gabarit daffichage, cest--dire un
nombre minimal de caractres utiliser. Si la valeur afficher peut scrire avec moins de caractres,
printf() la fera prcder dun nombre suffisant despaces pour combler le gabarit. En revanche, si la
valeur ne peut scrire convenablement dans le gabarit spcifi, printf() utilisera le nombre de
caractres ncessaires pour afficher la valeur et ignorera le gabarit.
Voici quelques exemples dans lesquels nous fournissons, la suite dune instruction printf(), la fois
des valeurs possibles des expressions afficher et le rsultat obtenu lcran. Nous allons par
convention utiliser le symbole ^ pour reprsenter un espace.

/* entier avec 3 caractres minimum */


(n = 20) printf ("%3d", n); ^20

(n = 3) printf ("%3d", n); ^^3

(n = 2358) printf
printf ("%3d", n); 2358

(n = -5200) printf ("%3d", n); -5200

/* notation dcimale avec gabarit par dfaut */


(x = 1.2345) printf ("%f", x); 1.234500
(x = 12.3456789) printf ("%f", x); 12.345679

/* notation dcimale, gabarit minimum de 10 */


(x = 1.2345) printf ("%10f", x); ^^1.234500
(x = 12.345) printf ("%10f", x); ^12.345000
(x = 1.2345E5) printf ("%10f", x); 123450.000

/* notation exponentielle, gabarit par dfaut */


(x = 1.2345) printf ("%e", x); 1.234500e+000
(x = 123.45) printf ("%e", x); 1.234500e+002
1.234500e+002

Dr. Eugne C. EZIN.

38

(x = 123.456789E8) printf ("%e", x); 1.234568e+010


(x = -123.456789E8) printf ("%e", x); -1.234568e+010

4. Spcification de la prcision
Pour les types flottants, on peut spcifier un nombre de chiffres requis aprs le point dcimal (aussi
bien pour la notation dcimale que pour la notation exponentielle). Ce nombre doit apparatre,
prcd dun point, avant le code de format (et ventuellement aprs le gabarit).
Voici quelques exemples :
printf ("%10.3f", x);

/* notation dcimale, gabarit minium 10 avec 3 chiffres aprs le point */


x = 1.2345 ^^^^^1.235
x = 1.2345E3 ^^1234.500
x = 1.2345E7 12345000.000
printf ("%12.4e", x);

/* notation exponentielle, gabarit minimum 12 avec 4 chiffres aprs le point */


x = 1.2345 ^1.2345e+000
x = 123.456789E8 ^1.2346e+010
^1.2346e+010

Remarques :


Le gabarit comprend les signes + . etc. de mme que tous les caractres.

La fonction printf() fournit en fait une valeur de retour . Il sagit du nombre de caractres
quelle a rellement affichs (ou la valeur -1 en cas derreur). Par exemple, avec :
o

un signe moins (-) plac immdiatement aprs le symbole % (comme dans %-4d
ou %-10.3f) demande daligner laffichage gauche au lieu de laligner (par
dfaut) droite; les ventuels espaces supplmentaires sont donc placs
droite et non plus gauche de linformation affiche ;

le caractre * figurant la place dun gabarit ou dune prcision signifie que la


valeur effective est fournit dans la liste des arguments de printf(). Voici un
exemple dans lequel nous appliquons ce mcanisme au gabarit :

printf ("%8.*f", n, x);


n = 1 x = 1.2345 ^^^^^1.2
n = 3 x = 1.2345 ^^^1.235

Lorsquen raison du gabarit indiqu, la valeur afficher doit tre tronque, elle est arrondie
la dernire dcimale.

La fonction printf() fournit en fait une valeur de retour . Il sagit du nombre de caractres
quelle a rellement affichs (ou la valeur -1 en cas derreur). Par exemple, avec :

Dr. Eugne C. EZIN.

39

5. Les erreurs de programmation


Deux types derreur de programmation peuvent apparatre dans lemploi de printf() notamment :


Code de format en dsaccord avec le type de lexpression. Lorsque le code de format, bien
querron, correspond une information de mme taille (cest--dire occupant la mme place
en mmoire) que celle relative au type de lexpression, les consquences de lerreur se
limitent une mauvaise interprtation de lexpression . Cest ce qui se passe, par exemple,
lorsque lon crit une valeur de type int en %u ou une valeur de type unsigned int en %d. En
revanche, lorsque le code de format correspond une information de taille diffrente de celle
relative au type de lexpression, les consquences sont gnralement plus dsastreuses, du
moins si dautres valeurs doivent tre affiches la suite. En effet, tout se passe alors
comme si, dans la suite doctets (correspondant aux diffrentes valeurs afficher reues par
printf()), le reprage des emplacements des valeurs suivantes se trouvait soumis un
dcalage.

Nombre de codes de format diffrent du nombre dexpressions de la liste. Dans ce cas, il faut
savoir que le C cherche toujours satisfaire le contenu du format. Cela signifie que si des
expressions de la liste nont pas de code de format, elles ne seront pas affiches. Cest le
cas dans cette instruction o la valeur de p ne sera pas affiche :
printf ("%d", n, p);

En revanche, si vous prvoyez trop de codes de format, les consquences seront l encore assez
dsastreuses puisque printf() cherchera afficher... nimporte quoi. Cette instruction, par exemple,
affichera deux valeurs, la seconde tant alatoire :
printf ("%d %d", n);

6. Complment de lecture : la macro putchar()


Linstruction putchar(c); joue le mme rle que printf ("%c", c); Son excution est toutefois plus
rapide, dans la mesure o elle ne fait pas appel au mcanisme danalyse de format. Notez quen
toute rigueur putchar() nest pas une vraie fonction mais pltot une macro. Ses instructions (crites en
C) seront incorpores votre programme grce au prprocesseur par la directive #include <stdio.h>
puisque cette macro est dfinie dans le fichier stdio.h. Alors que cette directive tait facultative pour
printf (qui est une fonction, cest--dire quelle ne seraincorpore votre programme, et sous forme
de code objet, qu ltape de ldition des liens), elle devient absolument ncessaire pour putchar().
En son absence, lditeur de liens serait amen rechercher une fonction putchar() en bibliothque
et, ne la trouvant pas, il vous prsentera un message derreur (en toute rigueur, la fonction
recherche pourra porter un nom lgrement diffrent, par exemple _putchar; cest ce nom qui
figurera dans le message derreur fourni par lditeur de liens).

Dr. Eugne C. EZIN.

40

7. Entres au clavier : scanf()


Nous avons dj rencontr quelques exemples dappels de scanf() en travaux pratiques. Nous y
avons notamment vu la ncessit de recourir loprateur & pour dsigner ladresse de la variable
(plus gnralement de la lvalue) pour laquelle on souhaite lire une valeur.
Malgr les ressemblances quelle prsente par rapport printf(), il existe des diffrences essentielles
notamment :


la signification des codes de formats. Certains codes correspondront des types diffrents,
suivant quils sont employs avec printf ou avec scanf;

linterprtation des caractres du format qui ne font pas partie dun code de format.

Compte tenu de la complexit de scanf(), nous vous en exposerons les diffrentes possibilits de
faon progressive, laide dexemples.

8. Principaux codes de conversion de scanf()


Voici les codes de formats utiliss avec scanf(), accompagns du type de la lvalue correspondante.
CODE DE F
Code de format

Type transform

%d

int

%c

char

%hi

short int

%u

unsigned int

%hd

short int

%hu

unsigned short int

%ld

long int

%f ou %e

float

%lf ou %e

double

%s

chane de caractres

ORMAT TYPE TRANSFORM


Remarque :
Contrairement ce qui se passait pour printf(), il ne peut plus y avoir ici de conversion automatique
puisque largument transmis scanf() est ladresse dun emplacement mmoire. Cest ce qui justifie
lexistence dun code %hd par exemple pour le type short ou encore celle des codes %lf et %le pour
le type double; ces codes sont absents dans le cas de printf().

9. Notion de tampon et de sparateur


Lorsque scanf() attend que vous lui fournissiez des donnes, linformation tape au clavier est range
temporairement dans un emplacement mmoire nomm tampon. Ce dernier est explor caractre
par

Dr. Eugne C. EZIN.

41

caractre par scanf(), au fur et mesure des besoins. Il existe un pointeur de lecture qui prcise
quel est le prochain caractre prendre en compte, afin que tous les caractres entrs soient
analyss.Dautre part, certains caractres jouent un rle particulier dans les donnes : ce sont les
sparateurs. Les deux principaux sparateurs sont lespace et la fin de ligne (\n).

10. Les premires rgles utilises par scanf()


Les codes de formats correspondant un nombre (cest--dire tous ceux du tableau prcdent
excepts %c et %s) entranent dabord lavancement ventuel du pointeur de lecture jusquau premier
caractre diffrent dun sparateur. Puis scanf() prend en compte tous les caractres suivants jusqu
la rencontre dun autre sparateur (en y plaant le pointeur), du moins lorsque aucun gabarit nest
prcis (comme nous apprendrons bientt le faire) et quaucun caractre invalide nest prsent
dans la donne (nous y reviendrons plus tard).Quant au code de format %c, il entrane la prise en
compte du caractre dsign par le pointeur (mme sil sagit dun sparateur comme espace ou fin
de ligne) et le pointeur est simplement avanc sur le caractre suivant dans le tampon.
Voici quelques exemples dans lesquels nous supposons que n et p sont de type int, tandis
que c est du type char. Nous fournissons, pour chaque appel de scanf(), des exemples dentres
possibles (lorsque vous validez la saisie dune donne, ^ dsigne un espace et @ une fin de ligne,
cest--dire un retour chariot) et, en regard, les valeurs effectivement lues.
scanf ("%d%d", &n, &p);
12^25@ n = 12 p = 25
^12^^25^^@ 12@@ n = 12 p = 25
^25@n =12 p =25
scanf ("%c%d", &c, &n);
a25@ c = 'a' n = 25
a^^25@ c = 'a' n = 25
scanf ("%d%c", &n, &c);
12^a@ n = 12 c = ' '

Notez que dans ce cas, on obtient bien le caractre espace dans c. En effet, lespace (de valeur
32
dans la table ASCII) est aussi un caractre au mme titre que tous les autres. Nous verrons, dans un
prochain paragraphe, comment imposer scanf() de sauter les espaces afin dviter la lecture
despaces dans le cas o le code de conversion %c est fourni scanf().

Remarque
Le code de format prcise la nature du travail effectuer pour transcoder une partie de
linformation entre au clavier, laquelle nest en fait quune suite de caractres (codes chacun sur un
octet) pour fabriquer la valeur (binaire) de la variable correspondante. Par exemple, %d entrane en
quelque sorte une double conversion : (suite de caractres) (nombre crit en dcimal) (nombre

Dr. Eugne C. EZIN.

42

cod en binaire). La premire conversion revient faire correspondre un nombre entre 0 et 9 un


caractre reprsentant un chiffre. En revanche, le code %c demande simplement de ne rien faire
puisquil suffit de recopier tel quel loctet contenant le caractre concern.

a. Gabarit maximum
Comme dans les codes de formats de printf(), on peut, dans un code de format de scanf(), prciser
un
gabarit. Dans ce cas, le traitement dun code de format sinterrompt soit la rencontre dun
sparateur, soit lorsque le nombre de caractres indiqus a t atteint (attention, les sparateurs
ventuellement sauts avant de rencontrer un caractre valide ne sont pas comptabiliss !).
Exemple
scanf ("%3d%3d", &n, &p);
12^25@ n = 12 p = 25
^^^^^12345@12@ n = 123 p = 45
25@ n = 12 p = 25

b. Rle dun espace dans le format


Un espace entre deux codes de formats demande scanf() de faire avancer le pointeur au prochain
caractre diffrent dun sparateur. Notez que cest dj ce qui se passe lorsque le code de format
correspond un type numrique. En revanche, cela ntait pas le cas pour les caractres, comme
nous lavons vu un peu avant.
Exemple
scanf ("%d^%c", &n, &c);
/* ^ dsigne un espace, %d^%c est diffrent de %d%c */
12^a@ n = 12 c = 'a'
12^^^a@ n = 12 c = 'a'
12@a@ n = 12 c = 'a'

Linstruction scanf ("%d%c", &n, &c); (sans espace) aurait ici fait en sorte que n aurait dabord
reu la valeur 12 et puis c la valeur du caractre espace, puis scanf() se serait interrompue pour la
raison que voici :

Cas o un caractre invalide apparat dans une donne


Voyez cet exemple, accompagn des valeurs obtenues dans les variables concernes :
scanf ("%d^%c", &n, &c); /* ^ dsigne un espace */
12a@ n = 12 c = 'a'

Ce cas fait intervenir un mcanisme que nous navons pas encore rencontr. Il sagit dun troisime

Dr. Eugne C. EZIN.

43

critre darrt de traitement dun code de format (les deux premiers taient : rencontre dun
sparateur
ou gabarit atteint). Ici, lors du traitement du code %d, scanf() rencontre les caractres 1, puis 2, puis
a. Ce caractre a ne convenant pas la fabrication dune valeur entire, scanf interrompt son
exploration et fournit la valeur 12 pour n. Lespace qui suit %d dans le format na aucun effet puisque
le caractre courant est le caractre a (diffrent dun sparateur). Le traitement du code suivant,
cest--dire %c, amne scanf() prendre ce caractre courant (a) et laffecter la variable c.
(Linstruction scanf ("%d%c", &n, &c); sans espace aurait donc conduit, dans ce cas-ci,
affecter les mmes valeurs aux variables n et c.).
Dune manire gnrale, dans le traitement dun code de format, scanf() arrte son exploration du
tampon ds que lune de ces trois conditions est satisfaite :


rencontre dun caractre sparateur,

gabarit maximal atteint (sil y en a un de spcifi);

rencontre dun caractre invalide par rapport lusage quon veut en faire (par exemple,
un

point ou un caractre pour un entier, une lettre autre que E ou e pour un flottant.). Notez bien laspect
relatif de cette notion de caractre invalide.

11. Arrt prmatur de scanf()


Voyons cet exemple dans lequel nous utilisons la valeur de retour de la fonction scanf().
compte = scanf ("%d^%d^%c", &n, &p, &c); /* ^ dsigne
dsigne un espace */
12^25^b@ n = 12 p = 25 c = 'b' compte = 3
12b@ n = 12 p indfini c indfini compte = 1
b@ n indfini p indfini c indfini compte = 0

La valeur retourne par scanf() nest pas comparable celle retourne par printf() puisquil sagit
cette fois du nombre de valeurs convenablement lues (printf() retourne le nombre de caractres
affichs). Ainsi, dans le premier cas, il nest pas surprenant de constater que cette valeur est gale
3.
Dans le second cas, par contre, le caractre b a interrompu le traitement du premier code %d. Dans
le traitement du second code (%d) scanf() a rencontr demble ce caractre b, invalide pour une
valeur numrique. Dans ces conditions, scanf() se trouve dans lincapacit dattribuer une valeur p
(puisque ici, contrairement ce qui sest pass pour n, elle ne dispose daucun caractre correct).
Dans un tel cas, scanf()

sinterrompt sans chercher lire dautres valeurs et fournit, en retour, le

nombre de valeurs correctement lues jusquici, cest--dire 1.


Dans le troisime cas, le mme mcanisme darrt prmatur se produit ds le traitement du
premier code de format, et le nombre de valeurs correctement lues est 0.
Remarques :


Nous venons de voir la signification dun espace introduit entre deux codes de formats. En
toute rigueur, vous pouvez introduire un tel endroit nimporte quel caractre de votre choix.

Dr. Eugne C. EZIN.

44

Dans ce cas, lorsque scanf()

rencontre un caractre (x par exemple) dans le format, il le

compare avec le caractre courant (celui dsign par le pointeur) du tampon. Sils sont
gaux, il ignore ce caractre, dplace le pointeur sur le caractre suivant et il poursuit son
travail. Dans le cas contraire, il y a arrt prmatur. Une telle possibilit ne doit toutefois tre
rserve qu des cas bien particuliers.


Vous pouvez mme introduire plusieurs caractres dans le code de format. Le principe
expliqu au paragraphe prcdent s'applique ici aussi.

12. Syntaxe de scanf()


Dune manire gnrale, lappel de scanf() se prsente ainsi :
scanf (format,
(format, liste_d_adresses);

o format est une constante chane de caractres (ou encore un pointeur sur une chane de
caractres et o liste_d_adresses est une liste de lvalue, spares par des virgules et dont le type est
en accord avec les codes de formats correspondants.

13. Problmes de synchronisation entre lcran et le clavier


Voyez cet exemple de programme accompagn de son excution alors que nous avons rpondu :
12^25@
# include <stdio.h>
int main ()
{
int n, p;
printf ("Donnez une valeur pour n : ");
scanf ("%d", &n);
printf ("Merci pour %d\
%d\n", n);
printf ("Donnez une valeur pour p : ");
scanf ("%d", &p);
printf ("Merci pour %d", p);
return 0;
}

Vous constatez que la seconde question (Donnez une valeur pour p) est apparue lcran, mais le
programme na pas attendu que vous frappiez votre rponse pour vous afficher la suite. Vous notez
alors quil a bien pris pour p la seconde valeur entre au pralable, savoir 25. En fait, comme nous
lavons vu, les informations tapes au clavier ne sont pas traites instantanment
par scanf() mais mmorises dans un tampon. Jusquici, cependant, nous navions pas prcis
quand
scanf() sarrtait de mmoriser pour commencer traiter .

Dr. Eugne C. EZIN.

45

Donnez une valeur pour n : 12 25


Merci pour 12
Donnez une valeur pour p : Merci pour 25
Il le fait tout naturellement la rencontre dun caractre de fin de ligne gnr par la frappe de la
touche return , dont le rle est ici, classiquement, celui dune validation. (Notez que, bien quil joue
le rle dune validation, ce caractre de fin de ligne est quand mme recopi dans le tampon; il
pourra
donc ventuellement tre lu en tant que tel.) Llment nouveau rside dans le fait que scanf() reoit
une information dcoupe en lignes. Tant que son traitement nest pas termin, elle attend une
nouvelle ligne. Par contre, lorsque son traitement est termin, sil existe une partie de ligne non
encore utilise, celle-ci est conserve pour une prochaine lecture. Autrement dit, le tampon nest pas
vid chaque nouvel appel de scanf(). Cest ce qui explique le comportement du programme
prcdent.

En cas derreur
Dans le cas de printf(), la source unique derreur rsidait dans les fautes de programmation. Dans le
cas
de scanf, par contre, il peut sagir, non seulement de fautes de programmation mais galement dune
mauvaise rponse de lutilisateur.
Erreurs de programmation
Comme dans le cas de scanf(), ces erreurs peuvent tre de deux types :


Un code de format en dsaccord avec le type de lexpression. Si le code de format, bien


querron, correspond un type de longueur gale celle de la lvalue mentionne dans la
liste, les consquences se limitent, l encore, lintroduction dune mauvaise valeur. Si, par
contre, la lvalue a une taille infrieure celle correspondant au type mentionn dans le code
de format, il y aura crasement dun emplacement mmoire conscutif cette lvalue. Les
consquences sont difficilement prvisibles.

Un nombre de codes de formats diffrent du nombre dlments de la liste Comme dans le


cas de scanf(), il faut savoir que scanf() cherche toujours satisfaire le contenu du format.
Les consquences sont limites dans le cas o le format comporte moins de codes que la
liste. Ainsi, dans cette instruction, on ne cherchera lire que la valeur pour n :
scanf ("%d", &n, &p);

En revanche, dans le cas o le format comporte plus de codes que la liste, on ira crire des valeurs
des emplacements (presque) alatoires de la mmoire. L encore, les consquences en seront
pratiquement imprvisibles.

Remarque
Il existe une erreur de programmation assez frquente et trs particulire, lie la lecture dun
caractre. Pour bien comprendre de quoi il sagit, considrez le code de lexemple suivant qui

Dr. Eugne C. EZIN.

46

demande lutilisateur de choisir une opration parmi laddition ou la multiplication, puis de fournir
deux nombres entiers. On affiche alors le rsultat correspondant :
#include <stdio.h>
int main ()
/* . . . . . . . . . . . . . . . . . . . . . . . */
{
char op;
int n1, n2;
printf ("Opration souhait (+ ou *) ? ");
scanf ("%c",
("%c", &op);
printf ("Donnez 2 nombres entiers : ");
scanf ("%d %d", &n1, &n2);
if (op == '+')
printf ("Leur somme est : %d ", n1 + n2);
else
printf ("Leur produit est : %d ", n1 * n2);
return 0;
}

Lerreur ne pas commettre serait dinverser lordre des deux instructions de lecture en crivant :
scanf ("%d %d", &n1, &n2);
. . .
scanf ("%c", &op);

Une difficult apparatrait : le caractre lu par le second appel de scanf() serait toujours diffrent de +
ou de *. Il sagirait toujours, dans ce cas, du caractre de fin de ligne '\n' (fourni pour la validation de
la rponse prcdente) toujours contenu dans le tampon. En effet, la plupart du temps, le tampon
nest pas vide et contient un symbole qui peut tre lu comme un caractre. Ainsi, vous naurez jamais
loccasion de taper votre caractre, lordinateur se sera dj servi !
Pour rgler ce problme, il existe en fait trois solutions :


la premire, cest de faire attention lordre de lectures des donnes, surtout quand il sagit
de caractres (voir lexemple ci-dessus);

la deuxime, pas trs esthtique, consiste lire un caractre supplmentaire;

a troisime, utilise une fonction prdfinie en C (dans stdio.h), la fonction fflush (stdin) (stdin

pour standard input, cest--dire le clavier) qui permet de vider le tampon :


scanf ("%d %d", &n1, &n2);
. . .
fflush (stdin);
scanf ("%c", &op);

Dr. Eugne C. EZIN.

47

Mauvaise rponse de lutilisateur


Nous avons dj vu ce qui se passait lorsque lutilisateur fournissait trop ou trop peu dinformation par
rapport ce quattendait scanf(). De mme, nous avons vu comment, en cas de rencontre dun
caractre invalide, il y avait arrt prmatur. Dans ce cas, il faut bien voir que ce caractre non
exploit reste dans le tampon pour une prochaine fois . Cela peut conduire des situations assez
fcheuses telles que celle prsente dans cet exemple (limpression de ^C reprsente, dans
lenvironnement utilis, une interruption du programme par lutilisateur; par exemple, sous DOS, vous
pouvez taper sur les touches Ctrl et c en mme temps pour interrompre lexcution de votre
programme) :
#include <stdio.h>
int main ()
{
int n;
do
{ printf ("Donnez un nombre : ");
scanf ("%d", &n);
printf ("Voici son carr : %d\
%d\n", n * n);
}
while (n) ;
return 0;
}

Donnez un nombre : 12@


Voici son carr : 144
Donnez un nombre : &@
Voici son carr : 144
Donnez un nombre : Voici son carr : 144
Donnez un nombre : Voici son carr : 144
Donnez un nombre : Voici son carr : 144
Donnez un nombre : Voici son carr : 144
Le programme est entr dans une boucle infinie sur un caractre invalide ! En effet, au premier appel
de scanf(), lusager a dabord entr le nombre 12 suivi dune fin de ligne. scanf() a donc lu le nombre
12 et a dplac le pointeur du tampon sur le caractre de fin de ligne qui suit 12. Au deuxime appel
de scanf(), lusager a entr le caractre & et une fin de ligne. scanf() a alors saut le caractre
courant fin de ligne (puisquil sagit dun sparateur et que le code de format est %d), a rencontr le
caractre illgal & et sest interrompue. Ensuite, linstruction suivante a t excute, la conditions de
la boucle a t value vrai et le bloc de la boucle est excut de nouveau. Au nouvel appel de
scanf(), le pointeur du tampon pointe toujours sur &, un caractre illgal.

Dr. Eugne C. EZIN.

48

14. Complment de lecture : la macro getchar()


Lexpression c = getchar(); joue le mme le rle que scanf ("%c", c); tout en tant plus rapide
puisquelle fait pas appel au mcanisme danalyse dun format. Notez que getchar utilise le mme
tampon (image dune ligne) que scanf(). En toute rigueur, getchar() est une macro (comme putchar)
dont les instructions figurent dans stdio.h. L encore, lomission dune instruction #include approprie
conduit une erreur ldition de liens.

15. Complment de lecture : validit des donnes


Les donnes fournies par lutilisateur doivent appartenir au domaine de valeurs des variables
dentre, cest--dire faire partie du type qui a t dclar et correspondre au problme rsolu par
lalgorithme. Pour illustrer ceci, nous vous proposons lexemple suivant :
Rsoudre lquation ax + b = 0 (a et b sont des rels et b > 0)

Analyse
On connat a et b; b est suppos > 0. Si a = 0, alors lquation na pas de racine, sinon la
racine est la valeur de x, cest--dire -b / a.
Lexcution des instructions par la machine va dpendre des valeurs de a et de b fournies par
lutilisateur (a et b sont donc des variables dentres). Il faut donc prvoir dans lalgorithme tous les
cas qui peuvent se prsenter. Lalgorithme va apparatre donc comme une manire de prvoir, par le
biais de structures conditionnelles, toutes les suites dinstructions susceptibles dtre excutes par la
machine. Chacune de ces suites est une excution (ou droulement ou encore ralisation)
particulire de lalgorithme. Lassimilation dun algorithme une application oblige prciser lespace
de dpart de lapplication, cest--dire lensemble des valeurs des variables dentres, et ainsi
sassurer que les valeurs fournies par lutilisateur appartiennent bien cet ensemble. Nous vous
prsentons, dans la figure 7.9.4, deux versions dun algorithme suppos donner la recette pour
solutionner le problme susmentionn. Ainsi, la boucle do... while permet de prvenir lutilisateur de
son erreur et de le faire rpter tant quil na pas respect la consigne affiche sur son cran. Le do...
while est utilis la place du while car, dans notre cas, il nous faut faire au moins une lecture de a et
b. Nous

recommandons de valider ainsi les donnes dans les

diffrents exercices et travaux

pratiques.

16. Les assertions


Nous avons dj parl de limportance des commentaires dans les algorithmes et programmes.
Notamment, nous avons indiqu quun des types des commentaires, les assertions, est une
hypothse que le concepteur de lalgorithme faisait, et que tout ce qui suit est bas sur la vracit de
cette hypothse. Nous avons galement dit que la mthode des assertions est une mthode de
vrification de programmes. En effet, lorsquun programme est crit, il faut prouver quil fournit bien la
solution au problme pos, et ceci en un nombre fini dtapes. Une premire vrification consiste
souvent en quelques essais : on fournit des donnes SOIGNEUSEMENT CHOISIES pour lesquelles

Dr. Eugne C. EZIN.

49

on connat le rsultat ou la nature des rsultats (type et domaine de validit; par exemple, si cest un
pourcentage que le programme doit fournir comme rponse, nous devons nous attendre ce que ce
soit un rel compris entre 0 et 100). On excute le programme la main (on fait une trace du
programme ou de lalgorithme) ou on le fait excuter lordinateur. Si le rsultat nest pas celui
attendu, on a prouv que le programme (algorithme) est incorrect. Sinon, on na rien prouv. Cest ce
que nous vous demanderons de faire pour vrifier vos programmes dans le cadre de notre cours.
Ainsi, la mthode des assertions est une des mthodes qui peuvent tre qualifies de formelles et
que nous pouvons utiliser pour nous assurer quun programme est correct. Sa description dpasse
largement la porte de notre cours, et elle y a t introduite uniquement en tant que type particulier
de commentaire. Par contre, elle sera utilise dans certains cas comme des indications du
concepteur de lalgorithme lintention du programmeur pour que ce dernier ajoute des instructions,
dans le langage de programmation utilis, visant vrifier les hypothses formules par lassertion.
Dans la deuxime version de lexemple prcdent, nous avons signal par une assertion, le fait que
tout ce qui suit est bas sur la condition que b est > 0. Le programmeur doit alors faire, cet endroit,
une validation de donnes pour sassurer que cette hypothse est vraie et garantir que lexcution du
programme respecte lassertion.

17. Filtrage des donnes


Nous avons vu la section prcdente comment liminer des valeurs situes en dehors du domaine
de validit des variables dentres. Nous allons voir maintenant comment liminer les erreurs dues
des fautes de frappe par exemple, la frappe par lutilisateur du caractre 'O' la place du chiffre 0.
Ces erreurs de lutilisateur risquent fort de provoquer, si rien nest prvu, une erreur dexcution du
programme. Une manire de rsoudre le problme sus mentionn est dutiliser une des
caractristique de la fonction scanf(). Avant de dcrire cette mthode, il faut souligner quil existe une
autre faon de rsoudre ce problme, faon qui consiste dfinir pour toute variable dentre une
chane de caractres. Ainsi tout caractre tap au clavier sera compatible avec une variable de type
chane. Ensuite, on vrifie que les caractres contenus dans la chane sont compatibles avec la
donne lire. Il suffit aprs cela de convertir cette chane en une valeur du type de la donne
dentre et de vrifier si la valeur est dans le domaine de validit. Nous y reviendrons plus tard.

Vrification des types de donnes saisie avec la mthode scanf().


Nous avons vu en pseudo-code quaprs chaque instruction Demander, on doit crire une assertion
pour valider les donnes que lusager entre au clavier. Par exemple, si on dsire que lusager entre
un
nombre entier > 5, on crivait ceci :
Demander n
{A : n est un entier > 5}

Nous savons dj que pour valider le fait que lusager entre un nombre > 5, il suffit de traduire
lassertion comme suit :

Dr. Eugne C. EZIN.

50

int n;
do
{
printf(" Veuillez entrer n, un entier plus
plus grand que 5 ");
scanf("%d", &n);
}while (n <= 5);

Maintenant, il nous reste nous assurer que lusager entre bel et bien un nombre entier (et non pas
une lettre de lalphabet, par exemple). Pour ce faire, on doit se rappeler que scanf() nous renvoie
toujours le nombre daffectations quelle a pu effectuer (autrement dit, le nombre de donnes quelle a
pu rcuprer partir de ce quelle a trouv dans le tampon dentre). Ainsi, dans lexemple
prcdent, si lusager entre bel et bien un nombre entier, scanf() va retourner 1. Sinon (si lusager
entre un mot, par exemple), elle va retourner 0 (ce qui veut dire quelle na pas pu rcuprer aucune
donne). On doit donc rcuprer la valeur de retour de scanf() et sassurer quelle a bien rcupr le
nombre de donnes auquel on sattend quelle rcupre. Dans notre exemple, il suffit de faire ceci :
int n;
int nbAff;
do
{
printf(" Veuillez entrer n, un entier plus grand que 5 ");
fflush (stdin);
nbAff = scanf( "%d", &n);
}while ((n <= 5) || (nbAff < 1));

Linstruction fflush(stdin) permet de librer le contenu du tampon (buffer) dentre. Ceci sera utile au
cas o une erreur de saisie se produira : lorsque lexcution de la boucle reprendra, la donne
indsirable, qui a fait que scanf() avait prcdemment avort, sera efface du tampon dentre. Si
on avait 2 donnes rcuprer, cela veut dire que lon sattend ce que scanf() retourne 2 si lusager
entre les donnes correctement. On aurait alors :
float toto;
float tata;
int nbAff;
do
{
printf("Veuillez entrer
entrer 2 nombres rels positifs ou nuls: ");
fflush(stdin);
nbAff = scanf(" %f %f ", &toto, &tata);
}while((toto < 0.0f) || (tata < 0.0f) || (nbAff < 2));

Dr. Eugne C. EZIN.

51

Conclusion

Dr. Eugne C. EZIN.

52

Les tableaux, les pointeurs et les


structures
Introduction
Lide dun vecteur est simple. Supposons que nous voulons crire un programme pour le calcul de la
moyenne dans un cours denseignement. Imaginer crer une variable pour chaque Etudiant ou Elve
est une tche ardue et mme pouvant conduire une confusion parfois incontrlable. Il suffit de sen
rendre compte dans le cas dune universit. Une solution a cette approche est lutilisation des
vecteurs. Un vecteur est une collection dobjets de mme structure, disposs les uns la suite des
autres en mmoire auxquels on accde au moyen de dun identificateur et dun ou des indices. Dans
ce chapitre, nous traiterons des vecteurs monodimensionnels et des vecteurs bidimensionnels ou
simplement des matrices. Le cas des vecteurs en dimension suprieur peut se gnraliser aisment.

1. Vecteur monodimensionnel
Un vecteur monodimensionnel peut tre vu comme une application
n

T = T x T x .. x T

(T, n)

o T reprsente le type, et n la dimension. En dautres termes, un vecteur monodimensionnels


est compltement au moyen dun identificateur et dun indice.

Lindice commence toujours par 0.

nous comprendrons la raison par la suite avec les pointeurs. Pour un vecteur monodimensionnel,
tous les lments ont le mme type. Ces lments sont disposs les uns la suite des autres de
faon contigu en mmoire. Pour dclarer un vecteur monodimensionnel, on utilise la syntaxe
suivante :
type nom_vecteur[dimension] ;
o type est lun des types de bases dj rencontrs. Il est possible aussi de dfinir dautres
types (Type de donnes abstrait ou Abstract Data Type en Anglais). Nous le verrons plus loin. Ce
cettte syntaxe, il ressort de ces observations, que [] est un oprateur. Lors de la dclaration dun
vecteur, la dimension doit tre prcise.
Dans la dclaration char p[5] ; on dfinit ainsi un vecteur de 5 caractres dont les lments
sont : p[0], p[1], p[2], p[3], p[4]. Dans la dclaration char p[5] ; le compilateur rserve 5 octets pour
le vecteur p.
Comme nous lavions soulign plus haut, les indices partent de 0. Voil un de des dfauts du
langage C. Par consquent le contrle doit tre sous la responsabilit du programmeur.

Dr. Eugne C. EZIN.

53

2. Les pointeurs
Un pointeur et une variable qui permet la manipulation des adresses. Puisque les lments
dun vecteur sont mmoriss de faon contigu, on peut parcourir ces lments partir de ladresse
du premier. Pour dclarer un pointeur, on utilise la syntaxe suivante :
type * Nom_pointeur ;
o type est le type de base du vecteur, et Nom_pointeur est le nom du pointeur. Il faut remarquer la
prsence de loprateur unaire *. On parle aussi doprateur monadique. Des lectures correctes de la
dclaration prcdente sont les suivantes:


Nom_pointeur est un pointeur un type

Nom_pointeur est de type type *.

*Nom_pointeur est de type type.

Dans lexemple int *p ; p est un pointeur un entier.


Un pointeur doit tre initialis avant dtre utilis correctement. Pour clarifier ce concept trs
important de C, considrons lexemple suivant :
int sample[10] ;
int * p ;
p = &sample[0] ; /* ou encore p = sample */
Le pointeur p est initialis pour pointer ladresse du premier lment du vecteur sample. On note
dailleurs une quivalence entre le nom du vecteur (ici sample) et ladresse du premier lment (ici p).
Voil pourquoi le nom dun vecteur est un pointeur constant. Cette notion est trs importante en
C, C++ et Java.
En rsum, on cr un pointeur au premier lment dun vecteur en utilisant le nom de ce
vecteur. On verra dautres dtails sur les pointeurs dans la suite de ce module.

3. Vecteur bidimensionnel
Un vecteur bidimensionnel est un vecteur de vecteurs monodimensionnels. En dautres
termes, il sagit dune matrice. Pour dclarer un vecteur bidimensionnel, la syntaxe est la suivante :
int vect[nombre_lignes][nombre_colonnes] ;
o nombre_lignes reprsente le nombre de lignes tandis que nombre_colonnes reprsente le nombre
de colonnes. Les indices dans ce cas aussi partent de 0. Considrons la matrice suivante :

10

11

12

Ecrivons un programme pouvant afficher cette matrice.


#include<stdio.h>

Dr. Eugne C. EZIN.

54

int main(void){
int i, j, mat[3][4] ;

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


for(j=0 ;j<4 ;j++)
num[i][j] =(i*4)+j+1 ;

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


for(j=0 ;j<4 ;j++)
printf("%3d",num[i][j]) ;
printf("\
printf("\n") ;
}
return 0 ;
}

Voyons maintenant comment les lments sont rangs en mmoire. Nous avions dj dit
dans le cas des vecteurs monodimensionnels, que les lments sont rangs de faon contige et ce
principe reste toujours valable. La convention adopte par les compilateurs C est la suivante : lindice
dcrivant la ligne varie moins vite que lindice celui dcrivant la colonne. Une gnralisation de cette
convention est immdiate. Dans le cas dun vecteur bidimensionnel o nous avons une dclaration
de la forme int mat[3][4] ; les lments de la matrice sont reprsents en mmoire dans lordre
suivant :

mat[0][0]

mat[0][1]

mat[0][2]

mat[1][0]

mat[1][1]

mat[1][2]

mat[2][0]

mat[2][1]

mat[2][2]

mat[3][0]

mat[3][1]

mat[3][2].

Exercice : quelle est la mmoire requise pour mmoriser ces lments de la matrice mat?
12 x sizeof(int)

En gnral, pour mmoriser les lments dun vecteur bidimensionnel dont la dclaration est type
num[nLignes][nCols] ; on a besoin de nLlignes x nCols x sizeof(type).

4. Chanes de caractres
Une chane de caractres en C est un vecteur de caractres dont le dernier lment est le caractre
nul (\0) appel le dlimiteur. De cette dfinition, il ressort quil faut tenir compte de ce caractre pour
attribuer la taille une chane de caractres. Pour dclarer une chane devant contenir le groupe de
mots "salut les amis" par exemple, on crira :
char chaine[15] ;

Dr. Eugne C. EZIN.

55

Une reprsentation de cette chane en mmoire serait


s

\0

En C, il existe une gamme varie de fonctions de la librairie standard pour la


manipulation des chanes de caractres. En voici quelques unes.

strcpy(str1,str2) permet de copier la chane str2 en str1. Cela suppose que


lespace de str1 est suffisant pour contenir str2.

strcat(str1,str2) permet de concatner str2 la fin de str1.

strlen(str) permet de connatre la longueur de la chane str.

strcmp(str1,str2) permet de comparer deux chanes de caractres.

strstr(s1,s2) restitue un pointeur la premire occurrence de s2 dans s1.

strchr(s1,ch) restitue un pointeur la premire occurrence du caractre ch


dans la chane s1.

Lexemple suivant permet dillustrer lutilisation de quelques une de ces fonctions.

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

int main(void){
char s1[80]
s1[80] , s2[40];
printf("Donner une premiere chaine de caractres :") ;
gets(s1) ;
printf("Donne rune deuxieme chaine de caractres :") ;
gets(s2) ;
printf("les

longueurs

de

s1

et

s2

sont

respectivement :

%d

et

%d",strlen(s1),strlen(s2)) ;

if( !strcmp(s1,s2))
!strcmp(s1,s2))
printf("les chaines sont gales :") ;
strcat(s1,s2) ;
printf("La concatenation donne : %s",s1) ;

strcpy(s1, "Chers Etudiants de DESS") ;


printf("La copie donne : %s", s1) ;

if (strchr("Bonjour",j))

Dr. Eugne C. EZIN.

56

printf("la lettre j se trouve dans Bonjour")


Bonjour") ;

if(strstr("Salut tous","tou"))
printf("le mot tou sy trouve ") ;

return 0 ;
}

4.1. Vecteur de chanes de caractres


Pour crer un vecteur de chanes de caractres, on utilise un vecteur de caractres bidimensionnel.
La dimension de lindice des lignes dtermine le nombre de chanes et la dimension de lindice des
colonnes dtermine la longueur maximale de chaque chane. Dans la dclaration char chaine[30][50]
par exemple, on dfinit ainsi 30 chanes de caractres ayant chacune au maximum 49 caractres
cause du terminateur nul.
La troisime chane de caractres contenue dans chaine peut tre obtenue au moyen de
linstruction gets(chaine[2]) ; ou encore gets(&chaine[2][0]) ;

4.2. Initialisation des vecteurs


En C, il est parfois utile dinitialiser un vecteur lors de sa dclaration. Linstruction suivante

int

vect[10] = {3,5,6,7,8,7,6,5,6,4} ; permet dinitialiser un vecteur de 10 composantes. Ainsi on vect[0]


=3, vect[1]=5 etc. Au cas o la liste des lments ne fait pas la dimension du vecteur, les autres
composantes sont initialises 0.
La dclaration char str[14]="Le C est beau" ; est quivalente : str[0] =L, str[1]=e , str[2]=
, str[13] =\0 ; On pourrait donc crire aussi
str[14] = {L, e, , C, , e, s, t, , b, e, a, u} ;

Voyons aussi un exemple dans le cas des vecteurs bidimensionnels.


int carre[5][2]{
1,1,
2,4,
3,9,
4,16,
5,25
};
ou

int carre[5][2]{

Dr. Eugne C. EZIN.

57

{1,1},
{2,4},
{3,9},
{4,16},
{5,25}
};

4.3. Initialisation dun vecteur sans dimension


Il est nest pas toujours commode de compter les lments dun vecteur avant de dfinir sa
dimension lors de sa dclaration. Cest fastidieux. Il suffit de considrer le cas des chanes pour sen
rendre compte.
On peut laisser le soin au compilateur de calculer automatiquement cette dimension pour
quil cr lespace ncessaire en mmoire pour les lments de ce vecteur. Voyons un exemple
pratique.
char iutIG[] = "Nous sommes des etudiants de Informatique de Gestion";
printf("la longueur de la chaine est %d", sizeof(iutIG)) ;
Ce deuxime exemple comme on peut le constater offre la possibilit aux programmeurs dajouter
dautres donnes sans se proccuper de la taille de la ligne.
int carre[][2]{
{1,1},
{2,4},
{3,9},
{4,16},
{5,25},
{20,400}
};

5. Variable pointeur
Un pointeur est une variable qui contient une adresse de mmoire. Cette adresse correspond la
position dun autre objet qui est normalement une autre variable. La syntaxe pour la dclaration dun
pointeur est :
type * variable ;
Il existe deux oprateurs unaires pour les pointeurs : * et &.

* se lit ladresse de
& se lit adresse de
Voici quelques exemples pour la lecture des expressions faisant usage de ces oprateurs.
m = &count

se lit

Dr. Eugne C. EZIN.

m reoit ladresse mmoire de count.

58

q = *m

se lit

q reoit la valeur qui se trouve ladresse de m.

Il faut bien faire attention pour que la variable pointeur pointe toujours au type correct. Voil
une raison pour laquelle on dit que le C est un langage fortement typ. Lexemple suivant contient un
bug qui peut tre facilement identifi.
#include<stdio.h>
int main(void){
double x = 10.5, y ;
int * p ;
p = &x ; /* elle est errone cause du type */
y=*p;
printf(" la valeur de y est %f", y) ; /* naffiche pas 10.5 ! ! ! ! */

return 0 ;
}

5.1. Indexation des pointeurs


En C un pointeur et un vecteur sont troitement lis. Le nom dun vecteur sans lindice est le pointeur
au premier lment du vecteur. Nous avions dej soulign cet aspect au dbut de ce module.
Comme illustration, dans la dclaration char p[10] ; on a lquivalence p == &p[0] ;
Le nom dun vecteur sans lindice engendre un pointeur. Rciproquement un pointeur peut
tre index comme sil est dclar au moyen dun vecteur. Considrons lexemple suivant :
int main(void)
{
int *p, i[10] ;
p =i ;
p[5] = 100 ; /* affectation */
*(p+5) = 100 ; /* arithmtique des pointeurs */
return 0 ;
}
Dans le cas des vecteurs bidimensionnels, on a lquivalence pour chaque lment :
a[j][k] == *((type de base *)a +(j*longueur de la ligne) +k );
Soit la dclaration suivante : int a[10][20] ;
a[0][4] est quivalente : *((int *)a + 0x10 +4).

5.2. Arithmtique des pointeurs


Deux oprations sont admises pour larithmtiques des pointeurs : laddition et la soustraction. Et l
encore le sens est trs particulier. Un pointeur est avant toute chose une adresse et on ne peut
donner un sens ce que signifierait la somme ou le produit de deux adresses par exemple.

Dr. Eugne C. EZIN.

59

int *p = 2000 ;
p++ ;
Le pointeur p pointe ladresse 2002 et non ladresse 2001 car un entier occupe deux
octets en gnral.

Pointeur
p

Valeur

Adresse

2000

2002

12

2004

56

2006

Larithmtique des pointeurs tient compte de la taille du type de base.


En rgle gnrale, chaque fois que lon incrmente un pointeur, il pointera la localisation de
mmoire de llment successif en considrant le type de base.

5.3. Pointeur des pointeurs


Considrons le schma illustratif suivant qui fait une comparaison entre un pointeur et un
pointeur.
Pointeur
Variable
Adresse

valeur

Pointeur

Pointeur

Variable

Adresse

Adresse

valeur

Considrons la dclaration :
int * *ptr ;
La variable ptr est un pointeur pointeur de type entier. Pour accder la valeur de
destination, il faut appliquer deux fois loprateur unaire *.

Exemple :

int main(void){
int x, *p, **q ;
x = 10 ;
p = &x ;
q = &p ;
printf("La valeur est %d",**q) ; /* evidemment 10 */
return 0 ;
}

Dr. Eugne C. EZIN.

60

5.4. Pointeur NULL


Aprs la dclaration dun pointeur local et avant de lui affecter une adresse, ce pointeur contient une
adresse inconnue tandis que les pointeurs globaux sont automatiquement initialiss NULL. Lorsque
lon utilise le pointeur NULL gauche dune affectation, on court le risque de bloquer le programme
ou pire le systme dexploitation.

6. Les structures
Une structure est forme dune srie de variables laquelle on fait rfrence laide dun nom
unique. Les variables qui composent une structure sont appeles membres, lments ou champs.
Les structures permettent de dfinir de nouveaux types que le programmeur manipulera plus
facilement.
Exemple : Voyons comment on dfinit une structure travers lexemple suivant.
struct Adresse{
char name[30] ;
char rue[40] ;
char ville[20] ;
char pays[10] ;
unsigned long int code ;
};
Ainsi faisant, struct Adresse devient un type de donnes abstrait. Il faut noter la prsence du pointvirgule ( ;) car la dclaration dune structure est une instruction en langage C.
Pour dclarer une variable de type struct adresse, on crit :
struct Adresse adr_info ;
Le compilateur alloue lespace suffisant pour les donnes relatives adr_info.
Ainsi la taille mmoire requise pour adr_info est (30 + 40 + 20 +10 +4) octets. On peut utiliser
loprateur sizeof pour vrifier la taille de lespace mmoire requis.
Il est possible la fois de dfinir et dclarer une structure. On utilise la syntaxe suivante :
struct Adresse{
char name[30] ;
char rue[40] ;
char ville[20] ;
char pays[10] ;
unsigned long int code ;

} adr1, adr2, adr3 ;

ou encore

struct Adresse{
char name[30] ;

Dr. Eugne C. EZIN.

61

char rue[40] ;
char ville[20] ;
char pays[10] ;
unsigned long int code ;
};
typedef struct Adresse Adresse;
Adresse adr1, adr2, adr3;
Le mot cl typedef permet de dfinir (et non de crer) un nouveau type de donnes partir
dun autre existant. La syntaxe est la suivante :
typedef type nouveauType ;
Dans lexemple typedef float balance ;
float a ; et balance a ; dsignent deux dclarations identiques de mme effet.
En rsum, la dclaration typedef A B ; indique au compilateur de considrer B comme un
type synonyme de A.

6.1. Accs aux membres dune structure


Il existe deux oprateurs qui permettent laccs aux membres dune structure : il sagit de loprateur .
et de loprateur (flche).


Pour affecter la valeur numrique 20054 par exemple au champ code, on crira :
adr1.code = 20054 ;
printf("Le code de la ville est : %d",adr1.code) ;

Parfois il est bon de passer par un pointeur une structure pour affecter une valeur une
variable de type structure. Cela comporte videmment un avantage assez important pour la
dure de vie du contenu dune variable durant lexcution dun programme.
Adresse *ptr ;
ptr = &adr1 ;
ptrcode = 20054 ;
printf("Le code de la ville est : %d", ptr code) ;

Il faut noter que loprateur binaire deux oprandes dont lun est un pointeur et le second
est un champ dans le cas des structures.

6.2. Affectation une structure


Les informations contenues dans une structure peuvent tre affectes une autre structure du mme
type.
#include<stdio.h>
int main(void){

Dr. Eugne C. EZIN.

62

struct{
int
int a ;
int b ;
int c ;
} x,y ;

x.a = 10 ;
y=x ; /* affectation une structure */
printf("%d",y.a) ; /* affiche 10 */
return 0 ;
}

6.3. Vecteur de structures


Pour dclarer un vecteur de structures, il suffit dabord de dfinir une structure et ensuite dclarer une
variable comme un vecteur de tel type. Pour dclarer 100 structures de type adresse par exemple, la
syntaxe est de la forme suivante :
struct Adresse adresInfo[100] ;
Cette dclaration cr 100 groupes de variables organises de la faon comme dfinie dans
adresse. Par exemple, la dclaration
printf("%d",adresInfo[2].code) ;
affiche le code de la structure adresInfo[2]. Les indices dans ce cas aussi partent de zro.

Conclusion
Nous avions dans ce chapitre expos des notions essentielles pour la manipulation de plusieurs objets de mme
nature (cest le cas des tableaux) et de plusieurs objets de natures diffrentes (cest le cas des structures). Les
pointeurs constituent des outils assez puissants pour la manipulation des variables au moyen de leurs adresses.

Dr. Eugne C. EZIN.

63

Les fonctions
Introduction
Les fonctions constituent un lment trs important de la programmation modulaire. On parle aussi
de procdure en Pascal dans certains cas. Le langage C quant lui na pas de procdures mais
uniquement des fonctions. Le but de chapitre est de prsenter les syntaxes essentielles pour dfinir
une fonction et les diffrents mcanismes dappel de fonction en C.

1. Dfinition et dclaration dune fonction


Une fonction est un bloc unique de code. Le code de la fonction devient ainsi priv et appartient
seulement cette fonction. Le code et les donnes dfinis lintrieur dune fonction ne peuvent
interagir avec le code et les donnes dfinis dans une autre fonction puisque ces deux fonctions ont
diverses aires de visibilit.


On parle de dfinition dune fonction lorsque lon crit le code de la tche que cette
fonction accomplit.

La dclaration dune fonction est encore le prototype de la fonction. Elle consiste


prciser le type restitu et les types des paramtres formels.

2. Appel par valeur


Cette mthode consiste copier la valeur dun argument dans le paramtre formel de la fonction.
Ainsi toute modification effectue sur le paramtre na aucun effet sur largument pass en
paramtre. Considrons lexemple suivant :
#include<stdio.h>
int carre(int) ;
int main(void){
int

t = 10 ;

printf("%d %d ", t , carre(t)) ;


return 0 ;
}

int carre(int x){


x = x*x ;
return x ;
}

Dr. Eugne C. EZIN.

64

La valeur 10 (argument de carre()) est copie dans le paramtre x.

3. Appel par adresse


Lappel par adresse consiste passer la fonction un pointeur un argument plutt que largument
lui-mme. Puisque ladresse de largument est pass la fonction, le code qui se trouve lintrieur
de la fonction peut modifier la valeur de largument qui se trouve lintrieur de la mme fonction.
Considrons le fameux exemple suivant :
#include<stdio.h>

void echange(int*, int*) ;

int main(void){
int i = 10 ;
int j= 20 ;
echange(&i, &j) ;
return 0 ;
}

void echange(int * p, int * q){


int temp ;
temp = *p ;
*p = *q ;
*q = temp ;
}

4. Vecteur comme paramtre dune fonction


Quand on utilise un vecteur comme argument dune fonction, seule ladresse de ce vecteur est pass
comme paramtre. Dans ce cas. Le code qui se trouve lintrieur de la fonction peut modifier le
contenu effectif du vecteur utilis pour rappeler la fonction.
#include<stdio.h>
#include<ctype.h>
void afficheMaj(char *) ;

int main(void){
char str[80] ;

Dr. Eugne C. EZIN.

65

gets(str) ; /* fgets(str,sizeof(str), stdin) ; */


afficheMaj(str) ;
printf("nest
printf("nest pas modifie : %s", str) ;
return 0 ;
}

void afficheMaj(char *str) {


register int t ;
for (t=0 ; str[t] ;++t)
putchar(toupper(str[t])) ;
}

5. Les arguments spciaux de main() : argc et argv


Nous avions dj rencontr plusieurs fois la fonction spciale main(). Elle accepte aussi des
arguments mais vraiment particuliers aussi.
Le paramtre argc est un entier qui vaut au moins 1 puisque le nom du programme est
considr comme un argument et il ny a pas de programme sans nom.
Le paramtre argv est un pointeur un vecteur de pointeurs caractres. Chaque lment
de ce vecteur pointe vers un argument de la ligne de commande.
Pour ceux qui sont familiers aux commandes du systme dexploitation UNIX, cest le moment de
faire lanalogie avec ces commandes et les messages derreurs qui saffichent.
Voyons un exemple pour illustrer tout cela.
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char *argv[]){


if (argc !=2){
printf("Tu nas pas entrer ton nom :") ;
exit(1) ;
}
printf("Salut
printf("Salut %s", argv[1]) ;
return 0 ;
}

Supposons que le nom du programme est prog.c. pour excuter ce programme sous UNIX
par exemple, il faut taper aprs compilation

Dr. Eugne C. EZIN.

66

./progEugene
pour voir safficher lcran, Salut Eugene.

6. Restitution dun pointeur


On sait quun pointeur est une adresse mmoire qui pointe vers un type de donnes dtermin. De
ce fait on peut exploiter judicieusement ladresse restitue par une fonction pour manipuler des
donnes.
Voyons lexemple suivant :
#include<stdio.h>

char * match(char
match(char , char *) ;

int main(void){
char str[80] ;
char *p, ch ;
gets(str) ;
ch = getchar() ;
p = match(ch,str) ;
if(*p)
printf("%s",str) ;
else
printf("Caractre absent") ;

return 0 ;
}

char * match(char c, char *s) {


while(c != *s && *s) s++ ;
return
return s ;
}

7. Fonction rcursive
Quand une fonction lintrieur du corps dune fonction sappelle elle-mme, une telle fonction est
dite rcursive. Quand une fonction rcursive sappelle, une nouvelle srie de variables locales est
cre chaque fois au dbut utilisant de telles variables. Un appel rcursif ne cr pas une nouvelle
copie de la fonction mais seulement les valeurs sur lesquelles elle opre.

Dr. Eugne C. EZIN.

67

Un excs dappels de fonctions rcursives peut provoquer le trop plein du STACK puisque la
mmorisation des variables locales et les paramtres formels de fonctions se fait sur le STACK. A
chaque nouvel appel, une nouvelle copie de ses variables se fait. il faut prvoir des instructions de
contrle dans la dfinition dune fonction rcursive.
/* version rcursive
rcursive de factoriel */
int factoriel (int

n){

int answer ;
if (n==1) return 1 ;
answer = factoriel(nfactoriel(n-1) * n ;
return answer ;
}

/* version non rcursive de factoriel */


int factoriel (int n){
int answer, t ;
answer = 1 ;
for (t=1 ;t<=n ;t++)
answer = answer * t ;
return answer ;
}

8. Vecteur monodimensionnel comme paramtre dune fonction


Nous avions vu que les appels de fonction en C se font par valeur ou par adresse. Lorsque le
paramtre est un vecteur, lappel se fait par adresse. En dautres termes, lappel dune fonction avec
un vecteur comme paramtre se fait laide dun pointeur au vecteur (cest dire le nom du vecteur
sans aucun indice). Considrons lexemple suivant qui illustre le concept.
int main(void){
int i[10] ;
func(i); /* lappel se fait par adresse */
return 0 ;
}

Voyons maintenant comment dfinir une fonction qui doit prendre comme paramtre formel,
un vecteur. Il existe trois faons pour dclarer un vecteur monodimensionnel comme paramtre
formel dune fonction :

Le paramtre formel peut tre un pointeur.

Dr. Eugne C. EZIN.

68

Le paramtre formel peut tre un vecteur de dimension connue.

Le paramtre formel peut tre un vecteur de dimension non dfinie.

Ces trois formes sont illustres dans les lignes suivantes :


void func(int
func(int * x){

void func(int

x[10]){

void func(int x[]){

Ces trois faons produisent des rsultats similaires. Chacune delle prcise au compilateur
quil recevra un pointeur un entier. En analysant ces trois formes, il ressort que la dimension dun
vecteur monodimensionnel nest pas indispensable lorsquil sagit de dclarer ce vecteur comme
paramtre formel dune fonction. Pour une explication sur ce rsultat important, on peut dire que le
compilateur produit un code qui prpare la fonction func() recevoir un point et non un vecteur de 10
lments.

9. Vecteur bidimensionnel comme paramtre dune fonction


Nous avions dit que dans le cas dun vecteur de dimension 1 comme paramtre formel dun
vecteur, il nest pas ncessaire de prciser la dimension. Dans le cas dun vecteur de dimension
2 , la situation est similaire mais avec des nuances. Lorsquun vecteur bidimensionnel est paramtre
formel, seul il est ncessaire de prciser le nombre de colonnes. En effet le compilateur doit
connatre avec prcision la longueur de chaque ligne pour accder correctement aux diffrents
lments du vecteur. Cela permet au compilateur de connatre le dbut dune autre ligne. Voyons
lexemple suivant qui permet de calculer la somme des lment dune matrice.
#define N_LIGNE 10
void

func(int mat[][20])

{
int som=0, i, j ;
for(i=0; i <N_LIGNE;i++)
for(j=0; i<20; j++)
som += mat[i][j];
printf(La somme est: %d,som) ;
}

Exercice : Un professeur intervient dans trois classes comportant 30 tudiants chacune. Ecrire un
programme qui mmorise les notes de chaque Etudiant. On pourra proposer trois fonctions dont la
premire a pour rle dentrer les donnes, la deuxime pour lire les donnes et la troisime pour
afficher les donnes lues.
#include<stdio.h>
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>

Dr. Eugne C. EZIN.

69

#define CLASSE 3
#define EFFECTIF 30

int eleve[CLASSE][EFFECTIF] ;

void entreNote(void) ;

int lireNote(int num) ;

void afficheNote(int g[][EFFECTIF]) ;

int main(void){

char ch, str[80] ;


for(

) {

do{
printf("(E)ntrer les notes :\
:\n") ;
printf("(A)fficher les notes :\
:\n") ;
printf("(Q)uitter :\
:\n") ;
gets(str) ;
ch = toupper(*str) ;
}while(ch !=E && ch !=A && ch !=Q) ;

switch(ch){
case E :
entrerNote() ;
break ;
case A
A :
afficheNote() ;
break ;
case Q :
exit(0) ;
}
}

Dr. Eugne C. EZIN.

70

return 0 ;
}

void entreNote(void) {
int t, i

for(t=0 ;t<CLASSE<t++)
for(i=0 ;i<EFFECTIF ;t++)
eleve[t][i] = lireNote(i);
}

int lireNote(int num) {


char s[8] ;
printf("Entrer la note de letudiant numero %d:\
%d:\n", num+1) ;
gets(s) ;
return(atoi(s)) ;
}

void afficheNote(int g[][EFFECTIF]) {


int t, i

for(t=0 ;t<CLASSE<t++){
printf("Classe numero %d:\
%d:\n", t+1) ;
for(i=0 ;i<EFFECTIF ;t++)
printf("Etudiant numero %d a la note %d",
%d", eleve[t][i]);
}
}

10. Pointeurs aux fonctions : adresse dune fonction


Durant la compilation dune fonction, le code source est transform en code objet et un point dentre
dans la fonction est ainsi dfini. En dautres termes, une fonction aussi a une adresse en mmoire et
on peut affecter cette adresse un pointeur.
Un appel la fonction durant lexcution du programme, fait rfrence (langage machine)
ce point dentre. Par consquent si un pointeur contient ladresse dentre dune fonction, il peut tre
utilis pour appeler cette fonction.
Pour connatre ladresse dune fonction, il suffit dutiliser le nom de la fonction sans paramtre
et sans parenthse. Considrons lexemple suivant :

Dr. Eugne C. EZIN.

71

#include<stdio.h>
void swap(int *, int *) ;

int main(void){
void *ptr ;
ptr = swap ;
printf("Ladresse de la fonction est %p",ptr) ;
return 0 ;
}

void swap(int * i, int * j){


int tmp ;
temp = * i ;
* i = * j ;
* j = tmp ;
}

Remarque : Il est prvu dans le compilateur, une partie qui soccupe de lvaluation des expressions.
On lappelle le parser.

Conclusion
Nous avons prsent dans ce cours des notions relatives pour une meilleure manipulation des fonctions qui
constituent un des points important pour la programmation modulaire. Quand on sait que la mthode
cartsienne en informatique consiste dcomposer les problmes complexes pour en arriver aux problmes
lmentaires que lon peut rsoudre aisment pour finalement en dduire une solution au problme initiale, on
se rend compte alors que la matrise de ce chapitre aussi est trs importante.

Dr. Eugne C. EZIN.

72

Les oprateurs dentre-sortie sur


fichier
Introduction
Nous avons dj eu loccasion dtudier les entres/sorties conversationnelles, cest--dire les fonctions
permettant dchanger des informations entre le programme et lutilisateur notamment les fonctions puts(),
gets(), putc(), getc(), scanf(),

printf(), etc. Nous tudierons ici les fonctions permettant dchanger des

informations avec des fichiers .

1. Dfinition
De faon gnral, le terme fichier dsigne plutt un ensemble dinformations situes sur une mmoire
de masse, telle quun disque, une disquette, etc. Mais, en langage C comme dans dautres langages,
tous les priphriques, quils soient darchivage (disques, disquettes, etc.) ou de communication
(clavier, cran, imprimante, etc.) peuvent tre considrs comme des fichiers. Cest dire donc que les
entres/sorties conversationnelles sur console rencontres jusquici apparatront comme un cas
particulier de la gestion de fichiers.

2. Fichiers binaires et fichiers de texte


En langage C, il existe des fonctions qui ralisent un transfert dinformation (entre mmoire et fichier)
que lon pourrait qualifier de brut , dans le sens o a se fait sans aucune transformation de
linformation. Les octets qui figurent dans le fichier sont des copies conformes de ceux qui
apparaissent en mmoire. Les fichiers concerns sont souvent appels
fichiers binaires.

3. Notion de flot et de fichier


En C, un fichier peut correspondre un disque, un terminal, une imprimante, etc. on associe un flot
un fichier dtermin excutant une opration douverture. Une fois que le flot est ouvert, il est
possible dchanger les informations entre les fichiers et le programme. Chaque flot auquel est
associ un fichier une structure propre de contrle de type FILE.
Un pointeur de fichier est un pointeur une structure de type FILE. La syntaxe est la suivante : FILE
*fp ;

Dr. Eugne C. EZIN.

73

La fonction fopen() ouvre un flot et fait connecter un fichier. Donc elle restitue le pointeur
associ un tel fichier. Le prototype de la fonction fopen() est :
FILE *fopen(const char *nomFichier, const char mode) ;
Pour sassurer de louverture effective dun flot, il est conseill dexploiter le pesudo-code suivant:
FILE * fp ;
if(fp = fopen("test", "w") == NULL){
printf("Impossible douvrir le fichier\n") ;
exit(1) ;
}

4. Flot de type binaire


Un flot binaire est compos dune suite doctets avec une correspondance une--une avec les octets
prsents sur le dispositif physique. Ce qui veut dire qaucune traduction de caractre nest faite. En
consquence, le nombre doctets crits (ou lus) correspond au nombre doctets prsents sur le
dispositif physique. Toutefois, il peut sajouter un nombre doctets nuls (dfinis dans limplmentation
du compilateur) pour aligner les informations afin de remplir par exemple un secteur de disque.

5. Flot de type texte


Un flot de type texte est form dune suites de caractres. Le C standard requiert quun flot de texte
soit organis en lignes termines par le caractre de fin de ligne\n. Il nexiste pas une relation un-un entre les caractres crits (ou lus) et les caractres prsents sur le dispositif physique. Ces
nombres sont en gnral diffrents.
Il est possible daccompagner ces transferts dinformations doprations de formatage
analogue celle que ralisent les fonctions printf() et scanf(). Les fichiers concerns par ces
oprations de formatage sont alors ce quon a coutume dappeler des fichiers de type texte ou encore
des fichiers de texte. Ce sont donc des fichiers que lon manipule avec un diteur quelconque, un
programme de traitement de texte quelconque ou, plus simplement, lister par des commandes
appropries du systme dexploitation (TYPE ou PRINT sous DOS, pr ou more sous UNIX, etc.).
Dans de tels fichiers, chaque octet reprsente un caractre. Gnralement, on y trouve des
caractres de fin de ligne (\n), de sorte que les caractres apparaissent comme une suite de lignes.
Les fonctions qui permettent de travailler avec des fichiers de texte ne sont rien dautre quune
gnralisation aux fichiers de celles que nous avons dj rencontres pour les entres/sorties
conversationnelles.
Les fonctions pour la manipulation de fichier de type texte
Voici une liste de quelques fonctions qui permettent la manipulation des fichiers de type texte.

fscanf (fichier, format, liste_dadresses)

fprintf (fichier, format, liste_dexpressions)

fgetc (fichier)

Dr. Eugne C. EZIN.

74

fputc (fichier)

La signification de leurs arguments, lexception de largument fichier (le nom de cet argument est
arbitrairement choisi), ainsi que de leur valeur de retour est la mme que pour les fonctions
conversationnelles correspondantes. Largument fichier est un pointeur de type FILE, un modle de
structure de donnes dfini dans le fichier stdio.h et correspondant aux fichiers. Voici deux
exemples dutilisation dun fichier de type texte.
Voici dabord un programme qui se contente denregistrer squentiellement, dans un fichier
quil va crer, une suite de nombres entiers quon lui fournira au clavier :
#include
#include <stdio.h>
int main (void)
{
char nomFich [21];
int n;
FILE * ofptr;
printf ("Donnez le nom du fichier crer > ");
scanf ("%s", nomFich);
ofptr = fopen (nomFich, "w");
do {
printf ("Donnez un nombre : ");
scanf ("%d", &n);
if (n) fprintf (ofptr, "%d
"%d\
%d\n", n);

}
while (n);
fclose (ofptr);
return 0;
}

Essayons danalyser le programme prcdent:

Nous avons dclar un tableau de caractres nomFich destin contenir le nom du fichier
que lon souhaite crer et que lon trouvera dans le rpertoire courant la fin de lexcution
du programme.

La dclaration FILE * ofptr; signifie donc que ofptr est un pointeur sur un objet de type FILE.
On emploie souvent le terme flux (en anglais stream ) pour dsigner un pointeur sur un
objet de type FILE. Dune manire gnrale, par souci de simplification, on utilise souvent le
mot fichier la place de flux ou flot.

La fonction fopen() est ce que lon nomme une fonction douverture de fichier. Elle possde
deux arguments que sont le nom du fichier concern, fourni sous forme dune chane de

Dr. Eugne C. EZIN.

75

caractres. Ce nom pourra comporter une information (chemin, rpertoire, etc.) permettant
de prciser lendroit o se trouvera le fichier aprs lexcution. Elle possde aussi

une

indication, fournie galement sous forme dune chane de caractres, prcisant le mode de
ce que lon souhaite faire avec ce fichier. Ici on trouve w (abrviation pour write) qui permet
de raliser une ouverture en criture .

Si le fichier cit nexiste pas, il sera cr par la fonction fopen(). Sil existe dj, son ancien
contenu deviendra inaccessible. Autrement dit, aprs lappel de cette fonction, on se retrouve
dans tous les cas en prsence dun fichier vide.

La fonction fopen() retourne une valeur nulle en cas dimpossibilit douverture du fichier. Ce
sera le cas, par exemple, si lon cherche ouvrir en lecture un fichier inexistant ou encore si
lon cherche crer un fichier sur une disquette sature, etc.

Le remplissage du fichier est ralis par la rptition de lappel de la fonction fprintf() avec un
format que lon pourra adapter suivant notre convenance (ici on crit dans le fichier un
nombre par ligne). Bien entendu, on peut enregistrer dans de tels fichiers des donnes de
type entier, de type rel, des caractres et des chanes de caractres.

Enfin, la fonction fclose() ralise ce que lon nomme une fermeture de fichier. Elle force
lcriture sur disque du tampon associ au fichier. En effet, chaque appel fprintf() provoque
un entassement dinformations dans le tampon associ au fichier. Ce nest que lorsque ce
dernier est plein quil est vid sur disque ou disquette. Dans ces conditions, on voit quaprs
le dernier appel de fprintf(), il est ncessaire de forcer le transfert des dernires informations
accumules dans le tampon, ce que ralise fclose().

Voyons maintenant un programme qui permet de lister sur lcran le contenu dun fichier quelconque
tel quil a pu tre cr par le programme prcdent :
#include <stdio.h>
int main (void)
{
char nomFich [21];
int n;
FILE * ifptr;
ifptr;
printf ("Donnez le nom du fichier lire > ");
scanf ("%s", nomFich);
entree = fopen (nomFich, "r");
fscanf (ifptr, "%d", &n);
while (! feof (ifptr )){
printf ("\
("\n%d", n);
fscanf (ifptr, "%d", &n);
}

Dr. Eugne C. EZIN.

76

fclose (ifptr);
return 0;
}

On trouve cette fois dans louverture du fichier, lindication r (abrviation de read). Elle prcise que le
fichier en question ne sera utilis quen lecture. Il est donc ncessaire quil existe dj. La lecture
dans le fichier se fait par un appel rptitif de la fonction fscanf() dont la condition darrt de la boucle
est feof(ifptr). Lorsque la fin de fichier est atteinte, la fonction fscanf()fournit la valeur EOF (constante
prdfinie dans <stdio.h> valant en gnral -1). La fin de fichier nest dtecte que lorsque lon
cherche lire un caractre alors quil ny en a plus de disponible, et non pas, ds que lon a lu le
dernier caractre. On se sert dans la pratique de la fonction feof(fichier) qui rend la valeur vrai (cest-dire 1) lorsque la fin du fichier est rencontre avec les mmes considrations que nous venons
dindiquer pour sassurer la fin dun fichier.

6. Modalit douverture de fichier


Il existe plusieurs modalits pour louverture des fichiers notamment :
Modalits

Signification

Ouvre un fichier de texte en lecture

Ouvre un fichier de texte en criture

Ouvre un fichier de texte pour lajout en fin de fichier

rb

Ouvre un fichier binaire pour la lecture

wb

Ouvre un fichier binaire pour lcriture

ab

Ouvre un fichier binaire pour lajout en fin de fichier

r+

Ouvre un fichier de texte pour la lecture et lcriture

w+

Ouvre un fichier de texte pour lcriture et la lecture

7. Flots prdfinis
Un certain nombre de fichiers sont connus du langage C, sans quil soit ncessaire ni de les ouvrir ni
de les fermer :
stdin : unit dentre (par dfaut, le clavier)
stdout : unit de sortie (par dfaut, lcran)
stderr : unit daffichage des messages derreurs (par dfaut, lcran)
stdprn : unit de sortie (par dfaut, limprimante).

8. Techniques de gestion de fichiers


On distingue deux types de gestion de fichiers : laccs squentiel et laccs direct.

Laccs squentiel consiste traiter les informations dans lordre dans lequel elles
apparaissent dans le fichier.

Dr. Eugne C. EZIN.

77

Laccs direct consiste se placer immdiatement sur linformation souhaite, sans avoir
parcourir celles qui le prcdent.

9. Quelques fonctions utiles pour les fichiers de type texte


Voici une liste non exhaustive de quelques fonctions utiles pour la manipulation des flots :
fopen()

fclose()

fseek()

ftell()

fprintf()

fscanf()
fputs()

feof()
ferror()

fflush()
rewind()

fputc()
remove()

fgets()
putc()

9.1. Prsentation de fputc() et de fgetc()


Pour crire des caractres deux fonctions sont essentielles : putc() et fputc() dont les prototypes sont
respectivement :
int putc(int ch) ;
int putc(int ch, FILE *fp) ;
Pour lire des caractres, on utilise deux fonctions : getc() et fgetc(). Leurs prototypes sont
respectivement :
int getc() ;
int fgetc(FILE *fp) ;

Voyons un exemple qui lit les caractres du clavier et les crit dans un fichier.
#include<stdio.h>
#include<stdlib.h>
int main(int arg, char *argv[]){

FILE *fp ;
char ch ;
if(argc !=2){
printf("Entrer le nom du fichier") ;
exit(1) ;
}

if(fp=fopen(argv[1], "w")==NULL){
printf("Impossible
printf("Impossible douvrir le fichier") ;
exit(1) ;
}

Dr. Eugne C. EZIN.

78

do{
ch = getchar() ;
putc(ch,fp) ;
} while(ch != $) ;

fclose(fp) ;
return 0 ;
}

Voici un autre exemple qui permet de dafficher le contenu du fichier.


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

int main(int arg, char *argv[]){

FILE *fp ;
char ch ;
if(argc !=2){
printf("Entrer le nom du fichier") ;
exit(1) ;
}

ch = getc(fp) ;
while(ch != EOF){
putchar(ch) ;
ch = getc(fp) ;
}

fclose(fp) ;
return 0 ;
}

10. Prsentation de feof()


La fonction feof() dtermine si la fin du fichier est atteinte. Son prototype est :
int feof(FILE *fp) ;

Dr. Eugne C. EZIN.

79

Linstruction suivante est un exemple.


while( !feof(fp)) ch = getc(fp) ;

Voyons un exemple dtaill pour illustrer cette fonction.


#include<stdio.h>
#include<stdlib.h>
int main(int
main(int arg, char *argv[]){
FILE *in, *out ;
char ch ;
if(argc !=3){
printf("Entrer le nom du fichier") ;
exit(1) ;
}

if(in = fopen(argv[1], "rb")==NULL){


printf("Impossible douvrir le fichier") ;
exit(1) ;
}

if(out = fopen(argv[2], "rb")==NULL){


"rb")==NULL){
printf("Impossible douvrir le fichier de destination") ;
exit(1) ;
}

while( !feof(in)) {
ch = getc(in) ;
if( !feof(in))
putc(ch, out) ;
}
fclose(in) ;
fclose(out) ;

return 0 ;
}

Dr. Eugne C. EZIN.

80

10.1. Prsentation des fonction fputs() et fgets()


Elles sont semblables aux fonctions puts() et gets() sauf que celles-ci ont besoind dun flot comme
paramtre.. Leurs prototypes sont donc:
int fputs(const char * str, FILE *fp) ;
int fgets(char *str , int longueur, FILE *fp) ;
La fonction fputs() crit du flot indiqu, la chane de caractres pointe par str et restitue la
valeur EOF.
La fonction fgets() lit une chane de caractres du flot indiqu jusquau caractre de fin de
ligne ou jusqu la lecture de (longueur - 1) caractres.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(void){

char str[80] ;
FILE *fp ;

if((fp=fopen("test", "w")) == NULL){


printf("Impossible douvrir le fichier") ;
exit(1) ;
}
do{
printf("Entrer une chane :") ;
gets(str) ;
strcat(str, "\
"\n") ;
fputs(str, fp) ;
} while(*str
while(*str

!= \n) ;

return 0 ;
}

10.2. Prsentation des fonctions fread() et fwrite()


Le langage C propose deux fonctions pour lire et crire des blocs de donnes de nimporte quelle
dimension. Leurs prototypes respectifs sont :
size_t fread(void * buffer, size_t nomoctet, size_t nombre, FILE * fp) ;

Dr. Eugne C. EZIN.

81

size_t fwrite(void * buffer, size_t nomoctet, size_t nombre, FILE * fp) ;

Rappelons ici que le type size_t reprsente unsigned int.


Voyons un exemple qui fait usage de ces fonctions.
#include<stdio.h>
#include<stdlib.h>
#include<stdlib.h>

int main(){

FILE *fp ;
double d = 12.23 ;
int i = 101 ;
long l = 12302L ;

if((fp=fopen("test", "wb+")) == NULL){


printf("Impossible douvrir le fichier") ;
exit(1) ;
}
fwrite(&l,sizeof(long), 1, fp) ;
fwrite(&l,sizeof(long), 1, fp) ;
fwrite(&l,sizeof(long),
fwrite(&l,sizeof(long), 1, fp) ;
rewind(fp) ;
fread(&d,sizeof(double), 1, fp) ;
fread(&i,sizeof(int), 1, fp) ;
fread(&l,sizeof(long), 1, fp) ;

printf("%f %d %ld",d, i, l) ;

fclose(fp) ;
return 0 ;
}

La fonction rewind(fp) permet de repositionner lindicateur de position au dbut du fichier et son


prototype est void rewind(FILE *fptr) ;
Le principe est valable aussi pour les structures. Ainsi donc, pour une structure dfinie par

Dr. Eugne C. EZIN.

82

struct strucType{
float balance ;
char nom[80] ;
} client;
on pourrait crire : fwrite(&client , sizeof(struct strucType), 1, fp) ;

10.3. Prsentation des fonctions ftell() et fseek()


Ces deux fonctions sont extrmement utiles pour la manipulation des fichiers binaires. Leur
manipulation et leur bon fonctionnement ncessitent louverture du flot en mode binaire.
La fonction fseek() dtermine la position de lindicateur du fichier. Son prototype est :
int fseek(FILE * fp, long nbreOoctets, int origine) ;
Les valeurs possibles de origine sont :
Dbut du fichier

SEEK_SET (0)

Position du fichier

SEEK_CUR (1)

Fin du fichier

SEEK_END (2)

Voyons un exemple qui fait usage de la fonction fseek().


#include <stdio.h>
int main(){
FILE * fp ;
if (argc !=3){
printf("Usage : SEEK fichier byte:\
byte:\n") ;
exit(1) ;
}
if ((fp=fopen(argv[1], "r"))
"r")) == NULL){
printf(" Impossible douvrir le fichier") ;
exit(1) ;
}
if (fseek(fp, atol(argv[2]) , SEEK_SET){
printf(" Erreurde positionnement") ;
exit(1) ;
}
printf("Loctet ladresse %ld contient %c", atol(argv[2]), getc(fp)) ;
fclose(fp) ;
return
return 0 ;
}

Pour connatre la position courante lintrieur dun fichier, on utilise la fonction ftell(). Son
prototype est : long ftell(FILE * fp) ;

Dr. Eugne C. EZIN.

83

En gnrale, laccs direct se fait essentiellement sur des fichiers binaires puisquil pourrait
ne pas y avoir une correspondance directe entre le contenu du fichier et les octets sur lesquels on
effectue le positionnement.
Enfin, un fichier de type texte peut-tre ouvert en modalit binaire. Cela permet dutiliser
efficacement les fonctions fseek() et ftell() pour une bonne manipulation des fichiers de type texte.

Conclusion
Nous avions explor travers ce chapitre la notion de flot qui permet de manipuler des donnes au moyen des
fichiers. Le langage C reste un langage trs format et il est ncessaire parfois de savoir comment les donnes
sont organises dans les fichiers pour leur meilleure manipulation.

Dr. Eugne C. EZIN.

84

La gestion dynamique de la mmoire


Introduction
Un programme en C fait manipuler des variables qui font usage de la mmoire RAM. Les variables
que nous nous avons manipuler jusquici sont de deux sortes :les variables locales et les variables
globales dont les emplacements dans la RAM sont assez bien dfinis. Dans le cas des variables
globales (donnes statiques), les donnes occupent un emplacement bien dfini lors de la
compilation. Les variables locales sont gres, sous forme de stack laquelle croit ou dcrot
suivant les besoins du programme. Dans ce chapitre-ci, nous allons prsenter les donnes
dynamiques qui nont pas une taille bien dfini priori. Leur gestion ne se fait pas la manire des
donnes automatiques ou statiques mais se fait dans une zone appele heap . Leur manipulation
est sous le contrle du programmeur.

1. Importance des donnes dynamiques


Les donnes statiques ne permettent pas de manipuler les tableaux dont la dimension peut tre
connu la phase dexcution. Les programmeurs parfois gaspillent de lespace mmoire en donnant
une taille plus grande aux tableaux manipuler.
La gestion statique ne se prte pas la mise en uvre des listes chans, des arbres binaires, des
objets dont la taille ne peut tre connue lors de la compilation.
Les fonctions qui permettent la gestion dynamiques de la mmoire ne sont pas nombreuses mais il
faut savoir les utiliser de faon efficace. Nous allons prsenter les fonctions malloc,() calloc(),
free(), etc. Avant daborder ltude de ces fonctions, prsentons dabord la notion de pointeur
gnrique.

2. Pointeur gnrique
On a parfois besoin dexploiter une adresse sans savoir le type de linformation qui sy trouve, la
norme ANSI C a introduit le type pointeur void * qui dsigne un pointeur sur un objet de type
quelconque. Ce type est compatible avec nimporte quel type de pointeur.

3. Prsentation de la fonction malloc()


Le prototype de cette fonction est le suivant :
void * malloc ( size_t) ;

Dr. Eugne C. EZIN.

85

qui se trouve dans les librairies stdlib.h et alloc.h. Le rsutat fourni par malloc() est un pointeur
gnrique. On pourra donc le convertir en dautres types de pointeur. Lunique argument est de type
size_t qui est en fait un typedef de unsigned int.
int
La fonction malloc() restitue une adresse NULL lorsque lallocation mmoire a chou. Il faudra
donc prvoir cette alternative lors de lutilisation.
Ainsi linstruction int * ptr = malloc(50*sizeof(int))
malloc(50*sizeof(int)) ; alloue une zone de 50 cases,
chacune en mesure de contenir un entier. Mais en ralit il faut ajouter 4 octets supplmentaires (les
explications sont donnes dans le chapitre concernant les structures, les tableaux et les pointeurs).
Lutilisation de loprateur sizeof() est fortement conseille mme si le programme est pour des fins
personnelles.
Les contenus de la zone de mmoire alloue peuvent tre imprvisibles avec la fonction malloc().

4. Prsentation de la fonction free()


Une fois la zone de mmoire alloue par lemploi de la fonction malloc(), il faut restituer au
systme les ressources. Cela se fait avec la fonction free().
free() Le rle de la fonction free() est de
librer un emplacement pralablement allou. Le prototype de cette fonction est :
void free(void *);
Dans lexemple free(ptr), le pointeur ptr doit ncessairement dsigner une zone pralablement
alloue au moyen de la fonction malloc(), calloc ()ou realloc().
realloc()

4.1. Exemple dutilisation des fonctions malloc() et free()


#include<stdio.h>
#include<stdio.h>
#include<alloc.h>

int main(){
int
float

nbre, *ptr1 ;
*ptr2;

printf(" Entrer le nombre delements") ;


scanf("%d",&nbre) ;
ptr1 = malloc(nbre*sizeof(int)) ;
printf(\
printf(\nAllocation de %d octets en ladresse %p pour %d entiers ,
nbre*sizeof(int), ptr1, nbre);
ptr2 = malloc(nbre*sizeof(float)) ;

Dr. Eugne C. EZIN.

86

printf(\
printf(\nAllocation de %d octets en ladresse %p pour %d float ,
nbre*sizeof(float), ptr2, nbre);
free(ptr1) ;
printf(" \nLibration de %d octets en ladresse %p ",ptr1) ;
free(ptr2) ;
printf(" \nLibration de %d
%d octets en ladresse %p ",ptr2) ;
return 0 ;
}

Certains avertissements ou erreurs peuvent surgir sur des compilateurs C++ qui veulent que lon
fasse une conversion explicite des pointeurs. Ainsi donc, les instructions pour lallocation se
prsenteraient comme :
ptr1 = (int *) malloc(nbre*sizeof(int));

5. Prsentation de la fonction calloc()


Le prototype de la fonction calloc() est le suivant :
void * calloc(size_t nblocs,size_t t);

qui alloue nblocs conscutifs ayant chacun une taille de t octets. La fonction calloc() remet zro
chacun des octets de la zone alloue.

6. Prsentation de la fonction realloc()


Le prototype de la fonction realloc() est le suivant :
void * realloc(void* ptr nblocs,size_t t);
qui permet de modifier la taille dune zone pralablement alloue par malloc(), calloc(). Le pointeur
doit tre ladresse du dbut de la zone dont on veut modifier la taille. Le second paramtre reprsente
la nouvelle taille sollicite.
Cette fonction restitue ladresse de la nouvelle zone ou un pointeur nul dans le cas o lallocation a
chou.
Si la nouvelle taille demande est suprieure lancienne, le contenu de lancienne zone est
conserv (qui le recopier si la nouvelle adresse est diffrente de lancienne).
Dans le cas o la nouvelle taille est infrieure lancienne, le dbut de lancienne zone verra son
contenu inchang.

7. Application la manipulation des matrices


Les mathmaticiens et surtout les ingnieurs font beaucoup usage des matrices. Il est tout fait juste
de manipuler les donnes de ces objets de faon dynamique. Le but de cet exercice est de proposer

Dr. Eugne C. EZIN.

87

un programme crit en C qui permet de manipuler les matrices carres de faon dynamique en
crivant les fonctions suivantes :

alloueEspace() ; qui permet dallouer dynamiquement de lespace la matrice manipuler.

initMat() qui permet dinitialiser une matrice. Cela consiste crer de lespace

traceMat() qui permet de calculer la trace dune matrice ;

sommeEltsMat() qui permet de calculer la somme des lments dune matrice ;

sommeMat() qui permet de faire la somme de deux matrices ;

prodMat() qui permet de faire le produit de deux matrices.

libereEspace() qui permet de restituer la mmoire au systme.

Conclusion
Dans ce chapitre, nous avons prsent les fonctions essentielles qui permettent la gestion dynamique de la
mmoire. La matrise de ce chapitre est indispensable pour une bonne comprhension du cours des structures
de donnes qui font la fois usage des pointeurs et de la gestion dynamique.

Dr. Eugne C. EZIN.

88

Etude du prprocesseur
Introduction
Le prprocesseur est un programme qui est excut automatiquement avant la compilation et
qui transforme le fichier source partir dun certain nombre de directives. Les directives sont crites
sur des lignes distinctes et commencent par le symbole dise #.
Dans un programme C, il est possible de faire usage du prprocesseur au moyen des
directives mme si elles ne font pas parties du langage C. Ces directives commencent par le symbole
#.
Le prprocesseur accepte les directives suivantes :
#define

#elif

#else

#endif

#error

#if

#ifdef

#ifndef

#include

#line

#pragma

#undef

Dans ce chapitre, nous allons prsenter quelques unes de ces directives.

1. Etudes des directives


1.1. La directive #define
La directive #define dfinit un identificateur appel nom de macro et une suite de caractres qui sont
substitus lidentificateur chaque fois quune occurrence de la macro se trouve dans le fichier
programme. La syntaxe gnrale de la macro #define est :

#define nomMacro suiteCaracteres

Exemple :
#define GAUCHE -1
#define DROITE 1
#define MILIEU

GAUCHE + DROITE

#define EMS "Erreur dEntre\


dEntre\n"
printf(EMS) ;

Remarques : Si la suite de caractres stend sur plusieurs lignes, on peut continuer sur la ligne
suivant aprs le caractre \.
Seule une directive peut occuper une ligne.

Dr. Eugne C. EZIN.

89

La Fonction Macro
Une fonction macro est une fonction dont les arguments utiliss dans la dfinition de la macro sont
effectivement remplacs par leur valeur dans le programme.
Exemple :
#include<stdio.h>
#define ABS(a)

(a) < 0 ?-(a) : (a)

int main(void){
printf("Valeurs

absolues

de

-1

et

de

sont :

%d

%d",ABS(%d",ABS(-

1),ABS(1)) ;
return 0 ;
}

Les fonctions macros prsentent parfois des difficults si lon ne prend pas garde den faire
un bon usage. Voyons des exemples pour clarifier cet aspect.

La directive #define carre(A) A*A peut paratre correcte. Mais ce nest quune apparence. En
effet, une expression comme carre(2+3) ne donnera pas comme rsultat 25 mais plutt 11.

La direcive #define carre(A) (A)*(A) peut paratre juste mais une expression aussi banale
comme

9 / carre(3)

ne donnera par 1 mais plutt

9. Ainsi une bonne dfinition

serait :#define carre(A) ((A)*(A)).

Malgr cette bonne prcaution, une expression comme carre(i++) ne saurait jamais tre le
carr effectif de i++.

En consquence, lutilisation des parenthses est fortement conseille pour la dfinition des
macros comme fonctions.

1.2. La directive #error


Cette directive demande au compilateur darrter la compilation. Elle est surtout utilise pour le
dboggage. La syntaxe est la suivante :
#error messageErreur
messageErreur nest pas entre les griffes (cest dire " ").
messageErreur saffiche avec dventuels autres messages selon le compilateur.

1.3. La directive #include


La directive #include demande au compilateur de lire un autre fichier (autre que le fichier programme
en cours). Deux formes sont souvent rencontres.
Considrons lexemple suivant pour lillustration.
#include <stdio.h>
#include "maBibl.h"

Dr. Eugne C. EZIN.

90

La premire demande au compilateur de rechercher le fichier dentte stdio.h dans les


rpertoires spciales selon limplmentation du compilateur.
La deuxime demande au compilateur de rechercher le fichier maBibl.h dans le rpertoire
courant. En cas dchec, le fichier est recherch comme si la directive tait sous la premire forme.

2. Les directives #if #elif #else #endif


Elles permettent dinclure de faon conditionnelle certaines portions de code sur la base du rsultat
dune expression constante. La syntaxe est la suivante :
#if exprConstante
instruction ;
#endif

Si exprConstante est vraie, alors cest le code entre #if et #endif qui est compil.
Considrons lexemple suivant:
#include<stdio.h>
#define MAX 100
int main(void){
#if (MAX > 99)
printf("Compilation car MAX est plus grand que 99")
99") ;
#endif
return 0 ;
}

La directive #else spcifie une alternative comme dans le cas de else du langage C.

#include<stdio.h>
#define MAX 100
int main(void){
#if (MAX > 99)
printf("Compilation car MAX est plus grand que 99") ;
#else
printf("Compilation
printf("Compilation car MAX est plus petit que 99") ;
#endif
return 0 ;
}

Dr. Eugne C. EZIN.

91

Seule la portion de code situe entre #if et #else est compile comme le montre le rsultat
lcran.

La directive #elif (qui signifie else if) dfinit une alternative plusieurs options du
compilateur.

#if exprConstante1
instructions
#elif exprConstante2
instructions
#elif exprConstante3
instructions
#endif

Voyons lillustration par lexemple suivant :


#define FRANCE 33
#define ANGLETERRE
#define ITALY 39
#define

PAYSACTIF

#if PAYSACTIF

BENIN

== BENIN

char monnaie * = "Franc CFA" ;

#elif PAYSACTIF

== ANGLETERRE

char monnaie* = "Livre Sterling" ;

#elif PAYSACTIF

== ITALY

char monnaie * = "Lire" ;


#endif

2.1

La Directive #ifdef et #ifndef


Elles permettent aussi la compilation conditionnelle. La syntaxe gnrale de #ifdef est :
#ifdef nomMacro
instructions ;
#endif
Si le nom de la macro nomMacro a t dfini par une directive #define alors le bloc

dinstructions compris entre #ifdef et #endif est compil.


De faon similaire, la syntaxe de la directive #ifndef est :

Dr. Eugne C. EZIN.

92

#ifndef nomMacro
instructions ;
#endif
On peut aussi utiliser la directive #else ou #elif avec #ifdef ou #ifndef. Voyons
lexemple suivant pour illustrer cela.
#include<stdio.h>
#define TED 10
int main(void){
main(void){

#ifdef TED
printf ("Salut TED") ;
#else
printf ("Salut Tous") ;
#endif

#ifndef RALPH
printf ("\
("\nSalut Ralph non dfini ") ;
#endif

return 0 ;
}

La sortie de ce programme est :


Salut Ted
Salut Ralph non dfini.

3. La directive #undef
Cette directive limine une dfinition prcdente relative au nom de la macro spcifie. En pratique,
elle limine la dfinition dune macro. La syntaxe gnrale est :
#undef nomMacro

Exemple :
#define

LEN 100

#define

WIDTH 100

char array[LEN][WIDTH] ;
#undef LEN
#undef WIDTH

Dr. Eugne C. EZIN.

93

La directive #undef est utilise principalement pour permettre aux noms des macross dtre
locale selon la section de code dans laquelle elles sont dfinies.

4. Les macros prdfinies


Le langage C offre cinq macros prfinies que sont :
__LINE__
__FILE__
__DATE__
__TIME__
__STDC__

__LINE__ : Cette macro spcifie le nombre de lignes dans le programme compil.

__FILE__ : Cette macro est une chane de caractres qui indique le nom du programme compil.

__DATE__ : Cette macro est une chane

de caractres qui prcise la date suivant le format

mois/jour/anne. Cest la date de traduction du programme en langage machine (fichier .obj).

__TIME__ : Cette macro est une chane d e caractres qui donne lheure de la traduction du
programme en programme objet suivant le format heure :minutes :secondes.

__STDC__ : Si cette macro est dfinie, le compilateur acceptera uniquement les programmes C et
C++ standards rejetant les extensions non standards.
Un exemple qui fait usage de ces macros est le suivant :
#include <stdio.h>
int main(){
printf(\
printf(\n%d,__LINE__);
printf(\
printf(\n%s,__DATE__);
printf(\
printf(\n%s,__FILE__);
printf(\
printf(\n%s,__TIME__);
return 0;
}

5. Les oprateurs du prprocesseur : # et ##


Ces deux oprateurs sutilisent avec la directive #define.

Dr. Eugne C. EZIN.

94

Loprateur # est appel oprateur de conversion en chane de caractres . Il


transforme largument suivant # en une chane de caractres (entre les griffes).
Voyons un exemple :

#include<stdio.h>
#define mkstr(s)

#s

int main(void){
main(void){
printf(mkstr(Le C est bon)) ;
return 0 ;
}

Pour le prprocesseur, cette instruction de la fonction main() est quivalente :


printf("Le C est bon") ;
Loprateur ## est appel oprateur de concatnation. Il est donc un oprateur binaire. Voyons ici
aussi un exemple.
#include<stdio.h>
#define concat(a,b)

a##b

int main(void){

int xy = 10 ;
printf("%d", concat(x,y)) ;
return 0 ;
}

Pour le prprocesseur, cette instruction de la fonction main() est quivalente :


printf("%d",xy) ;

Dr. Eugne C. EZIN.

95

Exercices proposs
CHAPITRE 1

Exercice 1
Ecrire un programme C qui calcule la somme des 100 premiers nombres premiers. Plus gnralement crire un
programme C qui affiche tous les nombres premiers infrieurs un nombre donn.
Exercice 2
Ecrire un programme C qui dtermine le maximum et le minimum de deux rels. Utiliser la modularit dans la
solution ce problme.
Exercice 3
Ecrire un programme C qui calcule le plus petit commun multiple et le plus grand commun diviseur de deux
entiers.
Exercice 4
Ecrire un programme qui dtermine la taille des types de base et la taille des pointeurs aux types de base sur
votre machine.
Exercice 5
On dsire calculer la facture dlectricit dun abonn sachant quil paye les frais fixes qui slvent 1800
FCFA et que la grille de tarification est la suivante :
500 FCFA pour chacun des 100 premiers KWH ;
600 FCFA pour chacun des 150 KWH suivants ;
750 FCFA pour la fraction de la consommation qui excde 250 KWH.
Ecrire un programme C qui affiche le montant de la facture dlectricit dun abonn.
Exercice 6
Ecrire un programme C qui permet partir dune somme dargent donne, affiche le nombre minimum de
pices de 5 F, 10 F, 25 F, 50 F, 100 F, 200 F, 250 F, 500 F qui la dcompose.
Exercice 7
Le jeu mystrieux consiste rechercher un nombre entier positif mystrieux en moins dun nombre fix de
coups. A chaque tape, on donne au joueur les indications suivantes :
Trop petit si le nombre est infrieur au nombre mystrieux ;
Trop grand si le nombre est suprieur au nombre mystrieux ;
Gagn si le nombre est gal au nombre mystrieux ;
Perdu si le nombre dessais est suprieur au nombre fix de coups.
Ecrire un programme C qui traduit ce problme.
Exercice 8
Ecrire un programme C qui dessine un rectangle dtoiles, un triangle isocle dtoiles, et un losange dtoiles
sur lcran.
Exercice 9
Ecrire un programme C qui affiche les nombre parfaits infrieurs un nombre donn. Un nombre est dit parfait
sil est gal la somme de ses diviseurs propres. Par exemple 28 = 1 + 2 + 4 + 7 + 14. Donc 28 est un nombre
parfait.

Dr. Eugne C. EZIN.

96

CHAPITRE 2

Exercice 10
Dboguer le programme suivant :
#include <stdio.h>
int main(){
int i, som;
for (i = 0; i < N; i+=2)
som +=5;
return 0;
}

Exercice 11
Ecrire le programme qui dessine lcran le triangle suivant
*
**
***
****
tout en donnant le nombre total dtoiles ncessaires sa construction.

CHAPITRE 3

Exercice 12

CHAPITRE 4

Exercice 13

CHAPITRE 6

CHAPITRE 7

CHAPITRE 8

Dr. Eugne C. EZIN.

97

Conclusion
Le prprocesseur est un programme trs important qui facile au programmeur lutilisation de certaines
fonctions prfinies ou dfinies par le programmeur par la cration de bibliothque. On peut surtour considrer
le prprocesseur comme le prcurseur du compilateur.

Dr. Eugne C. EZIN.

98

Dr. Eugne C. EZIN.

99

Bibliographie
1. Kochan Stephen, Programmation en Langage C, 3

Dr. Eugne C. EZIN.

me

dition, Sams Publishing 2005,

10
0