Vous êtes sur la page 1sur 46

Langage C

Chapitre 1

Eléments de base de Langage C

1.1 Historique
Le langage C est né en 1972 dans les laboratoires de Bell-laboratories. Il a été conçu par
Denis Ritchie et Brian W.Kernighan.
Les dates marquantes de l’histoire du langage C sont les suivantes :
 1972 : La première version de C est écrite en assembleur par Denis Ritchie et Brian
W.Kernighan.
 1973 : Alan Snyder écrit un compilateur C portable (thèse MIT).
 1975 : Steve C. Johonson écrit et présente le PCC (portable C compiler)
 1978 : Le premier compilateur C sur micro par Tom Gibson.
 1982 : L’ANSI crée un comité technique pour la standarisation du langage C.
 1987 : Normalisation du langage C par I.E.E.E Norme X3J-11. Cette norme a pour but
de rendre plus précise la description du langage C.
 1990 : Réalisation du document final normalisé auprès de l’ISO.
1.2 Présentation
Le langage C est un langage :
Langage évolué : Le programmeur n’est pas obligé de connaître l’architecture interne de
l’ordinateur pour écrire son programme.
Langage structuré : le programme est organisé en « blocs d’instructions » emboîtés.
Modulaire: peut être découpé en modules qui peuvent être compilés séparement
Universel: n'est pas orienté vers un domaine d'application particulier
Typé: tout objet C doit être déclaré avant d’être utilisé

Les compilateurs C possèdent les taux d'expansion les plus faibles de tous les langages
évolués (rapport entre la quantité de codes machine générée par le compilateur et la quantité
de codes machine générée par l'assembleur et ce pour une même application).
La connaissance du langage C est aussi nécessaire pour apprendre les langages proches de C
comme C++ qui est un langage orienté objet basé sur C et JAVA qui est un langage orienté
objet dont les structures ressemblent beaucoup à celles du C.
Le langage C possède assez peu d'instructions, il fait par contre appel à des bibliothèques,
fournies en plus ou moins grand nombre avec le compilateur.

Exemples: math.h : bibliothèque de fonctions mathématiques


stdio.h : bibliothèque d'entrées/sorties standard

1.3. La compilation
Les étapes permettant la création, la mise au point et l’exécution d’un programme sont comme
suit :

a. Création du programme source, il s’agit de la phase de saisie de texte du programme


source qui contiendra les lignes écrites en langage C. (NomduFichier.c)
b. Compilation du programme, c'est à dire création des codes machine destinés au
microprocesseur utilisé. Le compilateur indique les erreurs de syntaxe mais ignore les
fonctions bibliothèque appelées par le programme.

1
Langage C

Le compilateur génère un fichier binaire, non listable, appelé fichier objet:


NomduFichier.OBJ.
c. Editions des liens: Le fichier objet crée par le compilateur n’est pas directement
exécutable, il lui manque pour cela les différents modules correspondants aux
fonctions de la bibliothèque appelées par le programme. C’est le rôle de l’éditeur de
liens, le code machine des fonctions bibliothèques est alors chargé, création d'un
fichier binaire, non listable, appelé fichier exécutable: NomduFichier.EXE.
d. Exécution du programme. Le programme exécutable ainsi crée sera alors lancé
directement en exécution.

1.4 Les composants élémentaires du C


1.4.1 Les identificateurs
Un identificateur est le nom choisi par l’utilisateur pour désigner les différents "objets"
manipulés par le programme: variables, fonctions, etc. Il doit respecter les règles suivantes :
 Il ne peut être composé que de lettres alphabétiques (‘a’ à ‘z’ et ‘A’ à ‘Z’) des chiffres
(0 à 9) et du caractère souligné _
 Il doit obligatoirement commencé par une lettre alphabétique ou le caractère _ (dans la
norme ANSI le caractère souligné _ est considéré comme une lettre).
 Il ne doit pas être un mot clé

Exemple :
Tva, p250, a_x, _ax.(identificateurs)
2x, x#y (ne sont pas des identificateurs)

1.4.2 Les mots clés


Certains "mots clés" sont réservés par le langage à un usage bien défini et ne peuvent pas être
utilisés comme identificateurs. En voici la liste, classée par ordre alphabétique.
auto default float register struct volatile
break do for return switch while
case double goto short typedef
char else if signed union
const enum int sizeof unsigned
continue extern long static void

1.4.3 Les séparateurs :


Les principaux séparateurs du langage C sont :
 L’espace et les sauts de lignes assurent la mise en page du programme.
 , la virgule sépare des éléments d’une liste et sert d’opérateur en particulier dans la
boucle for
 ( ) les parenthèses encadrent une listes d’arguments
 { } les accolades encadrent un bloc d’instructions ou une liste de valeurs
d’initialisation
 ; termine une déclaration de variables ou une instruction
 [] les crochets encadrent la dimension ou l’indice d’un tableau
 /* */ encadrent un commentaire

1.4.4 Les commentaires :


Les commentaires sont utilisés pour clarifier la lecture d’un programme. Ils sont ignorés par le
compilateur et l’exécuteur
Exemple : /* ceci est un commentaire*/

2
Langage C

Remarque
Le langage C distingue les minuscules, des majuscules. Les mots réservés du langage C
doivent être écrits en minuscule.

1.5 Structure simplifiée d’un programme en langage C:


D’une manière générale, un programme écrit dans un langage de programmation (C….)
est composé principalement de deux parties : une partie déclaration et une partie
traitement contenant les instructions.
Un programme en langage C peut avoir la structure simplifiée suivante :

main( ) void main( )


{ {
Instructions de déclaration Instructions de déclaration
Instructions exécutables Instructions exécutables
return 0 ; }
}

1.6 Les types de base en C


Les types de bases en C se répartissent en trois grandes classes en fonction de la nature des
informations qu’ils permettent de représenter :
 Les types entiers
 Les types réels
 Les types caractères

1.6.1 Les types entiers :


C dispose de 6 types d’entiers différents caractérisés par :
 Leur taille (mot mémoire, 16 bits ou 32 bits)
 La présence ou l’absence du signe : signed ou unsigned
Le type int
C’est le type entier standard et sa représentation est différente suivant les machines. Le type
int est lié à la longueur du mot machine (emplacement mémoire)
Le type entier court (short int)
Ce type est codé sur 16 bits
Par défaut le compilateur C utilise des nombres signés. Pour préciser que l’on utilise un
nombre non signé, on fait précéder la déclaration du mot clé unsigned
Le type entier long (long int)
Ce type possède les mêmes propriétés que le type entier mais le codage est effectué sur 32 bits
au lieu de 16.

TYPE INTERVALLE TAILLE MEMOIRE (octets)


int dépend du mot machine 2 ou 4
unsigned int dépend du mot machine 2 ou 4
short int -32768 à 32767 2
unsigned short 0 à 65535 2
long int -2 147 483 648 à 2 147 483 647 4
unsigned long int 0 à 4 294 967 295 4

Remarque:

3
Langage C

Le type int est soit équivalent à short (dans le cas où le mot machine est de 16 bits) ou long
(dans le cas où le mot machine est de 32 bits)
1.6.2 Les types réels (types flottants)
Les types flottants en C permettent de représenter, de manière approchée des nombres réels
C dispose de 3 types flottants caractérisés par leurs tailles :
a. le type float qui utilise 32 bits
b. le type double qui utilise 64 bits
c. le type long double qui utilise 80 bits
Un réel est composé - d'un signe - d'une mantisse - d'un exposant
Pour chacun de ces types, la représentation d’un nombre se décompose alors en trois parties :
 Un bit réservé au signe.
 Un emplacement pour un exposant
• 8 bits pour le type float
• 11 bits pour le type double
• 15 bits pour le type long double.
 Un emplacement pour la mantisse
• 23 bits pour le type float
• 52 bits pour le type double
• 64 bits pour le type long double.

TYPE DESCRIPTION TAILLE MEMOIRE


float 1.2E(-38) 3.4E(+38) 4 octets
double 2.3E(-308) 1.7E(+308) 8 octets
long double 3.4E(-4932) 1.1E(+4932) 10 octets

Remarque : Ce tableau correspond seulement aux valeurs absolues des nombres, il peut
être complété de façon symétrique pour les valeurs négatives.

1.6.3 Les types caractères :


Les variables de type char sont codées sur 8 bits. On peut ainsi avoir 28=256 valeurs
La table la plus couramment employée pour définir un caractère est la table ASCII
Les variables de type char peuvent aussi servir à des calculs. Mais leurs valeurs sont entre
-128 et 127 ou entre 0 et 255 pour le cas de unsigned char

Remarque:
En langage C, le type char est un cas particulier du type entier.
Par exemple, Le caractère 'b' a pour valeur 98 (son code ASCII).
Tout objet de type char peut être utilisé dans une expression qui utilise des objets de type
entier. Par exemple, si c est de type char, l’expression c + 1 est valide
Les caractères constants s’écrivent entre ‘ ’
Par exemple : char c = ’A’;

Quelques constants caractères


Caractère Valeur (code ASCII) Nom ASCII
‘\n’ interligne (saut de ligne) 0x0a LF
‘\t’ tabulation horizontale 0x09 HT
‘\v’ tabulation verticale 0x0b VT
‘\f’ saut de page 0x0c FF
‘\\’ backslash 0x5c \

4
Langage C

‘\’’ cote 0x2c ‘


‘\’’ ’ guillemets 0x22 ‘’

1-7 Déclaration de variables et constantes


1.7.1 Déclaration de variables :
La déclaration d’une variable associe à un identificateur un type et une taille mémoire.
Toute variable utilisée dans un programme écrit en C doit être déclarée.

Syntaxe:
Type variable1, variable2,…. ;

Exemple:
int a,b ;

1.7.2 Initialisations
Le langage C permet l'initialisation des variables dans la zone des déclarations.
Exemple :
char c; c = 'A'; est équivalent à char c = 'A';
int i; i = 50; est équivalent à int i = 50;

1.7.3 Les constantes


Il existe 4 types de constantes associées aux types de bases:
 Constante de type entier
 Constante flottante
 Constante caractère
 Constante chaîne de caractères.
Le langage C autorise 2 méthodes pour définir des constantes.
1ere méthode: déclaration d'une variable, dont la valeur sera constante pour tout le
programme:
Exemple: const float PI = 3.14159;

2eme méthode: définition d'un symbole à l'aide de la directive de compilation #define.


Exemple:
#define PI 3.14159;

Le compilateur ne réserve pas de place en mémoire.

1.8 Opérateurs de Langage C


1.8.1 Définition d’un Opérateur :
Les opérateurs sont des symboles qui permettent de manipuler des variables.
Les opérateurs peuvent être unaires, binaire ou tertiaire selon le nombre d’opérandes utilisé.

1.8.2 Type d’opérateur


Opérateurs unaires : Un opérateur unaire agit sur un seul opérande qui peut être une
constante, une variable, ou une expression.
La liste des opérateurs unaires en C est la suivante :
& opérateur d’adresse
* opérateur d’indirection sur une adresse

5
Langage C

-- opérateur de décrémentation
++ opérateur d’incrémentation
Sizeof opérateur de taille en octets
! NOT logique
- Moins unaire : inverse de signe

Opérateurs binaires : Un opérateur binaire agit sur deux opérandes

La liste des opérateurs binaires en C est la suivante


+- * / % addition, soustraction, multiplication, division, modulo
& | ^ et, ou, ou exclusif
>> << Décalage vers la droite ou vers la gauche
< <= > >= inférieur, inférieur ou égal, supérieur, supérieur ou égal
= = != égal, non égal
&& || et logique, ou logique
= affectation.

Opérateurs tertiaires : Il existe en C un opérateur tertiaire qui porte sur trois opérandes.
C’est l’opérateur ?

Syntaxe :
exp1 ? exp2 :exp3
Où exp1, exp2, exp3 sont trois expressions
Le résultat retourné est exp2 si exp1 est vraie, ou exp3 si exp1 est faux.

Exemple
max =(a>=b ? a :b) ;

On distingue plusieurs types d’opérateurs selon leur rôle :

1.8.3 Opérateur d’affectation


L’opération la plus élémentaire est l’affectation, elle permet de mettre une valeur dans une
variable. En langage C, l’opérateur d’affectation est désignée par le symbole =
Syntaxe : var = expression ; // var est une variable
1.8.4 Opérateurs arithmétiques :
Opérateurs arithmétiques sur les réels: + - * / avec la hiérarchie habituelle.
Exemple : float x=5 ; float y=2 ;
x/y vaut 2.5

Opérateurs arithmétiques sur les entiers: + - * / (quotient de la division) % (reste de la


division) avec la hiérarchie habituelle.
Exemple : int x=5 ; int y=2 ;
x/y vaut 2
x%y vaut 1
Les caractères sont des entiers codés sur 8 bits, on peut donc effectuer des opérations.
Exemple : char c,d;
c = 'G';
d = c+'a'-'A';
Sur cet exemple, on transforme la lettre majuscule G en la lettre minuscule g.

6
Langage C

1.8.5 Opérateurs relationnels :


Les opérateurs de relation servent à réaliser des tests entre les valeurs de deux expressions.

Opérateur Dénomination
== Opérateur d’égalité
< Opérateur d’infériorité stricte
<= Opérateur d’infériorité
> Opérateur de supériorité stricte
>= opérateur de supériorité
!= Opérateur de différence

1.8.6 Opérateurs logiques :


Ce type d’opérateur permet de vérifier si plusieurs conditions sont vraies ou fausses.
C dispose de trois opérateurs logiques classiques

Opérateur Dénomination Effet


|| OU logique Vérifie qu’une des conditions est valable
&& ET logique Vérifie que toutes les conditions sont réalisées
! NON logique Inverse l’état d’une variable (retourne la valeur 1 si la
variable 0,0 si elle vaut 1)

Remarque :
Le langage C ne dispose pas de type logique.
Une expression est fausse si la valeur qu’elle retourne est égale à 0, elle est vraie si non.
C’est pourquoi ces opérateurs produisent un résultat numérique de type int.

1.8.7 Opérateur d’incrémentation et de décrémentation


On peut considérer que si var est une variable entière :
var-- ; // est équivalent à var=var-1
var++ ; // est équivalent à var=var+1

Lorsque l’opérateur est préfixé (opérateur ++ avant la variable), l’incrémentation est


appliquée avant l’affectation
Exemple (de la pré-incrémentation):
int i=0,j=0 ;
j=++i ;
on obtient: i vaut 1 et j vaut 1
int a=1,b=1 ;
b=--a ;
on obtient: a vaut 0 et b vaut 0

Dans le cas où l’opérateur est post-fixé (opérateur ++ après la variable), l’incrémentation est
appliquée après l’affectation.
Exemple:
int i=0, j=0 ;
j=i++;
A la fin de cette opération i vaut 1 et j vaut 0.
De même que la post-incrémentation, il est possible d’utiliser la post-décrémentation.

1.8.8 Opérateurs combinés (d’assignation)

7
Langage C

Le langage C autorise des écritures simplifiées lorsqu'une même variable est utilisée de
chaque côté du signe = d'une affectation. Ces écritures sont à éviter lorsque l'on débute l'étude
du langage C car elles nuisent à la lisibilité du programme.
Exemples : a = a+b; est équivalent à a+= b;
a = a-b ; est équivalent à a-= b;

1.8.9 Opérateurs de Conversion de types :


On appelle conversion de type de données le fait de modifier le type d’une donnée en un autre
type. Il existe deux types de conversions :
 Conversion implicite : Consiste en une modification du type de donnée effectué
automatiquement par le compilateur. Cela signifie que lorsque l’on va stocker un type
de donné dans une variable déclarée avec un autre type, le compilateur effectuera une
conversion implicite de la donnée.
 Conversion explicite : On utilise pour cela l'opérateur de cast ‘’ ( )’’. Et consiste en
une modification de la donnée forcée.

Exemple:
int n,p;
n=1 ;
float x,y;
x=6.25;
y =-14.4.;
x=n; /*conversion implicite*/
p= (int)y; /*conversion explicite*/

le résultat est
x=1
p=-14

1.8.10 La Priorité des Opérateurs en C


La précédence des opérateurs détermine l’ordre d’évaluation de l’expression par le
compilateur.
La priorité est décroissante de haut en bas selon le tableau suivant :
Lorsque deux opérateurs se trouvent dans la même ligne du tableau, la priorité
d’évaluation d’une ligne de C dans laquelle se trouvent ces opérateurs, est donnée par la
colonne (associativité).

CATEGORIE OPERATEURS ASSOCIATIVITE


Référence () [] De gauche à droite
Unaire ! = - + -- ++  (type) * & sizeof De droite à gauche
Arithmétique */ % De gauche à droite
Arithmétique + - De gauche à droite
Décalage << >> De gauche à droite
Relationnels < < = > >= De gauche à droite
Relationnels == != De gauche à droite
Manipulation &
de bits
Manipulation ^
de bits

8
Langage C

Manipulation |
de bits
Logique &&
Logique ||
Tertiaire ?
Affectation = += -= *= /= %= &= ^= |= <<= >>= De gauche à droite
Séquentiel ,

1.9 Les instructions d’entrées-sorties classiques


1.9.1 Sorties de nombres ou de texte à l’écran :
La fonction printf
C’est une fonction de la bibliothèque stdio.h, qui permet d’afficher sur la sortie standard
(écran) n'importe quel type de données.

 Affichage d’un texte


Exemple :
Printf("texte") ; /* pas de retour a la ligne du curseur après l’affichage,*/
Printf("texte \n") ; /*affichage du texte puis retour à la ligne du curseur.*/

 Affichage d’un résultat


La fonction printf exige l’utilisation de format de sortie, avec la structure suivante :
Printf("% code format ",nom _de _variable) ;

 Affichage multiple de structure:


printf("%code format1 %code format2 ... %code forma n",variable1,variable2,....,variable n);

 Les codes formats de sortie:


Les codes format précisent comment présenter les valeurs des expressions
(variable1,variable2,....,variable n) qui figurent en arguments de printf
Les principaux codes de format disponible en C sont :

code type
%c Caractère
%d Décimal
%e Réel sous forme exponentielle
%f Réel avec le point décimal
%lf Réel de type double
%s Chaîne de caractère
%u Décimal non signé
%x Hexadécimal signé

En plus du caractère donnant le type des données, on peut éventuellement préciser certains
paramètres du format d’impression, qui sont spécifiés entre le % et le caractère de conversion
dans l’ordre suivant :
– largeur minimale du champ d’impression : %10d spécifie qu’au moins 10 caractères seront
réservés pour imprimer l’entier. Par défaut, la donnée sera cadrée à droite du champ. Le signe
- avant le format signifie que la donnée sera cadrée `a gauche du champ (%-10d).
– précision : %.12f signifie qu’un flottant sera imprimé avec 12 chiffres après la virgule. De
même %10.2f signifie que l’on réserve 12 caractères (incluant le caractère .) pour imprimer le
flottant et que 2 d’entre eux sont destinés aux chiffres après la virgule. Lorsque la précision

9
Langage C

n’est pas spécifiée, elle correspond par défaut à 6 chiffres après la virgule. Pour une chaîne de
caractères, la précision correspond au nombre de caractères imprimés : %30.4s signifie que
l’on réserve un champ de 30 caractères pour imprimer la chaîne mais que seulement les 4
premiers caractères seront imprimés (suivis de 26 blancs).

La fonction putchar
La fonction putchar permet d’afficher à l’écran un seul caractère.
Soit c une variable de type char, l’écriture putchar(c), est équivalente à printf(’’%c\n’’, c).

La fonction puts
La fonction puts permet d’afficher un texte :
L’écriture puts("bonjour"), est équivalente à printf("bonjour\n").

Remarque
Il vaut mieux utiliser puts et putchar si cela est possible, ces fonctions, non formatées, sont
d’exécution plus rapide, et nécessitent moins de place en mémoire lors de leur chargement.

1.9.2 Saisie de Nombres et de Caractères au Clavier (lecture des données) :


La fonction scanf
La fonction scanf, appartenant à la bibliothèque stdio.h, permet la lecture de n'importe quel
type de données (variables) saisie au clavier.
Le nom de la variable est précédé du symbole & désignant l'adresse de la variable (On reverra
ce symbole dans le chapitre sur les pointeurs).

Syntaxe :
scanf("code format1 code format2... code format n",&variable1, &variable2,..., &variable n);

Exemples: char alpha;


int i;
float r;
scanf("%c",&alpha); /* saisie d'un caractère */
scanf("%d",&i); /* saisie d'un nombre entier en décimal */
scanf("%f",&r); /* saisie d'un nombre réel avec le point décimal */

Remarque
Si l’utilisateur ne respecte pas le format indiqué dans scanf, la saisie est ignorée. Aucune
erreur n’est générée.

La fonction getch
La fonction getch, appartenant à la bibliothèque conio.h permet la saisie au clavier d’un seul
caractère alphanumérique, sans écho écran. La saisie s’arrête dès que le caractère a été frappé.

Exemple
char alpha ;
printf ("Entrer un caractère") ;
alpha=getch() ;
printf ("\n Voici ce caractère :%c", alpha) ;

Remarque

10
Langage C

Les parenthèses vides de getch() signifient qu’aucun paramètre n’est passé à cette fonction par
le programme.

La fonction getchar
La fonction getchar permet la saisie d’un seul caractère (char) avec écho écran.
Exemple
Les deux écritures sont équivalentes :

char c ; char c ;
printf ("Entrer un caractère :") ; printf ("Entrer un caractère :") ;
scanf("%c",&c) ; c=getchar() ;

Remarque
Non formatée (pas de code format), la fonction getchar est moins gourmande en place
mémoire que scanf. Il vaut mieux l’utiliser quand cela est possible.

Exemple d’application
# include <stdio.h>
# include <conio.h>
main ( ){
char c ;
printf("Entrer un caractère :") ;
scanf("%c",&c) ; /* ou bien c=getchar() ; */
printf("Voici son code ASCII en decimal :%d \n" , c) ;
puts("Pour continuer frapper une touche…") ;
getch() ;
}
Notion de flux d’entrée :
Lorsqu’on saisie au clavier une suite de caractères terminées par "RETURN", ces caractères
sont rangés dans un tampan (ou buffer) de type FIFO (First In/First Out). Le dernier caractère
rangé dans le tampan est LF (code ASCII 0x0A). Cette suite de caractères est appelé flux
d’entrée la taille d’un tampan dépend de la machine et de compilateur utilisé. (127 caractères
pour un PC en TURBO C).
Une compilation du programme vide le tampan.
scanf et getchar() et flux d’entrée :
la saisie avec scanf et getchar est terminée par "RETURN", si le tampan est vide tous se passe
normal. Cependant, si le tampan n’est pas vide, ces fonctions testent le dernier élément s’il
correspond au format de la variable invoquée et le tampan perd cet élément.
Tout caractère ou nombre saisi au clavier et non pris en compte par scanf est rangé dans le
tampan.
Exemple :
#include<stdio.h>
main(){
char c1,c2;
printf("donner un caractère\n");
scanf("%c",&c1);
printf("voici son code ASCII en hexadécimal%x\n",c1);
printf("donner un autre caractère\n");

11
Langage C

scanf("%c",&c2);
printf("voici son code ASCII en hexadécimal%x\n",c2);
system("pause");
return 0;
}
Si l’utilisateur saisi A pour c1 :

Après la saisie de K, le caractère LF est rangé dans le buffer, lors du deuxième appel à scanf
le tampan n’est pas vide, pas de saisie au clavier.

Remarque :
En DevC++ la fonction fflush(stdin) permet de vider la tampan d’entrée
En Turbo C la fonction flushall()permet de vider la tampan d’entrée

12
Langage C

Chapitre 2

Instructions de contrôle de Langage C


Les instructions de contrôle permettent de choisir ou de répéter des actions en fonction des
conditions. Les instructions de contrôle sont soient :
Des instructions de choix conditionnelles ou non
Des boucles qui permettent de répéter des actions

2.1 Les instructions de branchement conditionnel

2.1.1 L’instruction de choix logique : SI ... ALORS ... SINON ...


Elle permet d’exécuter un bloc d’instructions en fonction d’une expression :
Il s'agit de l'instruction: si (expression conditionnelle vraie)
alors {BLOC 1 D'INSTRUCTIONS}
sinon {BLOC 2 D'INSTRUCTIONS}

Syntaxe en C: if (expression) {
............; /* bloc 1 d'instructions */
............;
}
else {
............; /* bloc 2 d'instructions */
............;
}
Le bloc "sinon" est optionnel, une autre forme de l’instruction if est donc comme suit :
si (expression vraie)
alors {BLOC D'INSTRUCTIONS}

Syntaxe en C: if (expression) {
............; /* bloc d'instructions */
............;
}
Remarque:
Les {} ne sont pas nécessaires lorsque les blocs ne comportent qu'une seule instruction.

Exemple 1
char reponse ;
printf ("Voulez-vous jouer ?") ;
reponse = getchar() ;
if(reponse = =’o’)
printf ("Bonjour\n") ;
else printf ("Tant-pis"\n) ;
Exemple 2 : un programme qui lit un nombre réel puis affiche sa valeur absolue :

/* programme de la valeur absolue*/

13
Langage C

#include <stdio.h>
void main(){
float x,absx ;
/* x est une variable réelle et absx contiendra sa valeur absolue*/
printf(" Entrer un nombre réel : ") ;
scanf("%f",&x) ; /* lecture de x au clavier*/
if (x>=0) absx=x ;
else absx=-x ;
printf(" la valeur absolue de %f est %f ",x,absx) ;
getchar() ;}

2.1.2 L’instruction de choix multiple : switch. (AU CAS OU ... FAIRE ...)
L'instruction d’aiguillage switch est une instruction du choix multiple qui effectue un
aiguillage vers les instructions en fonction d’une variable.
Syntaxe:
switch(variable de type char ou int) /*au cas où la variable vaut:*/
{
case valeur1: /*- cette valeur1: exécuter ce bloc1 d'instructions. */
bloc1 d'instructions ;
break;
valeur2: /*- cette valeur2: exécuter ce bloc2 d'instructions. */
bloc2 d'instructions ;
break;
. /*etc ... */
.
default: /* - aucune des valeurs précédentes: exécuter ce bloc
bloc d'instructions ; d'instructions, pas de "break" ici. */
}

Remarques
1) le bloc "default" n'est pas obligatoire.
2) L’instruction switch correspond à une cascade d’instructions if ...else
Exemple 1: (exemple avec variable de type int en argument de switch)
int i ;
scanf ("%d",& i) ;
switch(i)
{
case 0 : printf ("c’est dimanche\n") ;
break ;
case 1 : printf ("c’est lundi\n") ;
break ;
:
:
case 6 : printf ("c’est samedi\n") ;
break ;
default : printf ("ce choix n’est pas prevu") ;
}

Exemple 2 : (exemple avec variable de type char en argument de switch)


char c ;

14
Langage C

scanf ("%c",& c) ;
switch(c)
{
Case ‘o’ :
Case ‘O’ : printf ("Oui") ;
break ;
Case ‘n’ :
Case ‘N’ : printf ("Non ") ;
break ;
default : printf ("réponse incorrecte") ;
}

2.2 Les instructions répétitives (boucles)


Les boucles sont des structures qui permettent d’exécuter plusieurs fois la même série
d’instructions jusqu’à ce qu’une condition ne soit plus réalisée. En langage C, existe trois
types de boucles :
while
do while
for
2.2.1 Boucle while (tant que ... faire ...)
Il s'agit de l'instruction: tant que (expression vraie)
faire{Bloc d’instructions}
Elle permet d’exécuter un bloc d’instructions tant qu’une expression est vraie

Syntaxe en C: while (expression)


{
............; /* bloc d'instructions */
............;
}

Remarques
1) Le test se fait d'abord, le bloc d'instructions peut donc ne jamais être exécuté si
l’expression est fausse dès le début.
2) le bloc d'instructions peut être exécuté à l’infini si l’expression reste toujours vraie. On
parle alors de boucle infinie.
3) On peut rencontrer la construction suivante: while (expression); terminée par un ; et
sans la présence du bloc d'instructions. Cette construction signifie: "tant que
l'expression est vraie attendre".
Exemple: Calcul de la somme des N premiers nombres entiers strictement positives (sans
utiliser la formule de la suite)

# include<stdio.h>
void main( ) {
int i,N,somme;
printf(“entrer le nombre N>0:”);
scanf (“%d”,&N);
i=1;
somme=0;
while(i<=N){somme+=i; i++}
printf(“la somme est: %d”,somme);

15
Langage C

getch();
}

2.2.2 L'instruction do…while… (Répéter ... tant que ...)


Cette boucle exécute d’abord une fois les instructions, puis teste la valeur d’une expression et
répète l’exécution des instructions tant que l’expression est vraie.

Il s'agit de l'instruction: répéter{BLOC D'INSTRUCTIONS}


tant que (expression vraie)

Syntaxe en C: do
{
............; /* bloc d'instructions */
............;
}
while (expression);
Remarque
Le test se faisant après, le bloc est exécuté au moins une fois.

Exemple
Contrôler la lecture d’une valeur entière X avec 0<= X <= 10

Void main( ) {
int X;
do {
printf ("introduire la valeur de X avec 0<= X <= 10") ;
scanf ("%d",& X) ;
} while (X>=0&& X<= 10) ;
}

2.2.3 La boucle for (pour...)


Il permet de répéter une liste d’instructions un nombre déterminé de fois.

Syntaxe en C:
for (initialisation ; condition de continuité ; modification)
{
............; /* bloc d'instructions */
............;
}

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


{
............; /* bloc d'instructions */
............;
}
Remarque
Les trois instructions de for ne portent pas forcément sur la même variable.

16
Langage C

Exemple
int i, resultat ;
resultat = 0 ;
for (i = 0 ; resultat< 30 ;i++)
{…………… ;
…………… ;
resultat = resultat + 2*i ;
}
Remarque
En langage C il est possible de regrouper deux instructions en une seul en les séparant par le
symbole virgule (,) par exemple i++, j++.
On peut exploiter cette possibilité pour concevoir des boucles avec deux compteurs à la fois.

Exemple
int i,j ;
for (i = 0,j = 20 ; i< 30 ;i++, j--)
{printf ("i = %d\n", i) ;
printf ("j = %d\n", j) ;
}

17
Langage C

Chapitre 3

Les Tableaux
Définition
On appelle tableau, une variable composée de données de même type, stockées de manière
continue en mémoire (les unes à la suite des autres). Les éléments du tableau peuvent être :
des données de types : int, char, float, long, double, des pointeurs (des objets contenant une
adresse mémoire)…….

3.1 Les tableaux unidimensionnels


3.1.1 Définition
Un tableau unidimensionnel est un tableau qui contient des éléments simples de même type,
pour pouvoir être utilisé, un tableau doit être déclaré
En langage C, la syntaxe de la déclaration d’un tableau unidimensionnel est la suivante :
Type Nom_du_tableau [Nombre d’éléments] ;

 Type définit : le type des éléments du tableau


 Nom_du_tableau : est le nom du tableau, il suit les règles qu’un identificateur C
 Nombres d’éléments : est un nombre entier (constant) qui détermine le nombre
d’éléments que le tableau peut comporter.

Exemples :
char Tableau [8] ; /*déclaration d’un tableau de 8 éléments de types char */
int tab[10] ; */ déclaration d’un tableau de 10 éléments de types int */.

3.1.2 Taille d’un tableau unidimensionnel


Etant donné qu’un tableau est composé d’un nombre fixé d’élément d’un type donné, la taille
d’un tableau est déterminée dès sa définition.
Pour connaître la taille d’un tableau, c'est-à-dire déterminer le nombre d’octets que celui-ci
occupe en mémoire, il y a deux possibilités :
• Calculer manuellement la taille d’un tableau : il suffit de multiplier la taille du type
d’élément par le nombre d’éléments qui composent le tableau.
• Utiliser l’opérateur sizeof() :L’opérateur sizeof() permet de retourner directement la
taille de l’élément qui lui est passé en argument, ainsi en lui passant un tableau comme
opérande sizeof() est capable de retourner directement la taille de celui –ci.

Exemples :
Voici différents exemples de tableaux, et leurs tailles respectives.

Définition du tableau Taille du tableau (en octets)


char tableau1[12] 1*12=12
int tableau2[10] 2*10=20
float tableau3[8] 4*8=32
double tableau4[15] 8*15=120

18
Langage C

3.1.3 Accès aux éléments d’un tableau unidimensionnel


Pour accéder à un élément du tableau, il suffit donc de donner le nom du tableau, suivi de
l’indice de l’élément entre crochets :
Nom_du_tableau[indice]

Remarques :
 L’indice du premier élément du tableau est 0
 Un indice est toujours positif
 L’indice du dernier élément du tableau est égale au nombre d’éléments-1

Exemples :
int Tableau[7] ;
Tableau[0] est le premier élément du tableau
Tableau[6] est le dernier élément du tableau.

3.1.4 Manipulation des éléments d’un tableau unidimensionnel


Un élément du tableau (repéré par le nom du tableau et son indice) peut être manipulé
exactement comme une variable, on peut donc effectuer des opérations sur des éléments du
tableau comme pour une variable.

Exemple :
int tableau [10] ;
tableau [7]=3 ; pour affecter la valeur 3 au huitième élément
tableau [9]=tableau[0]+tableau[1] ; /*Pour affecter au 10ieme élément le résultat de l’addition
du premier et du deuxième élément*/
Remarque :
L’élément tableau[10] n’existe pas(on parle de débordement d’indice).
3.1.5 Initialisation des éléments d’un tableau unidimensionnel
Il existe plusieurs méthodes pour initialiser un tableau :

3.1.5.1 Initialisation individuelle de chaque élément :


Cette méthode consiste à affecter des valeurs aux éléments un par un.

Exemple :
Tableau [0]= Tableau [1]= Tableau [2]=0 ;Tableau [3]=1 ;

3.1.5.2 Initialisation grâce à des boucles :


Il est possible d’utiliser une boucle qui va permettre d’initialiser successivement chacun des
éléments grâce à un compteur qui servira d’indice.

Exemple :
int Tableau [10] ;
int indice ;
for (indice=0 ; indice<10; indice++)
{ Tableau [indice]=0 ; }

3.1.5.3 Initialisation à la définition


Une troisième méthode consiste à initialiser à la définition en plaçant entre accolades les
valeurs, séparées par des virgules.

19
Langage C

Exemple :
int tableau[10]={5,1,6,-8,1,2,1,-2,3,14} ;
Remarques
1) Le nombre de valeurs entre accolades ne doit pas être supérieur au nombre
d’éléments du tableau
2) Les valeurs entre accolades doivent être des constantes.
3) Si le nombre de valeurs entre accolades est inférieur au nombre d’éléments du
tableau, les derniers éléments sont initialisés à 0.

3.2 Tableaux et chaînes de caractères


3.2.1 Définition d’une chaîne de caractère.

Une chaîne de caractères est un tableau, comportant plusieurs données de type char, dont le
dernier élément est le caractère nul '\0', c'est-à-dire le premier caractère du code ASCII (dont
la valeur est 0). Ce caractère est un caractère de contrôle (donc non affichable) qui permet
d'indiquer une fin de chaîne de caractères. Ainsi une chaîne composée de n éléments sera en
fait un tableau de n+1 éléments de type char. On peut toutefois utiliser partiellement cet
espace pour acquérir une chaîne de taille inférieure, en insérant le caractère de fin de chaîne à
l'emplacement désiré dans le tableau.

La taille d’une variable de type char est de un octet. Le nombre d’octets d’un tableau de
caractères sera donc égal au nombre d’éléments.

3.2.2 Déclaration d’une chaîne de caractères.

Pour définir une chaîne de caractères en langage C, il suffit de définir un tableau de


caractères. La syntaxe de déclaration d’une chaîne de caractères :

char Nom_de_chaine[dim] ; // la taille de la chaîne est fixée à l’avance

3.2.3 Initialisation d’une chaîne de caractères :

Les tableaux de caractères peuvent être initialisés dans l’instruction de déclaration de la


façon suivante:
char chaîne[10]={‘B’, ‘o’, ‘n’, ‘j’, ‘o’, ‘u’, ‘r’,’\0’} ;
Vous pouvez aussi utilisez la chaîne littérale, séquence de caractères entre guillemets, qui est
plus facile à écrire et à lire
char chaine[10]= "Bonjour " ;
dans ce cas, le compilateur ajoute automatiquement le caractère nul à la fin de la chaîne. De
même, si la taille du tableau n’a pas été indiquée, le compilateur la calculera.
La ligne suivante, par exemple, crée et initialise un tableau de huit éléments :
char chaîne[]= "Bonjour " ;
Remarque
le caractère nul permet aux fonctions qui manipulent des chaînes de caractères de
connaître la longueur de la chaîne. Si vous l’avez oublié, la fonction n’a aucun autre
moyen de déterminer la fin de la chaîne, elle va continuer à traiter les données en mémoire
tant qu’elle ne rencontre pas de caractère nul.

20
Langage C

3.2.4 Quelques fonctions de manipulation des chaînes de caractères :

3.2.4.1 Lecture des chaînes de caractères :


La fonction usuel scanf() :
Soit un tableau de caractère déclaré par :
char nom[30] ;
L’instruction scanf("%S ",nom) ; /*ou scanf("%S ",&nom[0]) ;*/
Permet de lire une suite de caractère au clavier et les ranger dans le tableau nom en
commençant à partir de nom[0] et en ajoutant automatiquement, à la suite, un caractère de fin
de chaîne (‘\0’).

Vous pouvez lire plusieurs chaînes avec la même fonction, les règles précédentes
s’appliqueront pour chaque chaîne. Par exemple :
Scanf("%S %S %S " , S1,S2,S3);
Si vous tapez Janvier février mars, en réponse à cette instruction S1 sera égal à Janvier, S2 à
février et S3 à mars.
Si vous tapez septembre en réponse à l’instruction suivante :
Scanf("%3S %3S %3S »,S1,S2,S3);
Les valeurs de S1, S2 et S3 seront respectivement sep, tem et bre
La fonction usuel gets() :
La fonction gets() lit une chaîne de caractères entrée au clavier par l’utilisateur, quand cette
fonction est appelée, elle lit tous ce qui est tapé au clavier sans sauter aucun délimiteurs (les
espaces sont lus comme les autres caractères), jusqu’à ce que l’utilisateur enfonce la touche de
retour à la ligne (touche Entrée). La fonction ne prend pas en compte cette touche, ajoute un
caractère nul ‘\0’ en fin de chaîne et renvoie la chaîne au programme appellent.
Pour un tableau de caractères déclaré comme suit : char nom[30] ;
La syntaxe est : gets(nom) ;

3.2.4.2 Affichage de chaînes de caractères :


Un programme qui manipule des chaînes de caractères a souvent besoin de les afficher à
l’écran. Les deux fonctions utilisées sont printf() et puts().(inclure le fichier en-tête <stdio.h>)
La fonction printf()
De même, l’instruction Printf ("%S ",nom) va afficher à l’écran les caractères trouvés dans le
tableau nom à partir de nom[0] et s’interrompe à la rencontre du caractère de fin de chaîne.
La fonction puts()
Comme printf() mais avec la syntaxe suivante :
Puts(nom) ;

3.2.4.3 Fonctions permettant la manipulation des chaînes:


Les bibliothèques fournies avec les compilateurs contiennent de nombreuses fonctions de
traitement des chaînes de caractères. En voici quelques exemples qui appartiennent à la
bibliothèque <string.h>
La fonction strcpy() :
La fonction strcpy() (Abréviation de String Copy) permet de recopier une chaîne d’un endroit
à un autre :
Syntaxe :
Strcpy(destination,source) ;

21
Langage C

Cette fonction permet de recopier la chaîne source dans la chaîne destination. Il est nécessaire
que la taille du tableau réservé pour la chaîne destination soit suffisante pour accueillir la
chaîne à recopier.
Exemple :
Echanger les lieux de deux mots : mot1 et mot2 :
Pour cela on a besoin d’une troisième adresse, c’est le tableau mot.
#include <stdio.h>
#include <string.h>
#define LG_mot 30
void main (){
char mot1[LG_mot+1] ;
char mot2[LG_mot+1] ;
char mot[LG_mot+1] ;
printf("donnez deux mots:\n ") ;
scanf("%s %s",mot1,mot2) ;
{strcpy(mot,mot1);
strcpy(mot1,mot2);
strcpy(mot2,mot);}
printf("voici les deux mots permutés: %s %s",mot1,mot2) ;
}

La fonction strlen() :
La fonction strlen() (Abréviation de string lenght) permet de connaître le nombre de
caractères que contient une chaîne.
Syntaxe :
Pour un tableau de caractères déclaré comme suit :
char mot[LG_mot+1] ;
strlen(mot) renvoie le nombre de caractères de la chaîne existante dans le tableau.

3. 3 Les tableaux multidimensionnels


Se sont des tableaux qui contiennent des tableaux.
Définition
Un tableau multidimensionnel se définit de la manière suivante :
Type Nom_du_tableau[a1][a2][a3]……….[aN] ;

 chaque élément entre crochet désigne le nombre d’éléments dans chaque dimension
 Le nombre de dimension n’est pas limité.

Exemple :
int Tableau[3][4] ; correspondent aux matrices en mathématiques et définie un tableau
d’entiers a deux dimensions(3 lignes, 4 colonnes).

3.3.1 Initialisation des éléments


3.3.1.1 Initialisation individuelle de chaque élément.
Exemple :
int Tableau[3][4] ;
Tableau[0][0]=2 ;Tableau[0][1]=3 ;…

22
Langage C

3.3.1.2 Initialisation grâce a des boucles :


Il faut faire des boucles imbriquées correspondant chacune à un indice d’une dimension.

Exemple :
int Tableau[3][4] ;
int i,j ;
for (i=0;i<3;i++)
for (j=0;j<4;j++)
Tableau[i][j]=0 ;

3.3.1.3 Initialisation a la définition :


Syntaxe

Type Nom_du_tableau[Taille1][Taille2]……..[TailleN] ={a1,a2,a3,…};

Les valeurs sont attribués aux éléments successifs en incrémentant d’abord les indices de
droite, c'est-à-dire pour un tableau a deux dimensions [0][0],[0][1],[0][2]…..puis [1][0]
etc.…..

23
Langage C

Chapitre 4

LES POINTEURS

4.1 Notion de Pointeur

4.1.1 Intérêts des Pointeurs :


 Ils permettent de définir des structures dynamiques, c'est-à-dire qui évoluent au cours
de l’exécution (par opposition aux structures de données statiques dont la taille est
figée à la définition)
 Les tableaux ne permettent de stocker qu’un nombre fixé d’éléments de même type.
En stockant des pointeurs dans les cases d’un tableau, il sera possible de stocker des
éléments de tailles diverses
…..

4.1.2 Définition et déclaration d’un pointeur


Un pointeur est une variable ou une constante dont la valeur est une adresse mémoire.
L'adresse d'un objet est indissociable de son type. On pourra se définir par exemple des
pointeurs de caractères, des pointeurs d'entiers voire des pointeurs d'objets plus complexes.
Une variable de type pointeur se déclare à l'aide de l'objet pointé précédé du symbole *
(opérateur d'indirection).

Syntaxe :
Nom_type *ptr ;
Nom_type désigne le type de la variable
ptr : nom du pointeur
(*) c’est l’opérateur d’indirection qui indique que le pointeur ptr pointe sur la variable de type
(nom_type)

Exemple:
char *pc; pc est un pointeur pointant sur un objet de type char
int *pi; pi est un pointeur pointant sur un objet de type int
float *pr; pr est un pointeur pointant sur un objet de type float .

4.1.3 Les opérateurs & et *


L’opérateur & est utilisé pour afficher l’adresse d’une variable.
Syntaxe: &var /*retourne l’adresse de la variable de nom var*/.
Exemple
int i=2 ;
printf(" voici i :d\n ",i) ;
printf(" voici son adresse en hexadécimale : %x\n ",&i) ;

24
Langage C

Après avoir déclaré un pointeur il faut l’initialiser. Pour initialiser un pointeur, la syntaxe est
la suivante :
Nom_du_pointeur=NULL ; ou :
Nom_du_pointeur=&nom_de_la_variable_pointee ;

Exemple :
int rt=100 ;
int *P_rt=NULL ;
1004
NULL 100
P_rt rt
Pour stocker l’adresse de rt dans la variable P_rt selon l’instruction d’affectation d’adresse en
utilisant l’opérateur d’adresse &.
P_rt = & rt ; //on dit que P_rt pointe sur rt
D’où le schéma suivant :
1004
1004 100
P_rt rt

Une fois un pointeur affecté avec l’adresse d’une variable, ce pointeur peut être utilisé pour
accéder aux cases mémoires correspondant à la variable à laide de l’opérateur * (valeur de la
variable) :
Exemple
int rt=100, p ;
int *P_rt ;
P_rt =&rt ;
p=* P_rt ; /* affecte à p la valeur désignée par * P_rt c-à-d ici la valeur de rt*/
* P_rt =30 ; /*affecte à l’entier pointé par P_rt la valeur 30 ceci équivalent à rt=30 */.

4.2 Pointeurs et tableaux


Jusqu’à maintenant, lors de la déclaration d’un tableau, il fallait préciser les dimensions, soit
de façon explicite :
int tab[3][2] ;
soit de façon implicite :
int tab[][] = { {0 , 1 } , {2 , 3 } , {4 , 5 } } ;
Dans les 2 cas, on a déclaré un tableau de (3 fois 2) entiers.
Mais si l’on veut que le tableau change de taille d’une exécution à une autre, cela nous oblige
à modifier le programme et à le recompiler à chaque fois, ou bien à déclarer un tableau de
1000 fois 1000 entiers et n’utiliser que les n premières cases mais ce serait du gâchis.
Pour éviter cela, on fait appel à l’allocation dynamique de mémoire : au lieu de réserver de
la place lors de la compilation, on la réserve pendant l’exécution du programme, de façon
interactive.
4.2.1 Pointeur et tableau à une dimension

Tout tableau en C est en fait un pointeur constant. Dans la d´eclaration


int tab[10];
tab est un pointeur constant (non modifiable) dont la valeur est l’adresse du premier ´el´ement
du tableau. Autrement dit, tab a pour valeur &tab[0]. On peut donc utiliser un pointeur
initialis´e `a tab pour parcourir les ´el´ements du tableau.
#define N 5

25
Langage C

int tab[5] = {1, 2, 6, 0, 7};


main()
{
int i;
int *p;
p = tab;
for (i = 0; i < N; i++)
{
printf(" %d \n",*p);
p++;
}
}
On accède à l’élément d’indice i du tableau tab grâce à l’opérateur d’indexation [], par
l’expression tab[i]. Cet opérateur d’indexation peut en fait s’appliquer à tout objet p de
type pointeur. Il est lié à l’opérateur d’indirection * par la formule
p[i] = *(p + i)
Pointeurs et tableaux se manipulent donc exactement de même manière. Par exemple, le
programme précédent peut aussi s’écrire
#define N 5
int tab[5] = {1, 2, 6, 0, 7};
main()
{
int i;
int *p;
p = tab;
for (i = 0; i < N; i++)
printf(" %d \n", p[i]);
}
Remarque
La déclaration d’un tableau entraîne automatiquement la réservation de places en mémoire.
Ce n’est pas le cas lorsque l’on déclare un pointeur. Il faut alors utiliser une fonction
d’allocation dynamique comme malloc.

La fonction malloc()
Pour l’utiliser il faut inclure la bibliothèque <stdlib.h> en début de programme.
malloc( N ) renvoie l’adresse d’un bloc de mémoire de N octets libres (ou la valeur NULL s’il
n’y a pas assez de mémoire).
Cette fonction retourne par défaut un pointeur de type char * pointant vers un objet de taille N
octets.
Pour initialiser des pointeurs vers des objets qui ne sont pas de type char, il faut convertir le
type de la sortie de la fonction malloc à l’aide d’un cast.
Exemple :
int *p ;
p = (int*)malloc(800) ; /* fournit l’adresse d’un bloc de 800 octets libres */
/* et l’affecte au pointeur p */

L’opérateur sizeof()
D’une machine à une autre, la taille réservée pour un int, un float,... change. Si nous voulons
réserver de la mémoire pour des données d’un type dont la grandeur varie d’une machine á
l’autre, nous avons besoin de la taille effective d’une donnée de ce type.

26
Langage C

L’opérateur sizeof nous fournit ce renseignement.


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

Allocation dynamique pour un tableau à 1 dimension


On veut réserver de la place pour un tableau de n entiers, où n est lu au clavier :
int n ;
int *tab ;
printf("taille du tableau :nn") ;
scanf("%d", &n) ;
tab = (int *)malloc(n*sizeof(int)) ;

Fonction calloc :
La fonction calloc de la librairie stdlib.h a le même rôle que la fonction malloc mais elle
initialise en plus l’objet pointé *p à zéro. Sa syntaxe est
calloc(nb-objets,taille-objets)
Ainsi, si p est de type int*, l’instruction
p = (int*)calloc(N,sizeof(int));
est strictement équivalente à
p = (int*)malloc(N * sizeof(int));
for (i = 0; i < N; i++)
*(p + i) = 0;
L’emploi de calloc est simplement plus rapide.
4.2.2 Pointeur et tableau à plusieurs dimensions
Un tableau à deux dimensions est, par définition, un tableau de tableaux. Il s’agit donc en fait
d’un pointeur vers un pointeur. Considérons le tableau à deux dimensions défini par :
int tab[M][N];
tab est un pointeur, qui pointe vers un objet lui-même de type pointeur d’entier. tab a une
valeur constante égale `a l’adresse du premier élément du tableau, &tab[0][0]. De même
tab[i], pour i entre 0 et M-1, est un pointeur constant vers un objet de type entier, qui est
le premier élément de la ligne d’indice i. tab[i] a donc une valeur constante qui est égale à
&tab[i][0].
Exactement comme pour les tableaux à une dimension, les pointeurs de pointeurs ont de
nombreux avantages sur les tableaux multi-dimensionnés.
On déclare un pointeur qui pointe sur un objet de type type * (deux dimensions) de la
même manière qu’un pointeur, c’est-`a-dire
type **nom-du-pointeur;
Par exemple, pour crèer avec un pointeur de pointeur une matrice à k lignes et n colonnes à
coefficients entiers, on écrit :
main()
{
int k, n;
int **tab;
tab = (int**)malloc(k * sizeof(int*));
for (i = 0; i < k; i++)
tab[i] = (int*)malloc(n * sizeof(int));
....

27
Langage C

La première allocation dynamique réserve pour l’objet pointé par tab l’espace-mémoire
correspondant à k pointeurs sur des entiers. Ces k pointeurs correspondent aux lignes de la
matrice.
Les allocations dynamiques suivantes réservent pour chaque pointeur tab[i] l’espace-mémoire
nécessaire pour stocker n entiers.
Si on désire en plus que tous les éléments du tableau soient initialisés à zéro, il suffit de
remplacer l’allocation dynamique dans la boucle for par
tab[i] = (int*)calloc(n, sizeof(int));
la fonction free()
pour libérer (désallouer) l’espace mémoire déjà alloué par la fonction malloc en utilise la
fonction free().
Exemple :
for (i = 0; i < k; i++)
free(tab[i]);
free(tab);

4.3 Pointeurs et chaînes de caractères


On a vu précédemment qu’une chaîne de caractères était un tableau à une dimension d’objets
de type char, se terminant par le caractère nul ’\0’. On peut donc manipuler toute chaîne de
caractères à l’aide d’un pointeur sur un objet de type char.
Pour ce passer du tableau, il faut pouvoir s’allouer de la place mémoire, définir un pointeur en
début de chaîne et placer le caractère nul à la fin. La méthode consiste à utiliser la fonction
malloc() qui alloue la mémoire au moment de l’exécution du programme

Syntaxe
#include <stdlib.h>
char * nom_pointeur=malloc(taille) ;

Exemple :
char *ptr ;
Ptr=malloc(100) ; ou encore :
Ptr=(malloc(100*sizeof(char)) ;
Ptr pointe maintenant sur un bloc de 100 octets qui peut recevoir une chaîne de caractère.

4.4 Opérations possibles sur les pointeurs :

Incrémentation des pointeurs :


On constate qu’un pointeur devra être incrémenté de 2 pour accéder aux éléments successifs
d’un tableau d’entiers et de 4 pour les éléments d’un tableau de flottant. En général de la
valeur Sizeof(type) pour un tableau d’un certain type.
Comme C, connaît le type de données du tableau à partir de sa déclaration, il suffit que
l’utilisateur donne l’instruction :
Ptr_type+=n pour pointer vers le nième éléments, et C incrémente automatiquement le
pointeur de (n*Sizeof(type)).
Exemple:
Pour les entiers : Ptr_int+=4 implique C incrémente le pointeur de 8 pour qu’il pointe sur le
4ème élément.

28
Langage C

Affectation
On peut affecter une valeur à un pointeur, c’est une adresse précédée par l’opérateur &.
Différence :
Entre deux pointeurs de même type (si vous avez deux pointeurs sur un même tableau, le
résultat de leur soustraction correspond au nombre d’éléments qui les séparent).
Comparaison :
= = , != , > , < , >= et <=
Ne sont validés que pour deux pointeurs de même tableau.

Remarques
 Eviter d’effectuer des opérations mathématiques comme des divisions, des
multiplications ou des modulos
 pour incrémenter la valeur d’un pointeur (exemple int *x), il faut utiliser :
(*x)++ et nom pas *x++

29
Langage C

Chapitre 5

Les Fonctions en C
On appelle fonction ou sous programme, une partie de code source qui permet d’effectuer un
ensemble d’instructions par simple appel de la fonction.
Les fonctions permettent d’exécuter dans plusieurs parties du programme une série
d’instructions, cela permet une simplicité du code et donc une taille de programme minimale.

5.1 Définition d’une fonction


La définition d’une fonction consiste en l’écriture du code de la fonction.
Une fonction comporte deux parties :
 La signature de la fonction consiste au type et au nom de la fonction suivis par les
types et les noms des paramètres.
 Le corps de la fonction contient des déclarations de variables locales et un ensemble
d’instructions qui indiquent ce que la fonction doit faire. Il est sous forme de bloc.
Syntaxe
Type_f nom_f (typ1 p1, ………….,typn pn) //signature de la fonction
{
Instructions //corps de la fonction
}
Avec :
type_f : type de la fonction
nom_f : nom de la fonction
typi (1<i<=n) : type du ieme paramètre de la fonction
pi (1<i<=n) : nom du ieme paramètre (argument) de la fonction.

Exemple de définition de fonction


int plus(int a,int b)
{ int A;
A=a+b ;
return A ; }

Remarques :
1) L’imbrication d’une fonction n’est pas autorisée en C, une fonction ne peut pas être
déclarée à l’intérieure d’une autre fonction. Par contre une fonction peut appeler une
autre fonction
2) Si la fonction ne renvoie aucune valeur, on la fait précéder du mot-clé void
syntaxe : void nom_fonction(arguments)
3) Fonctions renvoyant une valeur au programme et sans d’arguments
Syntaxe : Type nom_fonction(void)
4) Si aucun type de données n’est précisé, le type int est pris par défaut
5) Les arguments sont facultatifs, mais s’il n’y a pas d’arguments les parenthèses doivent
rester présentes.

30
Langage C

Instruction return:
Le rôle de l’instruction return dans la fonction est double : d’une part, il précise la valeur qui
sera fournie en résultat, d’autre part, il met fin à l’exécution des instructions de la fonction.

Exemple : (fonction cube)


float cube(float x) /*en-tête de la fonction cube (Attention pas de ;)*/
{ float y ; /* variable local de la fonction cube*/
y=x*x*x ;
return y ; /* retour du résultat du cube de x*/
}
float : type du résultat de retour de la fonction
float x : type et nom du paramètre formel
cube : nom de la fonction
L’instruction return peut mentionner non seulement un nom de la variable, mais en fait
n’importe quelle expression.

Exemple :
float cube(float x)
{ return(x*x*x) ; } /* les ( ) ne sont pas indispensables*/

L’instruction return apparaît comme la dernière de la définition de notre fonction, mais il est
théoriquement possible de placer plusieurs instructions return dans une même fonction
Exemple :
float max(float a, float b)
{ if (a>b) return a;
else return b;
}

5.2 Variables locales et globales :


Une variable connue uniquement dans une fonction ou dans main() est une variable locale.
Une variable connue dans tout le programme est une variable globale(déclarée au début du
programme et en dehors de toute fonction y compris main).
Une variable locale à une fonction n’est accessible que par cette fonction. Cependant, une
variable global est accessible à toutes les fonctions (y compris le programme principal)

5.2.1 Initialisation des variables locales :


Une variable locale peut être initialisée lors de sa déclaration. Une variable locale est encore
appelée automatique. Elles perdent leurs valeurs à chaque appel à la fonction.

Exemple
int carre (int val)
{
int val_retour = 0; /* Déclaration variable locale */
val_retour = val * val;
return (val_retour);
}
void main ()
{
int val_retour = 0; /* Déclaration variable locale */

31
Langage C

val_retour = carre (2);


printf ("Le carré de 2 est : %d", val_retour);
getch ();
}
val_retour est dans les deux cas une variable locale. Bien qu'elles aient le même nom
dans la fonction main et carre, les deux variables n'ont rien à voir entre elles.

5.2.2 Initialisation des variables globales :


" Il est déconseillé d'utiliser les variables globales. "

Exemple
#include …
int val = 0; /* Déclaration variable globale */
int carre ()
{
int val_retour = 0;
val_retour = val * val;
return (val_retour);
}
void main ()
{
val = 2;
carre ();
printf ("Le carre de 2 est %d", carre ());
}

val est une variable globale.


On constate que le programme devient rapidement illisible …
5.3 Appel d’une fonction
Pour exécuter une fonction, il suffit de faire appel à elle en écrivant son nom suivie d’une
parenthèse ouverte (éventuellement des arguments) puis d’une parenthèse fermée
Syntaxe
Nom_De_La_Fonction(arguments) ;
Exemple
#include<stdio.h>
/* Déclaration des variable globales*/
int x,y ;
void lire()
{
printf("Entrer les valeur à sommer : ") ;
scanf("%d %d ",&x,&y) ;
}
int somme()
{
return(x+y) ;
}
void main()
{clrscr() ;
lire() ; /* Appel de la fonction lire*/
printf("\n la somme de %d et %d est égal à %d ",x,y,somme()) ;

32
Langage C

getch() ;
}
5.4 Prototype d’une fonction
Le prototype d’une fonction est une description d’une fonction qui est définie plus loin dans
le programme. Cette description permet au compilateur de vérifier la validité de la fonction à
chaque fois qu’il la rencontre dans le programme, en lui indiquant sa signature (le type de
valeur renvoyée par la fonction, le nom de la fonction, les types d’arguments).
Contrairement à la définition de la fonction, le prototype n’est pas suivi du corps de la
fonction (contenant les instructions à exécuter), et ne comprend pas le nom des paramètres
(seulement leur type).
Un prototype de fonction a la syntaxe suivante :
Type Nom_Fonction(type1,type2,…) ;
Remarques :
- Le prototype est une instruction, il est donc suivi d’un point
virgule ;
- Si la fonction n’a aucun argument, la liste des argument est
remplacée par void. Exemple : int fonct(void)
- Le prototype d’une fonction doit être utilisé, lorsque la
définition d’une fonction est placée après les fonctions qui
l’utilisent.
Exemples de prototypes :
void affiche_car(char,int) ;
int somme (int,int) ;
Exemple d’utilisation de prototype
#include <stdio.h>
int x,y ;
void lire (void) ; /*prototype de la fonction lire*/
int somme(void) ; /*prototype de la fonction somme*/
void main()
{
clrscr() ;
lire() ;
printf (" \n la somme de %d et %d est égal à %d",x,y,somme()) ;
getch() ;
}
void lire()
{printf(" Entrer les valeur à sommer : ") ;
scanf("%d %d",&x,&y) ;
}
int somme()
{return(x+y) ;}

5.5 Transmission des paramètres d’une fonction:


5.5.1 Passage des paramètres par valeurs
En C, tous les arguments sont passés par valeur. Les valeurs de ces arguments ne changent
pas après l’appel de la fonction
Exemple : (échange de deux entiers) :
void echange(int, int) ;
main()

33
Langage C

{ int i=2,j=3 ;
echange(i,j) ;
}
void echange(int a,int b)
{ int k /*variable intermidiare*/
k=a;
a=b;
b=k;
}
À l’exécution on a:
Avant l’appel les valeurs sont i=2 et j=3
A la fin de la fonction les valeurs sont 3 et 2
Après l’appel les valeurs sont i=2 et j=3
Il n’y a que recopie des valeurs de i et j (2 et 3) vers les variables locales de la fonction mais
après l’appel il n’y a aucune modification de i et j.

5.5.2 Passage des arguments par adresse : (Utilisation des pointeurs)


La seule façon de modifier en C, les valeurs des paramètres d’une fonction est l’utilisation
des pointeurs.
En effet, l’utilisation des pointeurs comme arguments permettent de modifier les valeurs des
variables pointés après l’appel des pointeurs.
Exemple :
Le même exemple que pour les paramètres passes par valeur mais en utilisant des adresses :
void echange(int *, int*) ;
main()
{ int i=2,j=3 ;
echange(&i,&j) ;
}
void echange(int *a,int *b)
{ int k /*valeur intermidiare*/
k=*a;
*a=*b;
*b=k;
}

À l’exécution on a:
Avant l’appel les valeurs sont i=2 et j=3
A la fin de la fonction les valeurs sont 3 et 2
Après l’appel les valeurs sont 3 et 2
5.6 Les Macros-Fonctions
Les macro fonctions sont des instructions prédéfinis en C. dans un programme source, une
macro fonction substitue à une instruction ou une séquence d’instructions du langage C. le
traitement des macro fonctions se fait par le compilateur.
La définition de macros grâce au symbole #define
Exemple :
#define carre(a) a*a le préprocesseur remplacera dans la suite carre(x) par x*x
#define SUP(a,b) (a>b) ?a :b

34
Langage C

Chapitre 6

Structures et Unions

6.1 Les structures


Un tableau permet de regrouper des éléments de même type, c'est-à-dire codés sur le même
nombre de bit et de la même façon. Toutefois, il est généralement utile de pouvoir rassembler
des éléments de type différents
Les structures permettent de remédier à cette lacune des tableaux, en regroupant des objets
(des variables) au sein d’une entité repérée par un seul nom de variable.
Les objets contenus dans la structure sont appelés champs de la structure.

6.1.1 Déclaration et définition d’une structure

Une structure est un objet composé de plusieurs champs qui sert à représenter un concept.

Le langage C permet de déclarer une structure de la façon suivante :


struct nom_de_structure
{ Type1 nom_champ1 ;
Type2 nom_champ2 ;
Type3 nom_champ3 ;
….. ….. ……. ;
TypeN nom_champN ;
};

Les types des champs type1, type2,…, typeN peuvent être différents ou identiques.

Remarques :
• la dernière accolade doit être suivi d’un point virgule
• Les champs peuvent être de n’importe quel type hormis le type de la structure dans
laquelle elles se trouvent

Exemples :

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

struct Mastructure
{ int Age;
char Nom[12];
float Moyenne;
struct Autre structure StrucBis ;

35
Langage C

/*en considérant que la structure AutreStructure est définie*/


};

Par contre la structure suivante est incorrecte


struct Mastructure
{ int Age ;
char Age ;
struct Mastructure StructBis ;
};
Il ya deux raisons à cela:
. Le nom de variable Age n’est pas unique
. Le type de donnée struct Mastruture n’est pas autorisé.

Déclaration de variables d’une structure

• Déclaration simultanée de structure et de variables

Dans ce cas, on groupe la déclaration de la structure et des variables associées de la façon


suivante :

struct nom_structure
{ Type1 nom_champ1 ;
Type2 nom_champ2 ;
Type3 nom_champ3 ;
….. ….. ……. ;
TypeN nom_champN ;
}var1, var2, …… ;
var1, var2, ….. Sont des variables associées à la structure nom_structure

Exemple :
struct date
{int jour ;
int mois ;
int an ;} départ,arrivée,naissance ;

• Déclaration séparée de structure et de variables

Il est possible de déclarer séparément la structure et les variables associées. Dans ce cas, il
faut d’abord déclarer la structure puis les variables après.

Syntaxe de déclaration de variable structure en C :

struct nom_struct var1, var2,…………….;

Exemple :
Une fois la structure date déclarée, ont peut écrire les déclarations suivantes :
struct date départ, arrivée, naissance ;

Utilisation de structures
Les structures peuvent être manipulées champ par champ ou dans leur ensemble.

36
Langage C

• Utilisation champ par champ

Chaque champ d’une structure peut être manipulé comme n’importe quelle variable du type
correspondant. La désignation de champ se note en faisant suivre le nom de la variable
structure d’un point puis du nom de champ.

La syntaxe : nom_de _variable.nom_du_champ


Exemple :
En utilisant la déclaration
struct date
{ int jour ;
int mois ;
int an ;
} départ,arrivée,naissance ;
Pour accéder aux champs des variables départ, on écrira :
départ.jour =16 ; départ.mois=3 ; départ.an=2012;
arrivée.jour=28; arrivée.mois=5; arrivée.an=2012;

• Utilisation globale d’une structure

Il est possible d’affecter à une structure le contenu d’une autre structure défini à partir du
même modèle. Ainsi si la structure s1 et s2 sont définie suivant le même modèle, nous
pouvons écrire s1=s2 ;

Exemple :
Si départ et arrivée sont deux variables de la structure date déjà définie nous pouvons écrire
départ=arrivée ;

Remarque :
Lorsqu’on dispose d’un pointeur sur une structure, l’écriture diffère un peu en s’écrivant :
Nom_de_variable pointeur->nom_de_champ; où la flèche est construite avec le signe
moins (-) et le signe supérieur (>).
Exemple :
struct date
{ int jour ;
int mois ;
int an ;} ;
struct date date1,*p ;
date1 est une variable structure de type date.
p est un pointeur sur une variable structure de type date
On peut écrire
date1.mois=12 ;
P->jour=15 ; /*equivalent à (*p).jour=15 ; */

Déclaration de type synonymes : typedef

La déclaration typedef permet de définir des « types synonymes ». Elle s’applique à tous les
types et en particulier aux structures.

Syntaxe : typedef type nouveau-type ;

37
Langage C

Exemples :
Typedef int entier ; : signifie que entier est synonyme de int. Dans ce cas :
int n,p ; est équivalent à entier n,p ;

Application aux structures :


typedef struct identificateur
{
Type1 nom_champ1 ;
Type2 nom_champ2 ;
Type3 nom_champ3 ;
….. ….. ……. ;
TypeN nom_champN ;
} nom_str1, nom_str2, …… ;

Une définition de ce type sert à définir un modèle de structure associé aux structures
nom_str1,nom_str2,…………… ;

Exemples :
Typedef struct temps
{ int champ1 ;
int champ2 ;
int champ3 ;
}date, time ;
date et time (appelé des images de structures) sont des types de structures équivalents à
struct temps.

Typedef struct temps


{ int champ1 ;
int champ2 ;
int champ3 ;
}*date ;
Date est un type équivalent à struct temps*

2 Les unions
2.1 Définition :
L’union est la déclaration de différentes variables qui occupent toutes la même place en
mémoire. Le système alloue un emplacement mémoire tel qu’il pourra contenir la variable de
plus grande taille
La syntaxe de déclaration d’une union est la suivante :
union nom_union
{ Type1 var1 ;
Type2 var2 ;
Type3 var3 ;
….. ……. ;
TypeN varN ;
} u;
Cette déclaration réserve un emplacement qui pourra contenir l’une des variables var1, var2,
…. varN.
2.2 Accès aux champs
Pour accéder à l’une des variables de l’union, on utilise la syntaxe :

38
Langage C

nom_union.nom_variable ;
Exemple :
union u {
char c ;
float f ;
long l ;}j;
j.c=’a’;
j.f=15.4; /* après cette déclaration, on a plus le caractère ‘a’ dans c */

39
Langage C

Chapitre 7
La gestion des fichiers
Le fichier est le seul moyen utilisé pour stocker les informations sur ordinateurs et
sauvegarder des résultats nécessitant une réutilisation ultérieure.
Le terme fichier, désigne ici un ensemble d’informations, situé sur une mémoire de masse
(disque dure, disquette, CD ROM,…). Néanmoins, tous les périphériques, qu’ils soient
d’archivage (disque, disquette, …) ou de communication (clavier écran imprimante,…)
peuvent être considérés comme un cas particulier de fichiers.
Schéma général de gestion d’un fichier :
Déclaration
Ouverture
Manipulation (Lecture/écriture)
Fermeture
7.1 Ouverture et fermeture d’un fichier
7.1.1 Déclaration d’un fichier
Pour pouvoir utiliser un fichier (l’ouvrir, écrire, lire,…) il faut déclarer un pointeur sur un
objet de type FILE (le type FILE est une structure définie dans le fichier <stdio.h>
Syntaxe : FILE *nom_fichier ;
Exemple : FILE *f ;
Cette déclaration ne réserve qu’un emplacement pour un pointeur. C’est la fonction fopen qui
créera effectivement une telle structure et qui en fournira l’adresse en résultat.
7.1.2 Ouverture d’un fichier
Pour travailler sur un fichier, il est nécessaire de l’ouvrir (association d’un objet extérieur ( le
fichier) au programme en cours d’exécution. La fonction fopen permet de réaliser l’ouverture
d’un fichier selon la syntaxe suivante :
FILE * nom_fichier ;
nom_fichier =fopen(nom_physique_du_fichier,Mode);
nom_physique_du_fichier : chaîne de caractère constante indiquant le nom du fichier sur le
disque.
Mode : chaîne de caractère constante indiquant le mode d’ouverture du fichier (lecture,
écriture/ajout) et (binaire/texte).
La fonction fopen retourne un pointeur sur un objet de type FILE, elle retourne l’adresse du
fichier ouvert ou un pointeur NULL si le fichier n’a pas pu être ouvert (problèmes d’existence
de fichiers ou de droits d’accès).
Exemple: f= fopen("c:\\test.txt", "rt");
Si on n’utilise pas le caractère t dans le mode d’ouverture. "r" implique fichier texte
implicitement.
Le type d’ouverture est spécifié à partir d’un mode de base et de compléments
"r" le fichier est ouvert en lecture. Si le fichier n’existe pas, la fonction ne le crée pas.
"w " le fichier est ouvert en écriture. Si le fichier n’existe pas, la fonction le crée. Si le fichier
existe la fonction le vide.
"a" le fichier est ouvert en ajout. Si le fichier n’existe pas, la fonction le crée. Les écritures
auront lieu à la fin du fichier.
Le type d’ouverture peut être agrémenté de deux caractères qui sont :
"b" le fichier est considéré en mode binaire. Il peut donc contenir des données qui sont
transférées sans interprétation par les fonctions de la bibliothèque.
"+ " le fichier est ouvert dans le mode complémentaire du mode de base.
Par exemple s’il est ouvert dans le mode “r+“ cela signifie qu’il est ouvert en mode lecture et
plus, soit lecture et écriture.

40
Langage C

La combinaison des modes de base et des compléments donne les possibilités suivantes :
“r+“ le fichier est ouvert en lecture plus écriture. Si le fichier n’existe pas, la fonction ne le
crée pas. Le fichier peut être lu, modifié et agrandi.
“w+“ le fichier est ouvert en écriture plus lecture. Si le fichier n’existe pas, la fonction le
crée. Si le fichier existe, la fonction le vide. Le fichier peut être manipulé en écriture et
lecture.
“a+“ le fichier est ouvert en ajout plus lecture. Si le fichier n’existe pas, la fonction le crée.
Les écritures auront lieu à la fin du fichier. Le fichier peut être lu.
“rb“ le fichier est ouvert en lecture et en mode binaire. Si le fichier n’existe pas, la fonction ne
le crée pas.
“wb“ le fichier est ouvert en écriture et en mode binaire. Si le fichier n’existe pas, la fonction
le crée. Si le fichier existe, la fonction le vide.
“ab“ le fichier est ouvert en ajout et en mode binaire. Si le fichier n’existe pas, la fonction le
crée. Les écritures auront lieu à la fin du fichier.
“r+b“ou “rb+“ le fichier est ouvert en lecture plus écriture et en mode binaire. Si le fichier
n’existe pas, la fonction ne le crée pas. Le fichier peut être lu, modifié et agrandi.
“w+b“ ou “wb+“ le fichier est ouvert en écriture plus lecture et en mode binaire. Si le fichier
n’existe pas, la fonction le crée. Si le fichier existe, la fonction le vide. Le fichier peut être
écrit puis lu et écrit.
“a+b“ ou “ab+“ le fichier est ouvert en ajout plus lecture et en mode binaire. Si le fichier
n’existe pas, la fonction le crée. Les écritures auront lieu à la fin du fichier.
7.1.3 Fermeture d’un Fichier :
fclose(nom_fichier) ;
Exp : fclose(f) ;
Exemple : un programme qui se contente d’afficher si un fichier de nom lu par le clavier a pu
être ouvert ou non.
#include <stdio.h>
void main ()
{ FILE *f;
char nom_f[40] ;
printf(" donner le nom du fichier : ") ;
gets(nom_f ) ;
f=fopen(nom_f, " r ") ;
if(f==NULL)
printf(" impossible d’ouvrir le fichier %s\n ",nom_f);
else
printf(" %s a été ouvert avec succés ", nom_f) ;
}

7.2 Accès au contenu d’un fichier


Une fois le fichier ouvert, le langage c permet plusieurs types d’accès à un fichier :
• par caractère,
• par ligne,
• par enregistrement,

41
Langage C

• par données formatées,


Dans tous les cas, les fonctions d’accès au fichier (sauf les opérations de déplacement) ont un
comportement séquentiel. L’appel de ces fonctions provoque le déplacement du pointeur
courant relatif au fichier ouvert. Si le fichier est ouvert en mode lecture, les opérations de
lecture donnent une impression de consommation des données contenues dans le fichier
jusqu’à la rencontre de la fin du fichier.
7.2.1 Accès par caractère

Ecriture caractère par caractère


Les fonctions suivantes permettent l’écriture caractère par caractère dans un fichier :
int fputc(int, FILE *) ; écrit dans le fichier associé décrit par le second argument un
caractère spécifié dans le premier argument. Ce caractère est converti en un unsigned char ;
Le premier argument contient le caractère à écrire
Le second contient le descripteur de fichier ouvert ;
Retour : la valeur du caractère écrit mise dans un entier sauf en cas d’erreur ;
Condition d’erreur : en cas d’erreur d’écriture, la fonction retourne EOF
Exemple :
fputc(‘A’,f) ;
char c=’a’ ; fputc(c,f) ;
int putc(int, FILE*) ; cette fonction est identique à fputc() mais elle est réalisée par une macro
définie dans <stdio.h>.
Lecture
Les fonctions suivantes permettent la lecture caractère par caractère dans un fichier :
int fgetc(FILE *fich) ; lit un caractère dans le fichier associé.
fich : le nom du fichier ouvert ;
Elle retourne la valeur du caractère lu et la met dans un entier. A la rencontre de la fin de
fichier, la fonction retourne EOF
int getc(FILE *fich) ; cette fonction est identique à fgetc() mais peut être réalisée par une
macro définie dans <stdio.h>.
Exemple: Ecrire un programme qui permet d’afficher le contenu d’un fichier texte
#include<stdio.h>
main()
{
FILE *fiche;
char carlu;
fiche =fopen("fichier1.txt", "r“) ;
if (fiche != NULL)
{
printf(“OK ouverture du fichier fichier1.txt\n“) ;
printf(“le contenu du fichier fichier1.txt est:\n “) ;
while( !(feof(fiche)))
{carlu=getc(fiche) ;
putchar(carlu) ;
}}
else

42
Langage C

printf(“problème d’ouverture de fichier fichier1.txt“) ;


fclose(fiche) ;
getch() ;}

7.2.2 Accès par ligne


Comme pour les entrées-sorties sur les pseudo-fichiers standard (écran, clavier, …), il est
possible de réaliser des opérations de lecture et d’écriture ligne par ligne à l’intérieur de
fichiers ouverts.
Ecriture ligne par ligne
L’accès ligne par ligne en écriture se fait grâce à la fonction fputs
int fputs(const char* , FILE*) ; cette fonction permet d’écrire une chaîne de caractères
référencée par le premier argument dans le fichier décrit par le second argument.
Arguments :
1. le premier argument contient l’adresse de la zone mémoire qui contient les caractères à
écrire. Cette zone doit être un chaîne de caractères (terminée par un caractère nul).
Elle doit contenir un retour chariot si on veut un passage à la ligne suivante.
2. le second argument contient le descripteur de fichier ouvert dans lequel les caractères
seront écrits.

Retour :
Une valeur positive si l’écriture s’est correctement déroulée.
Condition d’erreur :
En cas d’erreur d’écriture, la fonction retourne EOF.
La fonction fputs() écrit une ligne dans le fichier. Le tableau de caractère doit être terminé par
un caractère nul (‘\0’). Il faut mettre explicitement la fin de ligne dans ce tableau pour qu’elle
soit présente dans le fichier.
Exemple :
char *s=”ma chaine”;
fputs(s,f) ;

Lecture ligne par ligne


L’accès ligne par ligne en lecture se fait grâce à la fonction fgets
char * fgets(char*, int , FILE*) ; lit une ligne de caractères dans le fichier associé, les
caractères de la ligne sont rangés dans la mémoire à partir de l’adresse donnée en argument à
la fonction. Le retour chariot est lu et rangé en mémoire. Il est suivi par un caractère nul ’\0’
de manière à ce que la ligne une fois placée en mémoire, puisse être utilisée comme une
chaîne de caractères.
Arguments :
1. adresse de la zone de stockage des caractères en mémoire,
2. nombre maximum de caractères (taille de la zone de stockage),
3. descripteur de fichier ouvert.
Retour :
Adresse reçue en entrée sauf en cas d’erreur ;
Condition d’erreur :
À la rencontre de la fin de fichier, la fonction retourne NULL et positionne les indicateurs
associés.
Exemple :

43
Langage C

fgets(chaîne,N,f) ; lit une chaîne de maximum N caractères à partir d’une seule ligne

7.2.3 Accès par enregistrement


L’accès par enregistrement permet de lire et d’écrire des objets structurés dans un fichier. Ces
objets structurés sont le plus souvent représentés en mémoire par des structures. Pour ce type
d’accès, le fichier doit être ouvert en mode binaire. Les données échangées ne sont pas traitées
comme des caractères.
L’accès par enregistrement se fait grâce aux fonctions :
size_t fread(void *Zone, size_t Taille, size_t Nbr, FILE *fp) ;
size_t fwrite(void *Zone, size_t Taille, size_t Nbr, FILE *fp) ;
Ces fonctions ont une interface homogène. Elles acceptent une liste identique d’arguments, et
retournent le même type de résultat. Les arguments sont les suivants :
1. le premier argument, appelé Zone est l’adresse de l’espace mémoire à partir duquel
l’échange avec le fichier est fait. L’espace mémoire correspondant reçoit les
enregistrements lus, ou fournit les données à écrire dans les enregistrements. il faut,
bien entendu, que l’espace mémoire correspondant à l’adresse soit de taille suffisante
pour supporter le transfert des données.
2. le deuxième argument, appelé Taille est la taille d’un enregistrement en nombre
d’octets.
3. le troisième argument, appelé Nbr est le nombre d’enregistrements que l’on désire
échanger.
4. le dernier argument, appelé fp, est un descripteur de fichier ouvert dans un mode
binaire.
Exemple : Un programme qui copie un fichier d’individus dans un autre fichier, un individu
possédant un nom, un prénom et un age
#include<stdio.h>
struct individu
{ char np[30];
int age; }indi;

char nomfs[10], nomfd[10],chaine[30];


/*nomfs: nom fichier source, nomfd: nom fichier destination*/
int taille ;
FILE *fsource, *fdestination ;
Main(){
taille= sizeof(indi) ;
printf (“\n Entrer le nom du fichier source :“) ;
gets(nomfs) ;
printf (“\n Entrer le nom du fichier destination :“) ;
gets(nomfd) ;

44
Langage C

fsource=fopen(nomfs, “rb“) ;
if (fsource==NULL)
printf(“\n impossible de créer le fichier source %s“,nomfs) ;
else
{ fdestination=fopen(nomfd,“wb“) ;
if( fdestination==NULL)
Printf (“\n impossible de créer le fichier %s“,nomfd) ;
else
{
While(!feof(fsource))
{fread(&indi,taille,1, fsource);
fwrite(&indi,taille,1,fdestination);
}}
fclose(fsource);
fclose(fdestination) ;
}
getch() ;
}

7.2.4 Accès par données formatées


La fonction d’´ecriture fprintf
La fonction fprintf, analogue à printf, permet d’´ecrire des données dans un fichier. Sa
syntaxe est : fprintf(f,"format de contrôle",expression-1, ..., expression-n)
où f est le nom logique du fichier. Les spécifications de format utilisées pour la fonction
fprintf sont les mêmes que pour printf.
La fonction de saisie fscanf
La fonction fscanf, analogue à scanf, permet de lire des données dans un fichier. Sa
syntaxe est semblable à celle de scanf :
fscanf(f,"format de contrôle",argument-1,...,argument-n)
où f est le nom logique du fichier. Les spécifications de format sont ici les mêmes que celles
de la fonction scanf.

7.3 Fonctions de positionnement


Il y a plusieurs fonctions de positionnement :
1.1.1 La fonction fseek

int fseek(FILE *fp, long int deplacement, int origine) ;cette fonction permet un accès
direct au niveau de l’octet. Elle initialise le positionnement pour la prochaine lecture. La

45
Langage C

valeur du paramètre déplacement désigne la nouvelle valeur que l’on souhaite donner au
pointeur en opérant un déplacement par rapport à origine :
- Si origine vaut 0 ou SEEK_SET, le déplacement se fera par rapport au début du
fichier.
- Si origine vaut 1 ou SEEK_CUR, le déplacement se fera par rapport au pointeur
courant (position courante)
- Si origine vaut 2 ou SEEK_END, le déplacement se fera depuis la fin de fichier

Les valeur SEEK_SET, SEEK_CUR et SEEK_END sont prédéfinies dans le fichier unistd.h
Si le système d’exploitation ne peut pas positionner le pointeur dans le fichier, la fonction
retourne -1, sinon elle retourne 0.
Exemple1 :
fseek(f,20,0) ;char c=fgetc(f) ;
Exemple2 :
fseek(f,sizeof(str)*10,0) ;
str v;
fread(&v,sizeof(str),1,f);
1.1.2 La fonction rewind
void rewind(FILE *fichier) ; cette fonction est identique à fseek(fichier,0L, 0) ; elle
positionne le pointeur au début du fichier.

7.4 Fonctions diverses sur les fichiers


Long ftell(FILE *fichier) ; cette fonction retourne la valeur de la position courante par
rapport au début du fichier. S’il y a erreur cette fonction retourne -1L
taille= ftell(fichier)
int feof(FILE *fichier) ; cette fonction (found end of file) teste si une fin de fichier (EOF) a
été détectée. La valeur retournée par feof() est différente de 0 si EOF a été détectée et elle est
égale à 0 sinon
int unlink(char *fich) ; détruit le fichier de nom fich

46

Vous aimerez peut-être aussi