Diapos Cours C

Télécharger au format pptx, pdf ou txt
Télécharger au format pptx, pdf ou txt
Vous êtes sur la page 1sur 284

Programmation en C

ENIT - 1A GE/MINDS

Année Universitaire : 2023-2024


Le langage de Programmation C
Présentation du C
 C est un langage de programmation inventé par Dennis
Ritchie sur un système UNIX vers les années 1970.
 Il est issu des langages BCPL de M. Richards (1967) et B
développé aux Bel-Labs (1970).
 C est un:
 langage de Haut Niveau (de la famille du langage Pascal) car il possède
les principales structures de contrôle
 langage de Bas Niveau (de la famille du langage Assembleur) car il
possède les outils de manipulation d’informations système.
 C est un des premiers langages offrant des possibilités de
programmation modulaire

Programmation langage C -
ENIT 23-24 3
Structure d’un programme C

Un programme C comporte:
 Une entête (header) constitué de méta-instructions ou
directives destinées au préprocesseur (Exp: Inclusion de
librairies de fonctions prédéfinies)
 Un bloc Principal appelé main() qui représente la
fonction principale
 Le corps des fonctions placées avant ou après le
main() dans un ordre quelconque, les unes après les
autres
Partout, les variables et les fonctions font l’objet d’une
déclaration précisant leurs types

Programmation langage C -
ENIT 23-24 4
Fichier C (extension .c)
/* exemple de programme C :
- somme des nb de 1 à 10 et affichage
de la valeur*/ En C le programme principal 1
#include <stdio.h> 0 s'appelle toujours main
void main () 1
déclarations de variables de 2
{ type entier (cases mémoire
int somme; int i; 2 pouvant contenir un entier)
somme = 0; 3 instruction d'affectation de 3
for (i = 1; i <= 10; i++) valeur à la variable somme
4 { instructions exécutées
somme = somme + i; en séquence
} l'instruction entre accolades 4
printf ("%d\n", somme); 5 est exécutée pour les valeurs
} de i allant de 1 à 10
affiche à l'écran la valeur de 5
l'entier contenu dans somme
Programmation langage C -
ENIT 23-24 5
Exemple: Calcul de la surface d’un cercle

En Pascal En C

Program surface ; #include <stdio.h>


Const PI = 3.14 ; #define PI 3.14
Function surf (rayon : real) : real ; float surf(float rayon)
Var surfacecercle : real; {
Begin float surfacecercle ;
surfacecercle := rayon*rayon*PI; surfacecercle=rayon*rayon*PI;
surf := surfacecercle; return(surfacecercle );
End; }
Var s : real ; void main()
Begin {
s=surf(2.0); float s;
writeln(s); s=surf(2.0);
nd; printf("%f\n",s);
}

Programmation langage C -
ENIT 23-24 6
Structure d’un programme C
Programme typique en C

include
Main() est toujours la
1ère fonction appelée
main()

fonction a() instructions

fonction b() instructions

Programmation langage C -
instructions
ENIT 23-24 7
1. Les éléments de base du langage C

Considérations Lexicales
Les Identificateurs
 Un identificateur est constitué de lettres (‘a’...‘z’, ‘A’..‘Z’), de
chiffres (‘0’...‘9’) et éventuellement du caractère souligné (‘_’).
 Un identificateur doit impérativement commencer par une
lettre ou un ’_’ et ne pas faire partie de la liste des mots
réservés.
 Attention, une distinction est faite entre les caractères
majuscules et minuscules (NbLignes et nblignes sont deux
identificateurs différents).
 La norme ANSI a fixé à 31 le nombre de caractères
significatifs d’un identificateur bien que la longueur de ce
dernier puisse être plus importante.

Programmation langage C -
ENIT 23-24 9
Les mots clés
 Voici les mots réservés du langage C. Ils ne doivent pas
être utilisés comme identificateurs.
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 réservés const, signed et volatile sont
propres à la norme ANSI.

Programmation langage C -
ENIT 23-24 10
Les Commentaires

 Toute suite de caractères encadrée par les symboles ‘/*’ et ‘*/’


correspond à un commentaire et ne joue évidemment aucun rôle
lors de l’exécution du programme.
 Les commentaires sont donc ignorés par le compilateur mais sont
indispensables sur le plan de la documentation du programme.
 Exemples de commentaires :
/* Ceci est un commentaire */
/* Les commentaires peuvent etre formules sur
plusieurs lignes */
/* Il est frequent
* de formuler
* des commentaires ainsi
*/

Programmation langage C -
ENIT 23-24 11
L’appel d’une bibliothèque : #include

 #include indique au compilateur C qu’il doit inclure le


contenu du fichier entête *.h (ou header file) dans le
programme lors de la compilation
 Exemples de bibliothèques:
 "stdio.h" : (standard input output), elle contient les macros
standards pour les opérations d’entrées/sorties. Exp: printf,
scanf, puts, gets.
 "conio.h" : elle contient les routines d’E/S du DOS. Exp: clrscr,
pour clear screen et getch pour get character.
 "string.h" : pour la manipulation des chaines de caractères.
Exp : strcmp, strcpy.
 "math.h" : pour l’utilisation des fonctions mathématiques. Exp:
sqr, sqrt.

Programmation langage C -
ENIT 23-24 12
Les éléments de base du langage C

Les Constantes
Définition Constante

Ce sont les données les plus simples qu’un


programme C sache manipuler. Elles
permettent d’écrire une valeur n’importe où
dans le programme. On distingue quatre
types de constantes :
• Les nombres entiers.
• Les nombres réels, avec partie décimale.
• Les caractères.
• Les chaînes de caractères.

Programmation langage C -
ENIT 23-24 14
Nombres Entiers
 Les constantes littérales numériques entières ou
réelles suivent les conventions habituelles, avec
quelques particularités.
 Les constantes littérales entières peuvent aussi
s‘écrire en octal et en hexadécimal :
 une constante écrite en octal (base 8) commence par 0 (zéro)
 une constante écrite en hexadécimal (base 16) commence par
0x ou 0X
 Voici par exemple trois manières d‘écrire le même
nombre :
27 033 0x1B

Décimal octal hexadécimal

Programmation langage C -
ENIT 23-24 15
Nombres Flottants
 Une constante littérale est l'expression d'un nombre flottant si elle présente, dans
l'ordre :
 une suite de chiffes décimaux (la partie entière)
 un point, qui joue le rôle de virgule décimale
 une suite de chiffres décimaux (la partie fractionnaire)
 une des deux lettres E ou e
 éventuellement un signe + ou -
 une suite de chiffres décimaux
 Les trois derniers éléments forment l'exposant.
 Exemple : 123.456E-78.
 On peut omettre :
 la partie entière ou la partie fractionnaire, mais pas les deux
 le point ou l'exposant, mais pas les deux.
Exemples : .5e7, 5.e6, 5000000., 5e6
 Une constante flottante est supposée de type double, à moins de comporter un suffixe
explicite :
 les suffixes F ou f indiquent qu'elle est du type float
 les suffixes L ou l indiquent qu'elle est du type long double
Exemples : 1.0L, 5.0e4f

Programmation langage C -
ENIT 23-24 16
Caractères et Chaînes de Caractères(1)

 Une constante de type caractère se note en


écrivant le caractère entre apostrophes.
Exemple : 'A' '2' '"'
 Une constante de type chaîne de caractères
se note en écrivant ses caractères entre
guillemets.
 Quatre chaînes de caractères :
"A" "Bonjour à tous !" "" "'"

Programmation langage C -
ENIT 23-24 17
Caractères et Chaînes de Caractères(2)

 Une constante de type chaîne de caractères représente une suite


finie de caractères, de longueur quelconque.
 Le codage interne d'une chaîne de caractères est le suivant :
 les caractères constituant la chaîne sont rangés en mémoire, de manière
contiguë, dans l'ordre où ils figurent dans la chaîne ;
 un caractère nul est ajouté immédiatement après le dernier caractère de
la chaîne, pour en indiquer la fin ;
 la constante chaîne représente alors, à l'endroit où elle est écrite,
l'adresse de la cellule où a été rangée le premier caractère de la chaîne.

Programmation langage C -
ENIT 23-24 18
Caractères et Chaînes de Caractères(3)

 Par conséquent, une constante chaîne de caractères


a pour type celui d'un tableau de caractères (c'est-à-
dire char[] ) et pour valeur l'adresse d'une cellule de
la mémoire.
 Par caractère nul on entend le caractµere dont le
code interne est 0 ; on peut le noter indifféremment
0, '\000' ou '\0' (mais certainement pas '0') ; il est
utilisé trés fréquemment en C.

Programmation langage C -
ENIT 23-24 19
Déclaration Constante

C permet de déclarer des constantes par la


commande :
#define <Nom> <Valeur>
Ou encore (ajouté par l’ANSI) :
const <type> <nom>=<valeur>;
Exemples :
#define TEL 71000100
const int annee = 2002;

Programmation langage C -
ENIT 23-24 20
Les éléments de base du langage C

Les Types de Base en C


Deux catégories de types

 Les types scalaires :


Les variables de type scalaire ne peuvent stocker
qu’une seule valeur dans l’intervalle des valeurs
possibles.
 Les types composés :
Les variables de type composé permettent de
stocker simultanément plusieurs valeurs
(tableaux, pointeurs, structures, unions, etc.)

Programmation langage C -
ENIT 23-24 22
C possède 4 types de base

Plage de
Type Signification Taille (bits)
valeurs
int Entier 16 (2 o) -32768 à +32767

float Réel 32 (4 o) ±10-37 à ± 10+38

Réel en double
double 64 (8 o) ±10-307 à ± 10+308
précision

char Caractère 8 (1 o)

Programmation langage C -
ENIT 23-24 23
Les littéraux entiers
 Les notations utilisées pour écrire les littéraux entiers sont :
 la notation décimale,
 la notation octale, (doit commencer par 0)
 et la notation hexadécimale. (doit finir par h et commencer par 0 si le
premier est une lettre).
 Il existe la possibilité d’ajouter un attribut (ou modificateur ) :
 unsigned : entier ou caractère non signé, de 0 à 65535
 long : entier double longueur, de -2.109 à +2.109
 short : entier court, de -32768 à +32768
On peut omettre d’écrire int avec un attribut.

Programmation langage C -
ENIT 23-24 24
Les littéraux réels

 Deux notations habituelles sont utilisées:


 la notation fixée. Ex : 1.34
 et la notation flottante. Ex : -3.14e-10

Programmation langage C -
ENIT 23-24 25
Les littéraux caractères(1)
 Les littéraux caractères permettent de désigner les valeurs
entières correspondant aux code ASCII des caractères. Les
notations possibles sont :
 la notation éditable : présentation du caractère entre apostrophes,
 la notation décimale : valeur décimale du code ASCII correspondant,
 la notation octale : valeur octale du code ASCII correspondant,
 la notation hexadécimale : valeur hexadécimale du code ASCII
correspondant,
 la notation symbolique : certains littéraux caractères possèdent des
notations symboliques, le tableau ci-dessous les résume :

Programmation langage C -
ENIT 23-24 26
Les littéraux caractères(2)
Notation Signification
'\a' Signal sonore
'\n' Passage à la ligne suivante
'\r' Retour du curseur en début de ligne
'\b' Déplacement du curseur d’un caractère vers la gauche
'\f' Déplacement vers la page suivante
'\t' Déplacement du curseur d’une tabulation vers la droite

'\v' Déplacement du curseur d’une tabulation vers le bas


'\'' Apostrophe
'\''' Double cote
'\\' Anti-slash

Programmation langage C -
ENIT 23-24 27
Les littéraux chaînes de caractères
 Une chaîne de caractère est constituée d’une
séquence de caractères délimitée par double
cotes.
 Lorsque elle est mémorisée, une chaîne de
caractère est complétée automatiquement
par la caractère NUL (0 en code ASCII). Ce
terminateur est nécessaire pour la bonne
exécution de certaines fonctions standards.
 'A' et "A" sont deux variables distinctes

Programmation langage C -
ENIT 23-24 28
Définition de nouveaux types

 La norme ANSI permet de définir de nouveaux types de variables


par typedef.
 Syntaxe: typedef <type_de_base> nouveau_nom;
 Ceci permet de donner un nom à un type donné, mais ne crée
aucune variable. Une déclaration typedef est normalement globale
et publique.
 Exemple:
typedef long int entierlong; /* définition d'un nouveau type */
entierlong i; /* création d'une variable i de type entierlong */
tyedef char* STRING ; /* fait de string un synonyme de char* */

Programmation langage C -
ENIT 23-24 29
Les éléments de base du langage C

Les Opérateurs
Les opérateurs
 Symboles simples :
( ) [ ] . ! ~ < > ? :
= , + - * / % & ^
 Symboles composés :
-> ++ -- <= >= == != && || << >>
+= -= *= /= %= <<= >>= |= &= ^=
 Tous ces symboles sont reconnus par le compilateur comme des
opérateurs.
 Il est interdit d'insérer des caractères blancs à l'intérieur d'un
symbole composé. En outre, il est conseillé d'encadrer par des
blancs toute utilisation d'un opérateur.

Programmation langage C -
ENIT 23-24 31
Classes d’opérateurs

les opérateurs unaires : qui précèdent un identificateur,


une expression ou une constante. Exp: -x
 les opérateurs binaires : qui mettent en relation 2

termes ou expressions. Exp: a+b


 les opérateurs ternaires : qui mettent en relation 3

termes . Exp : « ? : ». Exp:


printf("%s", 1==2 ? "1 est égal à 2" : "1 est différent de
2") ;

Programmation langage C -
ENIT 23-24 32
Les opérateurs arithmétiques

+ : addition,
- : soustratction,
* : multiplication,
/ : division :
 division entière : si les 2 opérandes sont entières,
 division réelle : si au moins une des 2 opérandes est réel
% : reste de la division
 Exp: float x;
x = 3 / 2; /*affecte à x la valeur 1 */
x = 3 / 2.0; /*affecte à x la valeur 1.5 */
 L'opérateur % ne s'applique qu’à des opérandes de type entier.
 En C, il n’y a pas d’opérateur effectuant l’élévation à la puissance.
Donc, il faut utiliser la fonction pow(x,y) de la librairie math.h pour
calculer xy

Programmation langage C -
ENIT 23-24 33
Les opérateurs relationnels

== : égal,
!= : différent,
> : Strictement supérieur,
>= : supérieur ou égal,
< : Strictement inférieur,
<= : inférieur ou égal.

Programmation langage C -
ENIT 23-24 34
Les opérateurs logiques

! : négation unaire,
&& : ET logique binaire
|| : OU logique binaire
 Le type booléen n’existe pas en C, la valeur

retournée par ces opérateurs est un entier


qui vaut 0 si la condition est faux.

Programmation langage C -
ENIT 23-24 35
Les opérateurs de traitement de bits

& : ET niveau bit


| : OU niveau bit & 0 1
0 0 0
^ : O U exclusive 1 0 1

<< : décalage à gauche 0


| 0
0
1
1
1 1 1
>> : décalage à droite
^ 0 1
~ : complément à 1 0
1
0
1
1
0

Programmation langage C -
ENIT 23-24 36
Les opérateurs d’incrémentation et de décrémentation

i++ : post-incrémentation : utilise la valeur de i ensuite incrémente sa valeur,


++i : pré-incrémentation : incrémente la valeur de i puis utilise sa valeur,
i-- : post-décrémentation : utilise la valeur de i ensuite décrémente sa
valeur,
--i : pré-décrémentation : décrémente la valeur de i puis utilise sa valeur,
 Exemple :
int a = 3, b, c;
b = ++a; /* après exécution de cette instruction a et b valent 4
equivalent à a=a+1 ;
b=a ; */
c = b++; /* après exécution de cette instruction c vaut 4 et b vaut 5
equivalent à c=b ;
b=b+1 ;*/

Programmation langage C -
ENIT 23-24 37
L’opérateur d'affectation
 L’Opérateur d’affectation est le symbole =
 Syntaxe:
<Nomvariable> = <Expression>;
 Expression peut être:
 Une constante
 Le nom d’une variable
 Une expression
 Exemples:
 a=5 (met la valeur 5 dans la variable a. Si a est float, il y a conversion implicite en
float);
 b=(a*5)/2 (calcule d'abord l’expression, puis met le résultat dans b);
 a=5+(b=2) (Le compilateur lit l'expression de gauche à droite. la première affectation
nécessite le calcul d'une expression : 5+(b=2). Celle ci comporte une addition, dont il
évalue le premier opérande (5) puis le second (b=2). Il met donc 2 dans b, le résultat
de l'opération est 2, qui sera donc ajouté à 5 pour être mis dans a. a vaut donc 7 et b,
2. Le résultat de l'expression est 7).

Programmation langage C -
ENIT 23-24 38
Les opérateurs d'affectation composée

 Les opérateurs d'affectation composée sont


+= -= *= /= %= &= ^= |= <<= >>=
 Pour tout opérateur op, l'expression :
expression1 op= expression2

expression1 = expression1 op expression2
 Exemple :
x+=y ; /*equivalent à x = x+y*/

Programmation langage C -
ENIT 23-24 39
L'opérateur virgule
 Une expression peut être constituée d'une suite d'expressions
séparées par des virgules :
expression1, expression2, ..., expressionN
 Cette expression est alors évaluée de gauche à droite. Sa
valeur sera la valeur de l'expression de droite. Le programme
suivant:
main()
{
int a, b;
b = ((a = 3), (a + 2));
printf(''\n b = %d \n'',b);
}
Affiche à l’écran : b = 5
 La virgule séparant les arguments d'une fonction ou les
déclarations de variables ne représente pas l'opérateur virgule.

Programmation langage C -
ENIT 23-24 40
L'opérateur de conversion de type
 L'opérateur de conversion de type, appelé
cast, permet de modifier explicitement le type
d'un objet. La syntaxe est:
(type) objet
 Exemple :
int i = 3, j = 2;
float r ;
r=(float)i/j;
r va contenir la valeur 1.5

Programmation langage C -
ENIT 23-24 41
L'opérateur de référencement &

 L'opérateur & appliqué à une variable


retourne l'adresse mémoire de cette variable.
 Exemple:
int i=5 ;
printf("\n%x ",&i) ;
Affiche à l’écran l’adresse mémoire de i en
hexadécimale, exemple: FFF4

Programmation langage C -
ENIT 23-24 42
Opérateur de déréférencement *

 Le * est l'opérateur d'indirection. Il permet


d'accéder à une variable à partir d'une
adresse (le plus souvent en utilisant la valeur
contenue dans un pointeur).
 Pour l’exemple précedent *&i donne la valeur
5, de même que *p, si p été initialisé avec
l'adresse de i, soit (p=&i).

Programmation langage C -
ENIT 23-24 43
L’Opérateur SizeOf()

 Le langage C offre l’opérateur SizeOf() qui


donne la taille en octets de l’opérande
passée en paramètre.
 sizeof(char) retourne 1 octets

Programmation langage C -
ENIT 23-24 44
Priorité des opérateurs(1)

Exemple

 Soit l'instruction: A=5, B=10, C=1;


 Pour calculer la valeur de X après l’instruction:
X = 2*A+3*B+4*C;
L'ordinateur évalue d'abord les multiplications:
2*A ==> 10 , 3*B ==> 30 , 4*C ==> 4
Ensuite, il fait l'addition des trois résultats obtenus:
10+30+4 ==> 44
A la fin, il affecte le résultat général à la variable:
X = 44

Programmation langage C -
ENIT 23-24 45
Priorité des opérateurs(2)
 Si on veut forcer l'ordinateur à commencer par un
opérateur avec une priorité plus faible, nous devons
(comme en mathématiques) entourer le terme en
question par des parenthèses.

 Exemple
Dans l'instruction: X = 2*(A+3)*B+4*C;
(En reprenant les valeurs du dernier exemple, le résultat
sera 164)

Programmation langage C -
ENIT 23-24 46
Priorité des opérateurs(3)
Classes de priorités
Priorité 1 (la plus forte): ( )

Priorité 2: ! ++ --

Priorité 3: * / %

Priorité 4: + -

Priorité 5: < <= > >=

Priorité 6: == !=

Priorité 7: &&

Priorité 8: ||

Priorité 9 (la plus faible): = += -= *= /= %=

Programmation langage C -
ENIT 23-24 47
Priorité des opérateurs(4)
 Evaluation d'opérateurs de la même classe
Dans chaque classe de priorité, les opérateurs ont la
même priorité. Si nous avons une suite d'opérateurs
binaires de la même classe, l'évaluation se fait en
passant de la gauche vers la droite dans l'expression.
 Pour les opérateurs unaires (!,++,--) et pour les
opérateurs d'affectation (=,+=,-=,*=,/=,%=), l'évaluation
se fait de droite à gauche dans l'expression.

Programmation langage C -
ENIT 23-24 48
Priorité des opérateurs(5)

 Exemples
L'expression 10+20+30-40+50-60 sera évaluée comme suit:
10+20 ==> 30 - 30+30 ==> 60 - 60-40 ==> 20 - 20+50 ==> 70 - 70-60 ==> 10

Pour A=3 et B=4, l'expression A *= B += 5 sera évaluée comme suit:

Programmation langage C -
ENIT 23-24 49
Conversion Implicite de type(1)

 Le compilateur fait de lui-même des


conversions lors de l’évaluation des
expressions. Pour cela, il applique des règles
de conversion implicite

Programmation langage C -
ENIT 23-24 50
Conversion Implicite de type(2)

 Exemple

Programmation langage C -
ENIT 23-24 51
Conversion Implicite de type(3)

Programmation langage C -
ENIT 23-24 52
Conversion Implicite de type(4)

 Il est possible de forcer la conversion d’une variable (ou d’une


expression) dans un autre type avant de l’utiliser par une
conversion implicite (opération de cast veu plus haut).

Programmation langage C -
ENIT 23-24 53
Les éléments de base du langage C

Les Variables
Déclaration de variables
 Les variables doivent toutes être déclarées avant d’être utilisées.
En C, une variable est caractérisée par :
 Son nom (un identificateur)
 Son type (type de base ou type défini par l’utilisateur)
 Syntaxe de déclaration:
<type> <nomvariable1>[=<initialisation1>] [, <nomvariable2>[=<initialisation2>] ];
Exemples :
int x=10;
int y=10,z;
Float s;
char guillemet=‘\"‘;

Programmation langage C -
ENIT 23-24 55
Les fonctions d’E/S standards
Les fonctions d’E/S standards

 Les fonctions d’E/S standards sont les fonctions assurant


l’échange d’information entre la mémoire centrale et les
périphériques standard, principalement le clavier et l’écran.
 les fonctions les plus utilisées sont
printf()
écriture formatée de données

scanf()
lecture formatée de données

putchar()
écriture d'un caractère

getchar()
lecture d'un caractère

Programmation langage C -
ENIT 23-24 57
Ecriture formatée de données(1)

 Syntaxe
printf( "Chaine de format" {, argument});

 La chaîne de format contrôle comment les


arguments seront convertis, formatés et
affichés. Elle contient deux types
d’informations:
 des caractères ordinaires qui sont simplement
recopiés à l’écran
 des caractères de spécification de format.
Programmation langage C -
ENIT 23-24 58
Ecriture formatée de données(2)
 Les spécifications de format commencent toutes par le
caractère pourcent (’%’), peuvent ensuite contenir une
indication de largeur (minimale), de précision (maximale)
et finalement un caractère code pour le type de
l’argument. Voici les codes de type essentiels
• d pour les entiers
• f pour les nombres flottants sous forme décimale
• e pour les nombres flottants sous forme scientifique
• c pour les caractères
• s pour une chaîne de caractères
• % pour afficher le caractère ’%’

Programmation langage C -
ENIT 23-24 59
Ecriture formatée de données(3)

 Remarque :
Il doit y avoir au moins autant d’arguments
qu’il en est prévu dans la chaîne de format;
sinon, le résultat n’est pas prévisible

Programmation langage C -
ENIT 23-24 60
Ecriture formatée de données(4)

 Exercice:
 Déclarer une constante contenant le nom d’une
classe exemple "1AENIT"
 Déclarer une var nom de type chaîne de caractère
et lui assigner une valeur exemple "ahmed"
 Déclarer 2 variables test et exam de type réel et
leur assigner 2 valeurs quelconques exemple 12.5
et 17.0
 Afficher à l’écran le nom de la classe, le nom de
l’étudiant, les notes de test et examen ainsi que sa
moyenne ( test * 0.4 + exam * 0.6 )
Programmation langage C -
ENIT 23-24 61
Ecriture formatée de données(5)
 Remarques :

 printf ("%kd",n) ;  Affiche au moins k caractères à droite.


Exp1 : k=3 et n = 25  affiche _25 (tiré bas remplace l’espace)
Exp2 : k=2 et n = 355  affiche 355
 printf ("%-kd",n) ;  Affiche au moins k caractères à gauche.
Exp1 : k=3 et n = 25  affiche 25_ (tiré bas remplace l’espace)
Exp2 : k=2 et n = 355  affiche 355
 printf ("%f",x) ;  Affiche le nombre réel en décimal avec 6 chiffre après la virgule, par défaut.
Exp1 : x=1.5  1.500000
 printf ("%kf",x) ;  Affiche le nombre réel en décimal avec 6 chiffre après la virgule, par
défaut.
Avec k représente la longueur minimale du nombre.
Exp1 : k=9, x=1.5  _ _1.500000
 printf ("%kf.J",x) ;  Affiche le nombre réel en décimal avec 6 chiffre après la
virgule, par défaut. Avec k représente la longueur
minimale du nombre et J représente le nombre de chiffre
après la virgule.
Exp1 : k=9, J=3 ,x=1.5  _ _ _ _ _1.500

Programmation langage C -
ENIT 23-24 62
Lecture formatée de données(1)

 La fonction scanf() permet au programme de demander


des informations à l’utilisateur au moyen du clavier. La
syntaxe est
scanf( "Chaine de format" {, adresse});

 Cette fonction lit une chaîne de caractères au clavier et


stocke les données lues aux adresses indiquées.
 La chaîne de format est très semblable à celle de printf().
Elle contrôle comment les valeurs seront lues et
converties pour être mémorisées.

Programmation langage C -
ENIT 23-24 63
Lecture formatée de données(2)

 Pour chaque adresse de variable spécifiée, il faudra


une spécification de format dans la chaîne.
 Ces spécifications de format seront séparées par des
caractères séparateurs.
 Les caractères séparateurs possibles sont l’espace ’ ’,
la tabulation ’\t’ et l’interligne ’\n’.
 Lorsqu’un caractère séparateur est spécifié dans la
chaîne de format, tous les caractères séparateurs
rencontrés dans la chaîne d’entrée sont lus, jusqu’au
prochain caractère qui ne soit pas un séparateur.

Programmation langage C -
ENIT 23-24 64
Lecture formatée de données(3)

 Les spécifications de format commencent par un


caractère pourcent (’%’), comme pour la fonction
printf(). On peut ensuite mettre une spécification de
largeur (nombre maximal de caractères à lire) et un
caractère donnant le type de l’entrée. Les codes de
types les plus importants sont
• d pour un entier
• e ou f pour un nombre flottant
• s pour une chaîne de caractères
• c pour un seul caractère

Programmation langage C -
ENIT 23-24 65
Lecture formatée de données(4)

 Attention lors de la lecture d’un caractère, si le prochain


caractère est un séparateur, il sera stocké quand-même.
 Pour que scanf() puisse stocker les valeurs lues dans des
variables, il ne lui suffit pas d’avoir le nom de la variable, il
veut connaître l’adresse à laquelle la variable est stockée
en mémoire centrale.
 Pour qu’il reçoive bien cette adresse, nous devons faire
précéder chacun des noms de variables du caractère ’&’.
C’est un opérateur très utilisé en C qui retourne l’adresse
de la variable qui suit.

Programmation langage C -
ENIT 23-24 66
Lecture formatée de données(5)
Remarques:
 On peut placer la longueur de la variable entre le signe

% et la lettre spécificateur. Par exemple « %3d »


indique qu’on va lire un entier de 3 chiffres et le reste
des chiffres sont ignorés. scanf("%3d",&i) ;
 Si l’on sépare les spécificateurs de format par des

espaces ou par des virgules alors les valeurs à lire


seront séparées par les mêmes séparateurs.

Exercice:
Changer l’Exercice précédent de telle façon que le nom de
l’étudiant et ses notes seront demandés de l’utilisateur.
Programmation langage C -
ENIT 23-24 67
La fonction putchar

 Envoie un caractère vers stdout (écran)


 Exemple :
char c ;
c= ‘A’
putchar (c);
putchar (‘B’);

Programmation langage C -
ENIT 23-24 68
La fonction getchar()
 La fonction getchar pemet la saisie d'un caractère (char). Elle
appartient à la bibliothèque stdio.h. Les 2 écritures suivantes sont
équivalentes:
char c;
printf("ENTRER UN CARACTERE: ");
scanf("%c",&c);
 ET
char c;
printf("ENTRER UN CARACTERE: ");
c = getchar();
 Non formatée, la fonction getchar est moins gourmande en place
mémoire que scanf. Il vaut mieux l'utiliser quand cela est
possible; getchar utilise le flux d'entrée exactement comme scanf.

Programmation langage C -
ENIT 23-24 69
2. Les structures de contrôle
Contrôle de flux

 Jusqu’à maintenant, les programmes que nous avons


vus étaient tous séquentiels. Les instructions
devaient s’exécuter l’une après l’autre selon l’ordre
dans lequel nous les avons écrites, du haut vers le
bas.
 On trouve aussi dans les langages de haut niveau la
possibilité d’offrir des structures itératives (boucles),
des structures conditionnelles (tests) et des
ruptures (sauts).

Programmation langage C -
ENIT 23-24 71
Les structures conditionnelles
 Elles permettent au programme de suivre
plusieurs chemins différents, en fonction de
conditions que l’on teste en cours
d’exécution. Le programme choisira un
chemin et n’exécutera qu’un sous-ensemble
des instructions données. Les structures
conditionnelles de C sont
• if ... else ... (si ... sinon ...)
• switch (choix multiple : Selon)
• l’opérateur ( ... )? ... : ...; (alternative)

Programmation langage C -
ENIT 23-24 72
Les structures de contrôle

L’instruction if … else
if...else... (1)
 Syntaxe
 Sans alternative:
if ( expression )
instruction ou bloc d’instructions
 Avec alternative:
if ( expression )
instruction1 ou bloc d’instructions 1
else
instruction2 ou bloc d’instructions 2

Programmation langage C -
ENIT 23-24 74
if...else... (2)

 Si l’expression entre parenthèses est évaluée à vrai


(valeur non nulle) alors l’instruction ou le bloc
d’instructions qui suit le if est exécutée.
 Si l’expression est évaluée à faux (valeur nulle) alors
l’instruction se trouvant après le else est exécutée si on
l’a spécifiée. Si on ne l’a pas spécifiée, le programme
passe à l’instruction suivante directement.
 Dans le cas où plusieurs tests se suivent, la clause else
se rapporte toujours au if le plus proche.

Programmation langage C -
ENIT 23-24 75
if...else... (3)
Exp1:
if (A-B)
printf("A est différent de B\n");
else
printf("A est égal à B\n");

Exp2:
if (a==0)
printf("a est nul\n");
else if (a<0)
printf("a est strictement négatif\n");
else
printf("a est strictement positif\n");

Programmation langage C -
ENIT 23-24 76
if...else... (4)
Exemple: Lire un nombre à partir du clavier et tester si ce nombre est pair ou impair
#include <stdio.h>
void main() {
int nbr;
printf ("Entrez un nombre SVP ");
scanf ("%d", &nbr);
if (nbr > 0)
if (nbr % 2 == 0)
printf ("C\'est un nombre pair\n");
else
printf ("C'est un nombre impair\n");
else
printf ("C\'est un nombre negatif\n");
getch();
}

Programmation langage C -
ENIT 23-24 77
if...else... (5)

Exercice:
 Changer l’exercice du calcul et affichage de a moyenne
précédent de telle façon que le calcul et l’affichage ne se fait
que si les notes saisies sont compris entre 0 et 20, sinon, on
affiche un message d’erreur.
Remarques:
 Les { } ne sont pas nécessaires lorsque les blocs ne
comportent qu'une seule instruction.
 On peut avoir des « if » imbriqués

Programmation langage C -
ENIT 23-24 78
Les structures de contrôle

L’instruction switch
switch(1)
switch (expression )
{
case constante1: liste d'instructions 1
break;
case constante2: liste d'instructions 2
break;
...
case constanten: liste d'instructions n
break;
default: liste d'instructions
break;
}

Programmation langage C -
ENIT 23-24 80
switch(2)

 Le bloc default n’est pas obligatoire


 « expression » doit être de type char ou int
 expression, constante1, constante2 et les autres
valeurs sont de même type
 L’instruction break permet de sortir de l’instruction
switch. Elle est importante car si on ne la met pas
après chaque cas d’exécution alors toutes les
instructions après ce cas seront exécutées (bien sur
s’ils ne sont pas suivis d’une autre instruction break).

Programmation langage C -
ENIT 23-24 81
switch(3)

Exemple:
int mois ;
scanf(" %d" ,&mois) ;
switch ( mois )
{
case 1 : printf(" janvier" ) ;
break ;
case 2 : printf(" fevrier" ) ;
break ;

case 12 : printf(" décembre" ) ;
break ;
default : printf(“erreur”)
}

Programmation langage C -
ENIT 23-24 82
3. Les structures Répétitives
Les structures itératives
 Elles permettent de spécifier des instructions
qui seront exécutées plusieurs fois par le
processeur. On parle aussi de boucles. Les
structures itératives de C sont
• while (<==> tant que … faire)
• do ... while (<==> répéter … jusqu’à)
• for (pour parcourir un intervalle)
 Elles permettent de couvrir tous les cas
possibles d’itérations.

Programmation langage C -
ENIT 23-24 84
Les structures Répétitives

La boucle while
La boucle while(1)
 Syntaxe
while ( expression )
instruction ou bloc d’instructions
 Fonctionnement
 Lorsque le programme atteint l’instruction while, il évalue
l’expression entre parenthèses.
 Si le résultat est vrai (différent de zéro), alors il exécute
l’instruction ou le bloc d’instructions qui suit puis il
recommence. Il évalue une nouvelle fois l’expression, etc.
 Si le résultat est faux (au premier, deuxième,... ou Xème
passage) alors il n’exécute pas l’instruction et arrête de
boucler, passant à l’instruction suivante.

Programmation langage C -
ENIT 23-24 86
La boucle while(2)
 Remarques :
 Le test s’effectuant au début, il est très possible
que l’instruction ne soit jamais exécutée.
 L’expression entre les parenthèses est
obligatoire.
 Il est important que l’instruction ou le bloc puisse
influencer sur l’évaluation de l’expression entre
les parenthèses (par exemple en modifiant une
variable de fin ou un compteur), sinon, le
programme bouclera indéfiniment (CTRL-C pour
l’arrêter).
Programmation langage C -
ENIT 23-24 87
La boucle while(3)
Exemple1:
/* Afficher les nombres de 1 à 10 */
int I = 0 ;
while (I<10)
printf(“%d\n”,++I);
Exemple2:
/* calculer la somme des N premiers entiers naturels*/
int somme=0, i = 0;
while (i<N)
{
somme += i;
i++ ;
}

Programmation langage C -
ENIT 23-24 88
La boucle while(4)

Exemple: Affichage de toutes les lettres majuscules


#include <stdio.h>
#include <conio.h>
main() {
char uncar='A';
while (uncar<='Z') {
printf ("%c, ",uncar);
uncar += 1; /* code ASCII suivant */
}
printf ("\n");
getch();
}

Programmation langage C -
ENIT 23-24 89
Les structures Répétitives

La boucle do…while
La boucle do…while(1)

do
{
bloc d’instructions;
} while ( expression );
 Le bloc d'instructions est exécuté au moins une

fois et jusqu’à ce que l'expression fournit une


valeur égale à zéro (false).
 Les { } ne sont pas obligatoires, si le bloc

d’instruction contient une seule instruction.

Programmation langage C -
ENIT 23-24 91
La boucle do…while(2)
 do - while est comparable à la structure Repeat du
langage Pascal si la condition finale est inversée
logiquement.
 La structure do - while est semblable à la structure
while, avec la différence suivante :
 while évalue la condition avant d'exécuter le bloc d'instructions.
 do - while évalue la condition après avoir exécuté le bloc
d'instructions. Ainsi le bloc d'instructions est exécuté au moins
une fois.
 Une application typique de do - while est la saisie de
données qui doivent remplir une certaine condition.

Programmation langage C -
ENIT 23-24 92
La boucle do…while(3)

Exemple: Lecture d’un nombre réel dans


l’intervalle [1,10]
float N;
do
{
printf("Donner un nombre entre 1 et 10 :");
scanf("%f", &N);
}while (N<1 || N>10);

Programmation langage C -
ENIT 23-24 93
Les structures Répétitives

La boucle for…
La boucle for ... (1)
 L’instruction for est une sorte de while plus complexe
que l’on utilise généralement dans le cas de boucles où
le nombre d’itérations est connu. Son usage n’est
toutefois pas limité à ce seul cas comme dans d’autres
langages.
 Syntaxe
for ( initialisation; continuation; progression )
instruction ou bloc d’instructions
 initialisation, continuation et progression sont des
expressions C quelconques.

Programmation langage C -
ENIT 23-24 95
La boucle for ... (2)

 Fonctionnement
 Lorsque le programme arrive à une instruction for, l’expression
initialisation est évaluée. Ensuite, l’expression continuation est
évaluée, si elle est vraie, l’instruction ou le bloc est exécuté et
l’expression progression est évaluée. On revient ensuite à
l’évaluation de l’expression de continuation et on recommence
jusqu’à ce qu’elle soit fausse.
 Il est possible que les expressions initialisation, continuation ou
progression soient vides; dans ce cas, il faut tout de même mettre
le bon nombre de points-virgule. Il manquera une des étapes et le
comportement sera différent. Si l’expression continuation est
absente, la boucle ne s’arrêtera jamais, à moins qu’une
instruction de rupture appropriée soit rencontrée.

Programmation langage C -
ENIT 23-24 96
La boucle for ... (3)
Exemple
 Le programme suivant a
 Equivalence exactement le même
comportement que celui de
 Une instruction for peut l’exemple précédent.
être transformée en son #include <stdio.h>
équivalent while: #include <conio.h>
void main() {
initialisation; char uncar;
while ( continuation) { for (uncar='A'; uncar<='Z'; uncar+=1)
instruction ou bloc d’instructions printf ("%c, ",uncar);
printf ("\n");
progression;
getch();
} }

Programmation langage C -
ENIT 23-24 97
Les ruptures

• goto (aller à)
• break (arrêter)
• continue (passer à l’itération suivante)
• return (sortie de fonction)
• exit (fin du programme)

Programmation langage C -
ENIT 23-24 98
4. Les Tableaux
Les tableaux

Une seule variable de type tableau peut contenir plusieurs


informations du même type.
C’est donc une structure de données :
 de type composé car elle contient plusieurs valeurs,
 de taille fixe car l’occupation mémoire doit pouvoir être
calculée à la compilation,
 homogène car toutes ses valeurs sont du même type de
base.

Programmation langage C -
ENIT 23-24 100
Tableaux à une dimension(1)

 Déclaration d’une variable tableau :


type_de_base nom_tab[taille];
 Les crochets font partie de la définition et ne
signalent pas une partie optionnelle.
 Ceci indique que nous allons utiliser un
tableau appelé par nom_tab, comportant taille
éléments de type type_de_base.
 Exemple :
float notes[20];

Programmation langage C -
ENIT 23-24 101
Tableaux à une dimension(2)

Remarques:
 Le nombre d’éléments peut être n’importe quelle

expression constante dont le résultat est un nombre


entier positif.
 Cette expression ne peut pas contenir de variables ou

d’appels de fonctions.
 Le premier élément du tableau est obligatoirement

d’indice 0. ainsi, les éléments sont numérotés de 0 à


taille-1.

Programmation langage C -
ENIT 23-24 102
Tableaux à une dimension(3)

 Déclaration d’un type tableau


Typedef type_de_base nom_type_tab[taille];
 Accès aux éléments :
nom_du_tableau[indice_élément] ;
 indice-élément doit être dans l’ensemble {0,
1, ..., taille-1}. Dans le cas contraire, il n’y a
pas de signalisation d’erreur, mais le résultat
pourrait bien être anormal.
 Le langage C ne prévoit pas de routines pour
la vérification de la taille du tableau.

Programmation langage C -
ENIT 23-24 103
Tableaux à une dimension(4)
 Exemple
Typedef int TabEntier[10]
TabEntier notes;
notes[2] = 5;
 Opérations sur les tableaux :
 Il n’y a pas d’opérations globales (affectation, comparaison)
sur les tableaux ou sur des tranches de tableaux dans le
langage.
 La seule exception est pour l’initialisation du tableau lors de
sa déclaration.
Exemple: int tab[2]={10,15};

Programmation langage C -
ENIT 23-24 104
Tableaux à une dimension(5)

int tab[3]; tab tab[0]


tab[1]
tab[2]

int tab[3]={12,10,5};
tab 12
10
5

Programmation langage C -
ENIT 23-24 105
Les tableaux et les chaînes(1)
 L'initialisation d'un tableau de caractères peut se faire de
la manière suivante :
char msg[] = "Hello";
 Cette écriture est l'abréviation de :
char msg[] = {'H','e','l','l','o','\0'};
 La dimension du tableau est ici facultative, car elle peut
être calculée par le compilateur. msg est un tableau
initialisé, on ne peut donc modifier que son contenu.

Programmation langage C -
ENIT 23-24 106
Les tableaux et les chaînes(2)

 En dehors de la déclaration, il n'est pas possible


d'affecter une chaîne de caractères à un tableau. Il faut
passer par une fonction de copie de chaînes de
caractères (strcpy par exemple).
char ligne[81];
ligne = "Bonjour"; /* INTERDIT !!! */
ligne est le nom d'un tableau, "Bonjour" est une
constante chaîne de caractères et est considérée
comme une constante de type tableau de caractères.
Il faut employer strcpy(ligne,"Bonjour");

Programmation langage C -
ENIT 23-24 107
Tableaux à plusieurs dimensions(1)

 Déclaration d’une variable tableau :


type_de_base nom_tab[taille1][taille2]…[tailleN];
avec taillei le nombre d’éléments associés à la ième dimension
Exp: float T[3][2];
 Déclaration d’un type tableau :
Typedef type_de_base nom_type_tab[taille1][taille2]…[tailleN];
Exp: Typedef float tabf[3][2];
tabf T;
 Accès aux éléments :
nom_du_tableau[indice1][indice2]…[indiceN] ;
Exp: T[0][0]=12.0; /*élément numéro 1 dans T*/

Programmation langage C -
ENIT 23-24 108
Tableaux à plusieurs dimensions(2)

 Initialisation d’un tableau à plusieurs


dimensions :
 Il n’y a pas d’opérations globales (affectation,
comparaison) sur les tableaux ou sur des
tranches de tableaux dans le langage.
 La seule exception est pour l’initialisation du
tableau lors de sa déclaration.
 Exemple:
int tab[3][2]={{12,15},{12,1},{0,2}};

Programmation langage C -
ENIT 23-24 109
Exercice

Ecrire un programme qui


 lit la dimension N d'un tableau T de type int
(dimension maximale: 50 composantes),
 remplit le tableau par des valeurs entrées au
clavier et affiche le tableau.
 Calcule et affiche ensuite la somme des éléments
du tableau.

Programmation langage C -
ENIT 23-24 110
5. Les Fonctions
Les fonctions(1)

 sous-programme :
Un sous-programme est un petit programme
qui résout une partie du problème que le
programme principal doit traiter.
 On peut ainsi isoler la résolution de sous
problèmes différents dans autant de sous-
programmes.
 Intérêt : résoudre de très gros problèmes

Programmation langage C -
ENIT 23-24 112
Les fonctions(2)
 dans un programme, on peut avoir besoin de
faire plusieurs fois la même chose, avec de
petites variations  Dans ce cas, il est plus
économique d’appeler un sous programme avec
des paramètres différents, plutôt que d’écrire
plusieurs fois les mêmes lignes de code.

 Cette notion de réutilisabilité est aussi très


importante du point de vue du temps nécessaire
à la réalisation ultérieure d’autres programmes
qui peuvent se baser sur du travail déjà fait.

Programmation langage C -
ENIT 23-24 113
Les fonctions(3)

 Le langage C permet de spécifier des sous-


programme par le biais de fonctions.
 Il ne différencie pas procédures et fonctions
comme le font d’autres langages.
 D’une manière tout à fait générale, une
fonction peut effectuer un certain traitement
dépendant de paramètres et retourner le
résultat de ce traitement.

Programmation langage C -
ENIT 23-24 114
Définition de fonctions(1)

 Les fonctions définies dans un programme C sont


nommées par un identificateur construit de la même
manière que les identificateurs de variables ou de
constantes.
 Elles peuvent retourner une valeur, il est donc nécessaire
d’indiquer le type de cette valeur.
 Par ailleurs, elles peuvent recevoir un certain nombre de
paramètres ou arguments en entrée. Généralement, le
comportement de la fonction est influencé par ses
paramètres et il est aussi essentiel que le compilateur
connaisse leurs types.

Programmation langage C -
ENIT 23-24 115
Définition de fonctions(2)

 Les types de la valeur retournée et des arguments doivent


faire partie des types connus au moment de la définition
de la fonction.
 Enfin viendra un bloc d’instructions définissant les
variables locales et les actions que la fonction devra
effectuer lorsqu’elle sera appelée.
 Une des grandes différences entre la définition originale
du langage et la norme ANSI plus récente est justement la
syntaxe d’une telle définition.

Programmation langage C -
ENIT 23-24 116
Définition et déclaration "ANSI"(1)

Déclaration de fonction (prototypes)


type nom-fonction (type-1 arg-1,...,type-n arg-n)
Ou
type nom-fonction (type-1,...,type-n) /*sans nommer les args*/
 La déclaration doit contenir, entre les parenthèses, l’énoncé des
types de chacun des paramètres formels, séparés par des
virgules. Si les types ne sont pas déclarés, la vérification ne
pourra pas avoir lieu.
 Exemple, déclaration de la fonction «cube»
float cube (float); /* SANS nommer le paramètre */
float cube (float nombre); /* déclaration équivalente */

Programmation langage C -
ENIT 23-24 117
Définition et déclaration "ANSI"(2)

La définition d'une fonction est de la forme:


type nom-fonction (type-1 arg-1,...,type-n
arg-n)
{
[déclarations de variables locales ]
liste d'instructions
}

Programmation langage C -
ENIT 23-24 118
Définition et déclaration "ANSI"(3)

 Dans les définitions de fonctions, les types des


paramètres sont donnés juste avant les noms des
paramètres, entre les parenthèses et non plus à
l’extérieur des parenthèses.
 Les paires type-paramètre sont séparées par des
virgules.
 Pour chaque paramètre, il faut mettre explicitement le
type, même si plusieurs paramètres sont du même type.

Programmation langage C -
ENIT 23-24 119
Définition et déclaration "ANSI"(4)

Exemple: définition de la fonction «cube»


/* Fonction retournant le cube de son paramètre,
définition ANSI */
float cube (float un_nombre)
{
float resultat;
resultat = un_nombre * un_nombre * un_nombre;
return resultat;
}

Programmation langage C -
ENIT 23-24 120
Retour d’une fonction(1)
 L’instruction return expression; n’importe
où dans le bloc de la fonction a pour effet de
sortir de la fonction et de retourner le résultat
de l’expression au point d’appel de la
fonction.
 Il peut y avoir plusieurs sorties de ce type
dans une même fonction. Nous pouvons
affecter la valeur retournée à une variable ou
continuer à l’utiliser dans l’expression qui a
déclenché l’appel de la fonction. Nous
pouvons aussi négliger ce résultat
complètement.
Programmation langage C -
ENIT 23-24 121
Retour d’une fonction(2)

 Il se peut aussi dans certains cas qu’aucune instruction


return ne soit atteinte. Dans ce cas, la fonction se
termine, le contrôle revient au programme appelant et
la valeur de retour n’est pas définie.
 S’il est prévu qu’une fonction ne retourne pas de valeur
(elle peut toutefois se terminer par l’instruction return;)
elle doit être définie du type void.
 Dans ce cas, ce sera l’équivalent d’une procédure
Pascal ou Fortran. Le mot réservé void est aussi utilisé
pour indiquer l’absence de paramètres.

Programmation langage C -
ENIT 23-24 122
Appel d’une fonction

 Dans le programme, partout où la définition de la fonction ou


une déclaration équivalente est connue, il est possible
d’appeler une fonction à l’intérieur d’une expression en
écrivant son nom et ses paramètres effectifs entre
parenthèses.
 L'appel d'une fonction se fait par l'expression
nom-fonction(para-1,para-2,...,para-n)
 Lorsqu’une fonction est appelée, l’exécution du sous-
programme appelant est suspendue et le contrôle passe à la
première instruction de la fonction.
 Les paramètres peuvent eux-mêmes être des expressions
qui seront toutes évaluées avant d’entrer dans la fonction.
L’ordre d’évaluation n’est pas précisé.

Programmation langage C -
ENIT 23-24 123
Exercice

 Ecrire un programme se servant d'une


fonction MOYENNE du type float pour
afficher la moyenne arithmétique de deux
nombres réels entrés au clavier.

Programmation langage C -
ENIT 23-24 124
Récursivité(1)
 Une fonction peut s'appeler elle-même :
int factorielle(int i)
{
if (i>1)
return(i*factorielle(i-1));
else
return(1);
}
 Attention, la récursivité est gourmande en temps et
mémoire, il ne faut l'utiliser que si l'on ne sait pas
facilement faire autrement

Programmation langage C -
ENIT 23-24 125
Récursivité(2)

Appelons factorielle(3) : i=1


i=2 i=2 i=2
i=3 i=3 i=3 i=3 i=3
(a) (b) (c) (d) (e)

 (a) appel de factorielle(3), création de i, à qui on affecte la valeur 3. comme


i>1 on calcule i*factorielle(i-1) : i=3,i-1=2 on appelle factorielle(2)
 (b) création i, affecté de la valeur 2, i>1 donc on appelle factorielle(1)
 (c) création de i, i=1 donc on quitte la fonction, on libère le pile de son
sommet, on retourne où la fonction factorielle(1) a été appelée en rendant 1.
 (d) on peut maintenant calculer i*factorielle(1), i (sommet de la pile) vaut 2,
factorielle(1) vaut 1, on peut rendre 2, puis on "dépile" i
 (e) on peut calculer i*factorielle(2), i vaut 3 (sommet de la pile), factorielle(2)
vaut 2, 3*2=6, on retourne 6, la pile est vidée et retrouve son état initial.

Programmation langage C -
ENIT 23-24 126
Paramètres d’une fonction

 En C, le passage des paramètres entre le sous-


programme appelant et la fonction appelée se fait par
valeur, ce qui signifie que la fonction reçoit une copie
de toutes les valeurs transmises. Elle peut modifier ces
valeurs tant qu’elle veut,
 les valeurs originales du sous-programme appelant ne
seront pas modifiées. Par ailleurs, même si les noms
des variables sont les mêmes, il y a totale étanchéité
entre l’intérieur et l’extérieur.

Programmation langage C -
ENIT 23-24 127
Passage de paramètre à une fonction(1)

 Soit la fonction échange de valeurs de 2 variables:


void echange (int a, int b)
{
int t;
printf("debut fonction :\n a = %d \t b = %d\n",a,b);
t = a;
a = b;
b = t;
printf("fin fonction :\n a = %d \t b = %d\n",a,b);
return;
}
void main()
{
int a = 2, b = 5;
printf("debut programme principal :\n a = %d \t b = %d\n",a,b);
echange(a,b);
printf("fin programme principal :\n a = %d \t b = %d\n",a,b);
}

Programmation langage C -
ENIT 23-24 128
Passage de paramètre à une fonction(2)

 Résultat de ce programme:
debut programme principal :
a=2 b=5
debut fonction :
a=2 b=5
fin fonction :
a=5 b=2
fin programme principal :
a=2 b=5

Programmation langage C -
ENIT 23-24 129
Passage de paramètre à une fonction(3)

 Pour qu'une fonction modifie la valeur d'un de ses arguments, il faut qu'elle
ait pour paramètre l'adresse de cet objet et non sa valeur.
 Par exemple, pour échanger les valeurs de deux variables, il faut écrire :

void echange (int *adr_a, int *adr_b)


{
int t;
t = *adr_a;
*adr_a = *adr_b;
*adr_b = t;
return;
}

Programmation langage C -
ENIT 23-24 130
Passage de paramètre à une fonction(4)

 L’appel se fait donc par passer à la fonction les adresses des


variables à échanger.

void main()
{
int a = 2, b = 5;
printf("debut programme principal :\n a = %d \t b = %d\n",a,b);
echange(&a,&b);
printf("fin programme principal :\n a = %d \t b = %d\n",a,b);
}

Programmation langage C -
ENIT 23-24 131
Portée des variables
 Dans un programme C, une variable peut
être:
 Globale: définie en dehors de toute fonction, et
peut être utilisée par toutes les fonctions
 Locale: par défaut une variable locale à une
fonction est automatique. Elle est créée lors de
l’invocation de la fonction et détruite à la sortie
 Statique: c’est une variable locale à une
fonction mais qui garde sa valeur d’une
invocation à l’autre de la fonction

Programmation langage C -
ENIT 23-24 132
Portée des variables: Exemple(1)

int n; Résultat
void fonction()
{ appel numero 1
n++; appel numero 2
printf("appel numero %d\n",n); appel numero 3
return; appel numero 4
} appel numero 5
main()
{
int i;
for (i = 0; i < 5; i++)
fonction();
}

Programmation langage C -
ENIT 23-24 133
Portée des variables: Exemple(2)

int n = 10; Résultat


void fonction()
{ appel numero 1
int n = 0; appel numero 1
n++;
appel numero 1
printf("appel numero %d\n",n);
return; appel numero 1
} appel numero 1
main()
{
int i;
for (i = 0; i < 5; i++)
fonction();
}

Programmation langage C -
ENIT 23-24 134
Portée des variables: Exemple(3)
int n = 10; Résultat
void fonction()
{ appel numero 1
static int n; appel numero 2
n++; appel numero 3
printf("appel numero %d\n",n); appel numero 4
return; appel numero 5
}
main()
{
int i;
for (i = 0; i < 5; i++)
fonction();
}

Programmation langage C -
ENIT 23-24 135
Remarques

 Le programme principal main est une fonction comme


toutes les autres. Si elle a des paramètres, ils viennent
de la ligne de commande.
 Par ailleurs, la déclaration préalable des fonctions
permet de mettre les définitions des fonctions dans un
ordre quelconque, on préfère généralement mettre les
choses les plus générales au début.
 Dans un but d’économie, une fonction peut appeler
d’autres fonctions.

Programmation langage C -
ENIT 23-24 136
6. Application

Tri d’un tableau


Problème de tri(1)

 Trier un tableau: ordonner ses éléments par


ordre croissant ou ordre décroissant
 On suppose que le tableau contient des
valeurs pouvant avoir n’importe quel type
pour lequel est définie une relation d’ordre.

Programmation langage C -
ENIT 23-24 138
Problème de tri(2)

 Plusieurs méthodes de tri existent. Les plus


connues sont:
 tri par sélection
 tri par échange ou tri à bulles
 tri par insertion
 tri rapide (quick sort) ou tri par partition

Programmation langage C -
ENIT 23-24 139
Tri par sélection
 Idée : sélectionner le minimum et le déplacer au début
du tableau T (de taille N).

for (i=0 ; i < N‐1 ; i++)


{
k = i;
for ( j=i+1 ; j<N ; j=j+1)
if(T[ j ] < T[ k ])
k = j;
X = T[ i ] ; T[ i ] = T[ k ] ; T[ k ] = X ;
}

Programmation langage C -
ENIT 23-24 140
Tri par échange
 Idée : L’idée est de faire remonter les grands éléments à la fin
du tableau. Comparer toute paire d’éléments contigus et les
permuter s’ils ne sont pas dans le bon ordre. Répéter le
processus jusqu’à ce qu’il n’y ait plus de permutations.
do{
permute = 0 ;
for ( i = 0 ; i < N‐1 ; i = i+1)
if ( T[ i ] > T[ i+1 ] )
{
X = T[ i ] ; T[ i ] = T[ i+1 ] ; T[ i+1 ] = X ;
permute = 1;
}
} while ( permute) ;
Programmation langage C -
ENIT 23-24 141
Tri par insertion
 Idée : dans le tableau à insérer, on suppose qu’une partie a
été triée et qu’il reste à trier l’autre partie. Pour continuer le tri
il suffit de considérer un élément et de l’insérer au bon endroit
dans la partie triée.

for (i=1 ; i < N ; i=i+1)


{
X = T[ i ] ; j = i;
while ( X < T[j‐1] && j > 0 )
{ T[ j ] = T[j‐1]; j = j –1 ; }
T[j]=X;
}

Programmation langage C -
ENIT 23-24 142
Tri rapide(1)
 Tri récursif basé sur un partitionnement :
 on choisit un pivot,

 on permute les éléments du tableau : les petits au début, puis le

pivot, puis les grands.


 On trie les petits entre eux et les grands entre eux.

void quick_sort(int T[ ], int p, int r) {


if (r-p > 1) {
int q = partition(T,p,r);
quick_sort(T,p,q);
quick_sort(T,q+1,r);
}
}

Programmation langage C -
ENIT 23-24 143
Tri rapide(2)
int partition(int T[ ], int p, int r) {
int x = T[p]; int q = p; int i,tmp;
for (i=p+1; i<=r; i++) {
if (T[i] <= x) {
q++;
tmp = T[q]; T[q] = T[i]; T[i] = tmp;
}
}
tmp = T[q]; T[q] = T[p]; T[p] = tmp;
return q;
}

Programmation langage C -
ENIT 23-24 144
7. Les types composés
Les types composés

A partir des types prédéfinis du C


(caractères, entiers, flottants), on peut créer
de nouveaux types, appelés types
composés, qui permettent de représenter
des ensembles de données organisées:
 Les structures
 Les unions
 Les énumérations

Programmation langage C -
ENIT 23-24 146
Les types composés

Les structures
Les structures(1)
 C'est un mécanisme permettant de grouper un certain nombre de variables de types
différents au sein d'une même entité en utilisant le concept d’enregistrement.
 Un enregistrement est un ensemble d'éléments de types différents repérés par un
nom. Les éléments d'un enregistrement sont appelés des champs. Le langage C
possède le concept d'enregistrement appelé structure.
 Déclaration de structure :
 Méthode 1 : déclaration en précisant un nom pour la structure
struct personne
{
char nom[20];
char prenom[20];
int n_cin;
};
 On peut ensuite utiliser ce type structure pour déclarer des variables, de la manière
suivante :
struct personne p1,p2; /* qui déclare deux variables de type
struct personne de noms p1 et p2 */

Programmation langage C -
ENIT 23-24 148
Les structures(2)
 Méthode 2 : déclaration en précisant un nom pour la structure et en déclarant des variables
struct personne
{
char nom[20];
char prenom[20];
int n_cin;
} p1,p2;
Déclare les deux variables p1 et p2 et donne le nom personne à la structure. Là aussi, on pourra
utiliser ultérieurement le nom struct personne pour déclarer d'autres variables.

 Méthode 3 : déclaration en utilisant typedef


typedef struct personne /* le nom du type peut être omis ici si on ne va l’utiliser à
{ l’intérieur de la même structure */
char nom[10];
char prenom[10];
int n_cin;
}personne; /*il faut mettre le nom du nouveau type ici, si non à la déclaration de variable, on doit
mettre struct personne p;…*/
 Utilisation : On déclare des variables par personne et non par struct personne :
personne x,y;

Programmation langage C -
ENIT 23-24 149
Les structures(3)
 Accès aux membres d’une structure :
Pour désigner un membre d'une structure, il faut utiliser l'opérateur de sélection de
membre '.' (Point).
 Exemple:
struct personne
{
char nom[20];
char prenom[20];
int age;
};
struct personne p1,p2;
p1.age=15 ; /* accès au troisième champs + affectation */
scanf ("%s",p1.nom) ; /* lecture du premier champs */
printf("%d",p1.age) ; /* affichage du troisième champs */
p2.nom[0] = 'X';

Programmation langage C -
ENIT 23-24 150
Les structures(4)

 Initialisation d’une structure :


Exemple1:
struct personne pr1 = {"Sami", "Ben sassi", 55};
Exemple2:
struct personne pr2; /* déclaration de pr2 de type struct personne
*/
strcpy ( pr2.nom, "ahmed" ) ; /* affectation de "ahmed" au deuxième
champs */
strcpy ( pr2.prenom, "sousou" ) ;
pr2.age = 164 ;
Remarque:
On ne peut pas faire l’initialisation d’une structure lors de sa
déclaration.

Programmation langage C -
ENIT 23-24 151
Les structures(5)

 Affectation de structures:
On peut affecter une structure à une variable
structure de même type.
struct personne pr1,pr2;
pr1 = pr2 ;
 Comparaison de structures:
Aucune comparaison n'est possible sur les
structures, même pas les opérateurs == et !=.

Programmation langage C -
ENIT 23-24 152
Tableau de structures

Une déclaration de tableau de structures se fait selon le


même modèle que la déclaration d'un tableau dont les
éléments sont de type simple. Supposons que l'on ait
déjà déclaré la struct personne.
struct personne t[100]; /* dec d’un tableau de 100
structures de type struct personne */
Pour référencer le nom de la personne qui a l'index i
dans t on écrira : t[i].nom.

Programmation langage C -
ENIT 23-24 153
Composition de structures
 Composition de structures:
Une structure permet de définir un type. Ce type peut être utilisé dans la déclaration
d’une autre structure comme type d’un de ses champs.
 Exemple :
struct date
{
unsigned int jour;
unsigned int mois;
unsigned int annee ;
};
struct personne
{
char nom[20];
char prenom[20];
struct date d_naissance;
};

Programmation langage C -
ENIT 23-24 154
Exercice
Créer une structure point{int num;float x;float y;}
Saisir 4 points, les ranger dans un tableau puis les afficher.

#include <stdio.h> printf("Y= ");scanf("%f",&yy);


#include <conio.h> p[i].x = xx;p[i].y = yy;
typedef struct {int num;float x;float y;} }
point; /* affichage*/
void main() printf("\n\nAffichage\n\n");
{ for(i=0;i<4;i++)
point p[4]; /* tableau de points */ {
int i; printf("\nRELEVE N¯
float xx,yy; %1d",p[i].num);
/* saisie */ printf("\nX= %f",p[i].x);
printf("SAISIE DES POINTS\n\n"); printf("\nY= %f\n",p[i].y);
for(i=0;i<4;i++) }
{ printf("\n\nPOUR SORTIR FRAPPER
printf("\nRELEVE N¯%1d\n",i); UNE TOUCHE ");
p[i].num = i; getch();
printf("X= ");scanf("%f",&xx); }

Programmation langage C -
ENIT 23-24 155
Les énumérations
 Les énumérations permettent de définir un type par la liste des
valeurs qu’il peut prendre. Un objet de type énumération est défini
par le mot clef enum et un identificateur de modèle suivis de la liste
des valeurs que peut prendre cet objet.
 Exemple1 :
enum jour {LUNDI, MARDI, MERCREDI, JEUDI,
VENDREDI,
SAMEDI, DIMANCHE};
enum jour j1, j2;
j1 = LUNDI;
j2 = MARDI;
enum jour {LUNDI, MARDI, MERCREDI, JEUDI,
VENDREDI, SAMEDI, DIMANCHE} d1, d2;
enum {FAUX, VRAI} b1,b2; /* mauvaise programmation */
Programmation langage C -
ENIT 23-24 156
Les unions(1)
 Une union désigne un ensemble de variables de types différents susceptibles
d’occuper alternativement une même zone mémoire. Une union permet donc de
définir un objet comme pouvant être d’un type au choix parmi un ensemble fini de
types. Si les membres d’une union sont de longueurs différentes la place réservée en
mémoire pour la représenter correspond à la taille du membre le plus grand.
union jour
{
int numero;
char lettre;
};
union jour hier, demain ; /* déclaration de deux variables de type union jour */
hier.numero = 5 ;
hier.lettre=’D’ ; /* écrase la valeur précédente */
 Remarque :
La différence sémantique entre les struct et les unions est la suivante : alors que pour
une variable de type structure tous les membres peuvent avoir en même temps une
valeur, une variable de type union ne peut avoir à un instant donné qu'un seul membre
ayant une valeur.

Programmation langage C -
ENIT 23-24 157
Les unions(2)
 Utilisation des unions
enum type {ENTIER, FLOTTANT};
struct arith
{
enum type typ_val; /* indique ce qui est dans u */
union
{
int i;
float f;
} u;
};
La struct arith a deux membres typ_val de type enum, et u de type
union d'int et de float. On déclare des variables par :
struct arith a1,a2;

Programmation langage C -
ENIT 23-24 158
Les unions(3)
Puis on peut les utiliser de la manière suivante :
a1.typ_val = ENTIER;
a1.u.i = 10;
a2.typ_val = FLOTTANT;
a2.u.f = 3.14159;
 Si on passe en paramètre à une fonction un
pointeur vers une struct arith, la fonction
testera la valeur du membre typ_val pour
savoir si l'union reçue possède un entier ou
un flottant.

Programmation langage C -
ENIT 23-24 159
8. Les Pointeurs
Les Pointeurs

Notion de pointeur
Intérêt des pointeurs en C
 La plupart des langages de programmation offrent la
possibilité d'accéder aux données dans la mémoire de
l'ordinateur à l'aide de pointeurs, c.-à-d. à l'aide de
variables auxquelles on peut attribuer les adresses
d'autres variables.
 En C, les pointeurs jouent un rôle primordial dans la
définition de fonctions:
 Comme le passage des paramètres en C se fait
toujours par la valeur, les pointeurs sont le seul
moyen de changer le contenu de variables déclarées
dans d'autres fonctions.
 De même le traitement de tableaux et de chaînes de
caractères dans des fonctions serait impossible sans
l'utilisation de pointeurs

Programmation langage C -
ENIT 23-24 162
Adressage de variables

 Une variable est caractérisée par:


 son adresse: c.à.d l’adresse mémoire à partir de
laquelle l’objet est stocké.
 sa valeur, c.à.d ce qui est stocké à cette adresse.
 Deux modes d’adressage:
 Adressage direct
 Adressage indirect

Programmation langage C -
ENIT 23-24 163
Adressage direct
 La valeur d'une variable se trouve à un endroit spécifique
dans la mémoire interne de l'ordinateur. Le nom de la
variable nous permet alors d'accéder directement à cette
valeur.
 Adressage direct: Accès au contenu d'une variable par
le nom de la variable.
 Exemple:

Programmation langage C -
ENIT 23-24 164
Adressage indirect
 On peut copirer l'adresse d’une variable dans une variable
spéciale P, appelée pointeur. Ensuite, on peut retrouver
l'information de la variable A en passant par le pointeur P.
 Adressage indirect: Accès au contenu d'une variable, en
passant par un pointeur qui contient l'adresse de la variable.
 Exemple: Soit A une variable contenant la valeur 10 et P un
pointeur qui contient l'adresse de A. En mémoire, A et P
peuvent se présenter comme suit:

Programmation langage C -
ENIT 23-24 165
Pointeur
 Un pointeur est une variable spéciale qui peut contenir
l'adresse d'une autre variable.
 En C, chaque pointeur est limité à un type de données. Il peut
contenir l'adresse d'une variable simple de ce type ou l'adresse
d'une composante d'un tableau de ce type.
 Si un pointeur P contient l'adresse d'une variable A, on dit que
'P pointe sur A'.
 Remarque : Les pointeurs et les noms de variables ont le même
rôle: Ils donnent accès à un emplacement dans la mémoire
interne de l'ordinateur. Il faut quand même bien faire la
différence:
 Un pointeur est une variable qui peut 'pointer' sur différentes
adresses.
 Le nom d'une variable reste toujours lié à la même adresse.

Programmation langage C -
ENIT 23-24 166
Déclaration d'un pointeur

<Type> *<NomPointeur>
déclare un pointeur <NomPointeur> qui peut recevoir des
adresses de variables du type <Type>
 Exemple:
Signifie que
int *PNUM; *PNUM est du type int
ou
PNUM est un pointeur sur int
ou
PNUM peut contenir l'adresse d'une
variable du type int

Programmation langage C -
ENIT 23-24 167
Les opérateurs de base(1)

 Lors du travail avec des pointeurs, nous avons besoin:


 d'un opérateur 'adresse de': & pour obtenir l'adresse d'une
variable. &<NomVariable> fournit l'adresse de la variable
<NomVariable>

 d'un opérateur 'contenu de': * pour accéder au contenu d'une


adresse. *<NomPointeur> désigne le contenu de l'adresse
référencée par le pointeur <NomPointeur>

 d'une syntaxe de déclaration pour pouvoir déclarer un pointeur.

Programmation langage C -
ENIT 23-24 168
Les opérateurs de base(2)

 Exemple: Soit A une variable contenant


la valeur 10, B une variable contenant la
valeur 50 et P un pointeur non initialisé:

 Après les instructions,


P = &A;
B = *P;
*P = 20;
 P pointe sur A,
 le contenu de A (référencé par *P) est
affecté à B, et
 le contenu de A (référencé par *P) est
mis à 20.

Programmation langage C -
ENIT 23-24 169
Les opérateurs de base(3)
Le programme complet effectuant les transformations de l'exemple ci-dessus
peut se présenter comme suit:
main() Ou bien main()
{ {
/* déclarations */ /* déclarations */
short A = 10; short A, B, *P;
short B = 50; /* traitement */
short *P; A = 10;
/* traitement */ B = 50;
P = &A; P = &A;
B = *P; B = *P;
*P = 20; *P = 20;
return 0; return 0;
} }

Programmation langage C -
ENIT 23-24 170
Les opérations élémentaires sur un
pointeur(1)
Priorité de * et &
 Les opérateurs * et & ont la même priorité

que les autres opérateurs unaires (la


négation !, l'incrémentation ++, la
décrémentation --). Dans une même
expression, les opérateurs unaires *, &, !, +
+, -- sont évalués de droite à gauche.
 Si un pointeur P pointe sur une variable X,

alors *P peut être utilisé partout où on peut


écrire X.
Programmation langage C -
ENIT 23-24 171
Les opérations élémentaires sur un
pointeur(2)
Exemple
Après l'instruction P = &X; les expressions suivantes, sont
équivalentes:

Y = *P+1 Y = X+1
*P = *P+10 X = X+10
*P += 2 X += 2
++*P ++X
(*P)++ X++

les parenthèses sont nécessaires

Programmation langage C -
ENIT 23-24 172
Les opérations élémentaires sur un
pointeur(3)
Le pointeur NUL
 Seule exception: La valeur numérique 0 (zéro) est utilisée pour
indiquer qu'un pointeur ne pointe 'nulle part'.

int *P;
P = 0;
 Finalement, les pointeurs sont aussi des variables et peuvent être
utilisés comme telles. Soit P1 et P2 deux pointeurs sur int, alors
l'affectation
P1 = P2;
copie le contenu de P2 vers P1. P1 pointe alors sur le même objet
que P2.

Programmation langage C -
ENIT 23-24 173
Les opérations élémentaires sur un
pointeur(4)
Résumé:
 Après les instructions:

int A;
int *P;
P = &A;
A désigne le contenu de A et &A désigne l'adresse de A
P désigne l'adresse de A et *P désigne le contenu de A

 En outre:
&P désigne l'adresse du pointeur P
*A est illégal (puisque A n'est pas un pointeur)

Programmation langage C -
ENIT 23-24 174
Les Pointeurs

Pointeurs et tableaux
Adressage des composantes d'un tableau(1)

 Le nom d'un tableau représente l'adresse de son


premier élément. En d'autre termes:
&tableau[0] et tableau
sont une seule et même adresse.
 En simplifiant, nous pouvons retenir que le nom d'un
tableau est un pointeur constant sur le premier
élément du tableau.
 Exemple: En déclarant un tableau A de type int et un
pointeur P sur int, int A[10];
int *P;
l'instruction: P = A; est équivalente à P = &A[0];

Programmation langage C -
ENIT 23-24 176
Adressage des composantes d'un tableau(2)

 Si P pointe sur une composante quelconque d'un tableau, alors


P+1 pointe sur la composante suivante et:
P+i pointe sur la i-ième composante derrière P et
P-i pointe sur la i-ième composante devant P.

 Ainsi, après l'instruction, P = A; le pointeur P pointe sur A[0], et


*(P+1) désigne le contenu de A[1]
*(P+2) désigne le contenu de A[2]
...
...
*(P+i) désigne le contenu de A[i]

Programmation langage C -
ENIT 23-24 177
Adressage des composantes d'un tableau(3)

 Exemple
Soit A un tableau contenant des éléments de type
float et P un pointeur sur float:
float A[20], X;
float *P;
Après les instructions,
P = A;
X = *(P+9);
X contient la valeur du 10-ième élément de A, (c.-à-d.
celle de A[9]). Une donnée du type float ayant besoin
de 4 octets, le compilateur obtient l'adresse P+9 en
ajoutant 9 * 4 = 36 octets à l'adresse dans P.

Programmation langage C -
ENIT 23-24 178
Adressage des composantes d'un tableau(4)

Différence essentielle entre un pointeur et le nom d'un tableau:


 Un pointeur est une variable,
donc des opérations comme P = A ou P++ sont permises.
Le nom d'un tableau est une constante,
donc des opérations comme A = P ou A++ sont impossibles.

 Lors de la première phase de la compilation, toutes les expressions de la


forme A[i] sont traduites en *(A+i). En multipliant l'indice i par la grandeur
d'une composante, on obtient un indice en octets:
<indice en octets> = <indice élément> * <grandeur élément>
Cet indice est ajouté à l'adresse du premier élément du tableau pour obtenir
l'adresse de la composante i du tableau. Pour le calcul d'une adresse
donnée par une adresse plus un indice en octets, on utilise un mode
d'adressage spécial connu sous le nom 'adressage indexé':
<adresse indexée> = <adresse> + <indice en octets>

Programmation langage C -
ENIT 23-24 179
Adressage des composantes d'un tableau(5)

Formalisme tableau et formalisme pointeur


• Exemple: Les deux programmes suivants copient les éléments positifs d'un
tableau T dans un deuxième tableau POS.
Formalisme tableau Formalisme pointeur
main() main()
{ {
int T[10] = {-3, 4, 0, -7, 3, 8, 0, -1, 4, -9} ; int T[10] = {-3, 4, 0, -7, 3, 8, 0, -1, 4, -9} ;
int POS[10]; int POS[10];
int I,J; int I,J;
for (J=0,I=0 ; I<10 ; I++) for (J=0,I=0 ; I<10 ; I++)
if (T[I]>0) { if (*(T+I)>0) {
POS[J] = T[I]; *(POS+J) = *(T+I);
J++; J++;
} }
return 0; return 0;
} }

Programmation langage C -
ENIT 23-24 180
Résumons
 Les variables et leur utilisation int A; déclare une variable
simple du type int
A désigne le contenu de A
&A désigne l'adresse de A

int B[]; déclare un tableau d'éléments de type int


B désigne l'adresse de la première composante de B.
(Cette adresse est toujours constante)

B[i] désigne le contenu de la composante i du tableau


&B[i] désigne l'adresse de la composante i du tableau
en utilisant le formalisme pointeur:

B+i désigne l'adresse de la composante i du tableau


*(B+i) désigne le contenu de la composante i du tableau

Programmation langage C -
ENIT 23-24 181
Résumons
int *P;
déclare un pointeur sur des éléments du type int.
P peut pointer sur des variables simples du type int ou sur les
composantes d'un tableau du type int.
P désigne l'adresse contenue dans P
(Cette adresse est variable)

*P désigne le contenu de l'adresse dans P


Si P pointe dans un tableau, alors

P désigne l'adresse de la première composante


P+i désigne l'adresse de la i-ième composante derrière P
*(P+i) désigne le contenu de la i-ième composante derrière P

Programmation langage C -
ENIT 23-24 182
Les Pointeurs

Arithmétique des pointeurs


Arithmétique des pointeurs(1)

 Affectation par un pointeur sur le même type


Soient P1 et P2 deux pointeurs sur le même type de
données, alors l'instruction
P1 = P2;
fait pointer P1 sur le même objet que P2

 Addition et soustraction d'un nombre entier


Si P pointe sur l'élément A[i] d'un tableau, alors
P+n pointe sur A[i+n]
P-n pointe sur A[i-n]

Programmation langage C -
ENIT 23-24 184
Arithmétique des pointeurs(2)

 Incrémentation et décrémentation d'un pointeur


Si P pointe sur l'élément A[i] d'un tableau, alors après
l'instruction

P++; P pointe sur A[i+1]


P+=n; P pointe sur A[i+n]
P--; P pointe sur A[i-1]
P-=n; P pointe sur A[i-n]

Programmation langage C -
ENIT 23-24 185
Arithmétique des pointeurs(3)

 Domaine des opérations


 L'addition, la soustraction, l'incrémentation et la décrémentation sur les
pointeurs sont seulement définies à l'intérieur d'un tableau. Si l'adresse
formée par le pointeur et l'indice sort du domaine du tableau, alors le résultat
n'est pas défini.
 Seule exception: Il est permis de 'pointer' sur le premier octet derrière un tableau
(à condition que cet octet se trouve dans le même segment de mémoire que le
tableau). Cette règle, introduite avec le standard ANSI-C, légalise la définition de
boucles qui incrémentent le pointeur avant l'évaluation de la condition d'arrêt.
 Exemples:
int A[10];
int *P;
P = A+9; /* dernier élément -> légal */
P = A+10; /* dernier élément + 1 -> légal */
P = A+11; /* dernier élément + 2 -> illégal */
P = A-1; /* premier élément - 1 -> illégal */

Programmation langage C -
ENIT 23-24 186
Arithmétique des pointeurs(4)

 Soustraction de deux pointeurs


Soient P1 et P2 deux pointeurs qui pointent dans le même
tableau: P1-P2
fournit le nombre de composantes comprises entre P1 et P2.
Le résultat de la soustraction P1-P2 est

- négatif, si P1 précède P2
- zéro, si P1 = P2
- positif, si P2 precède P1
- indéfini, si P1 et P2 ne pointent pas dans le même tableau

Plus généralement, la soustraction de deux pointeurs qui pointent


dans le même tableau est équivalente à la soustraction des
indices correspondants.

Programmation langage C -
ENIT 23-24 187
Arithmétique des pointeurs(5)

 Comparaison de deux pointeurs


On peut comparer deux pointeurs par
<, >, <=, >=, ==, !=.
La comparaison de deux pointeurs qui pointent dans le
même tableau est équivalente à la comparaison des
indices correspondants. (Si les pointeurs ne pointent pas
dans le même tableau, alors le résultat est donné par
leurs positions relatives dans la mémoire).

Programmation langage C -
ENIT 23-24 188
Les Pointeurs

Pointeurs et chaînes de caractères


Pointeurs sur char et chaînes de caractères constantes(1)

De la même façon qu'un pointeur sur int peut contenir l'adresse d'un nombre isolé ou
d'une composante d'un tableau, un pointeur sur char peut pointer sur un caractère
isolé ou sur les éléments d'un tableau de caractères. Un pointeur sur char peut en
plus contenir l'adresse d'une chaîne de caractères constante et il peut même être
initialisé avec une telle adresse.
 Affectation
On peut attribuer l'adresse d'une chaîne de caractères constante à un pointeur sur
char:
Exemple
char *C;
C = "Ceci est une chaîne de caractères constante";

 Nous pouvons lire cette chaîne constante (p.ex: pour l'afficher), mais il n'est pas
recommandé de la modifier, parce que le résultat d'un programme qui essaie de
modifier une chaîne de caractères constante n'est pas prévisible en ANSI-C.

Programmation langage C -
ENIT 23-24 190
Pointeurs sur char et chaînes de caractères constantes(2)

 Initialisation
Un pointeur sur char peut être initialisé lors de la déclaration si on lui affecte l'adresse
d'une chaîne de caractères constante:
char *B = "Bonjour !";
Remarque:
 Il existe une différence importante entre les deux déclarations:
char A[] = "Bonjour !"; /* un tableau */
char *B = "Bonjour !"; /* un pointeur */
 A est un tableau qui a exactement la grandeur pour contenir la chaîne de
caractères et la terminaison '\0'. Les caractères de la chaîne peuvent être
changés, mais le nom A va toujours pointer sur la même adresse en
mémoire.
 B est un pointeur qui est initialisé de façon à ce qu'il pointe sur une chaîne
de caractères constante stockée quelque part en mémoire. Le pointeur peut
être modifié et pointer sur autre chose. La chaîne constante peut être lue,
copiée ou affichée, mais pas modifiée

Programmation langage C -
ENIT 23-24 191
Pointeurs sur char et chaînes de caractères constantes(3)

 Modification
Si nous affectons une nouvelle valeur à un pointeur sur une chaîne
de caractères constante, nous risquons de perdre la chaîne
constante. D'autre part, un pointeur sur char a l'avantage de pouvoir
pointer sur des chaînes de n'importe quelle longueur:
Exemple
char *A = "Petite chaîne";
char *B = "Deuxième chaîne un peu plus longue";
A = B;
Maintenant A et B pointent sur la même chaîne; la "Petite chaîne" est
perdue:

Programmation langage C -
ENIT 23-24 192
Pointeurs sur char et chaînes de caractères constantes(4)

 Remarque:
Les affectations discutées ci-dessus ne peuvent pas être effectuées avec des tableaux de
caractères:
Exemple
char A[45] = "Petite chaîne";
char B[45] = "Deuxième chaîne un peu plus longue";
char C[30];
A = B; /* IMPOSSIBLE -> ERREUR !!! */
C = "Bonjour !"; /* IMPOSSIBLE -> ERREUR !!! */

 Dans cet exemple, nous essayons de copier l'adresse de B dans A, respectivement l'adresse de
la chaîne constante dans C. Ces opérations sont impossibles et illégales parce que l'adresse
représentée par le nom d'un tableau reste toujours constante.
 Pour changer le contenu d'un tableau, nous devons changer les composantes du tableau l'une
après l'autre (p.ex. dans une boucle) ou déléguer cette charge à une fonction de <stdio> ou
<string>.

Programmation langage C -
ENIT 23-24 193
Pointeurs sur char et chaînes de caractères constantes(5)

 Conclusions:
 Utilisons des tableaux de caractères pour déclarer
les chaînes de caractères que nous voulons
modifier.
 Utilisons des pointeurs sur char pour manipuler
des chaînes de caractères constantes (dont le
contenu ne change pas).
 Utilisons de préférence des pointeurs pour
effectuer les manipulations à l'intérieur des
tableaux de caractères.
Programmation langage C -
ENIT 23-24 194
Les Pointeurs
Pointeurs et tableaux à
deux dimensions
Pointeurs et tableaux à deux dimensions(1)

 L'arithmétique des pointeurs se laisse élargir avec toutes ses


conséquences sur les tableaux à deux dimensions.
 Exemple
Le tableau M à deux dimensions est défini comme suit:
int M[4][10] = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10,11,12,13,14,15,16,17,18,19},
{20,21,22,23,24,25,26,27,28,29},
{30,31,32,33,34,35,36,37,38,39}};
Le nom du tableau M représente l'adresse du premier élément du
tableau et pointe sur le tableau M[0] qui a la valeur:
{0,1,2,3,4,5,6,7,8,9}.
L'expression (M+1) est l'adresse du deuxième élément du tableau
et pointe sur M[1] qui a la valeur: {10,11,12,13,14,15,16,17,18,19}.

Programmation langage C -
ENIT 23-24 196
Pointeurs et tableaux à deux dimensions(2)

 Problème
Comment pouvons-nous accéder à l'aide de pointeurs aux éléments de
chaque composante du tableau, c.à-d.: aux éléments M[0][0], M[0][1], ... ,
M[3][9] ?
 Discussion
Une solution consiste à convertir la valeur de M (qui est un pointeur sur un
tableau du type int) en un pointeur sur int. Par exemple:
int M[4][10] = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10,11,12,13,14,15,16,17,18,19},
{20,21,22,23,24,25,26,27,28,29},
{30,31,32,33,34,35,36,37,38,39}};
int *P;
P = M; /* conversion automatique */
Cette dernière affectation entraîne une conversion automatique de l'adresse
&M[0] dans l'adresse &M[0][0]. (Remarquez bien que l'adresse transmise reste la
même, seule la nature du pointeur a changé).

Programmation langage C -
ENIT 23-24 197
Pointeurs et tableaux à deux dimensions(3)

 Cette solution n'est pas satisfaisante à cent pour-cent: Généralement, on


gagne en lisibilité en explicitant la conversion mise en oeuvre par
l'opérateur de conversion forcée ("cast"), qui évite en plus des messages
d'avertissement de la part du compilateur.
 Solution
Voici finalement la version que nous utiliserons:
int M[4][10] = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10,11,12,13,14,15,16,17,18,19},
{20,21,22,23,24,25,26,27,28,29},
{30,31,32,33,34,35,36,37,38,39}};
int *P;
P = (int *)M; /* conversion forcée */

Dû à la mémorisation ligne par ligne des tableaux à deux dimensions, il


nous est maintenant possible traiter M à l'aide du pointeur P comme un
tableau unidimensionnel de dimension 4*10.

Programmation langage C -
ENIT 23-24 198
Pointeurs et tableaux à deux dimensions(4)

 Exemple
Les instructions suivantes calculent la somme de tous les éléments du tableau M:
int M[4][10] = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10,11,12,13,14,15,16,17,18,19},
{20,21,22,23,24,25,26,27,28,29},
{30,31,32,33,34,35,36,37,38,39}};
int *P;
int I, SOM;
P = (int*)M;
SOM = 0;
for (I=0; I<40; I++)
SOM += *(P+I);

 Remarque:
Lors de l'interprétation d'un tableau à deux dimensions comme tableau
unidimensionnel il faut calculer avec le nombre de colonnes indiqué dans la
déclaration du tableau.

Programmation langage C -
ENIT 23-24 199
Les Pointeurs

Tableaux de pointeurs
Tableaux de pointeurs(1)
 Si nous avons besoin d'un ensemble de pointeurs du même type, nous pouvons les
réunir dans un tableau de pointeurs.
 Déclaration d'un tableau de pointeurs
<Type> *<NomTableau>[<N>]
déclare un tableau <NomTableau> de <N> pointeurs sur des données du type
<Type>.
Exemple
double *A[10];
déclare un tableau de 10 pointeurs sur des rationnels du type double dont les
adresses et les valeurs ne sont pas encore définies.
 Remarque
Le plus souvent, les tableaux de pointeurs sont utilisés pour mémoriser de façon
économique des chaînes de caractères de différentes longueurs. Dans la suite, nous
allons surtout considérer les tableaux de pointeurs sur des chaînes de caractères.
 Initialisation
Nous pouvons initialiser les pointeurs d'un tableau sur char par les adresses de
chaînes de caractères constantes.

Programmation langage C -
ENIT 23-24 201
Tableaux de pointeurs(2)
 Exemple
char *JOUR[] = {"dimanche", "lundi", "mardi", "mercredi", "jeudi",
"vendredi", "samedi"};
déclare un tableau JOUR[] de 7 pointeurs sur char. Chacun des pointeurs
est initialisé avec l'adresse de l'une des 7 chaînes de caractères.

Programmation langage C -
ENIT 23-24 202
Tableaux de pointeurs(3)
 On peut afficher les 7 chaînes de caractères en fournissant les adresses
contenues dans le tableau JOUR à printf :
int I;
for (I=0; I<7; I++)
printf("%s\n", JOUR[I]);

Comme JOUR[I] est un pointeur sur char, on peut afficher les premières
lettres des jours de la semaine en utilisant l'opérateur 'contenu de' :
int I;
for (I=0; I<7; I++)
printf("%c\n", *JOUR[I]);

L'expression JOUR[I]+J désigne la J-ième lettre de la I-ième chaîne. On peut


afficher la troisième lettre de chaque jour de la semaine par:
int I;
for (I=0; i<7; I++)
printf("%c\n",*(JOUR[I]+2));

Programmation langage C -
ENIT 23-24 203
Tableaux de pointeurs(4)
int *D[]; déclare un tableau de pointeurs sur des éléments du type int

D[i] peut pointer sur des variables simples ou


sur les composantes d'un tableau.

D[i] désigne l'adresse contenue dans l'élément i de D


(Les adresses dans D[i] sont variables)

*D[i] désigne le contenu de l'adresse dans D[i]

Si D[i] pointe dans un tableau,


D[i] désigne l'adresse de la première composante
D[i]+j
désigne l'adresse de la j-ième composante
*(D[i]+j)
désigne le contenu de la j-ième composante

Programmation langage C -
ENIT 23-24 204
Les Pointeurs
Allocation dynamique
de mémoire
Déclaration statique de données(1)
 Chaque variable dans un programme a besoin d'un certain nombre
d'octets en mémoautomatiquement ire. Jusqu'ici, la réservation de la
mémoire s'est déroulée par l'emploi des déclarations des données.
Dans tous ces cas, le nombre d'octets à réserver était déjà connu
pendant la compilation. Nous parlons alors de la déclaration
statique des variables.
 Exemples
float A, B, C; /* réservation de 12 octets */
short D[10][20]; /* réservation de 400 octets */
char E[] = {"Bonjour !"}; /* réservation de 10 octets */
char F[][10] = {"un", "deux", "trois", "quatre"}; /* réservation de
40 octets
*/

Programmation langage C -
ENIT 23-24 206
Déclaration statique de données(2)

 Pointeurs
Le nombre d'octets à réserver pour un pointeur dépend
de la machine et du 'modèle' de mémoire choisi, mais il
est déjà connu lors de la compilation. Un pointeur est
donc aussi déclaré statiquement. Supposons dans la
suite qu'un pointeur ait besoin de p octets en mémoire.
(En DOS: p =2 ou p = 4)
 Exemples
double *G; /* réservation de p octets */
char *H; /* réservation de p octets
*/
float *I[10]; /* réservation de 10*p octets */

Programmation langage C -
ENIT 23-24 207
Allocation dynamique

 Problème
Souvent, nous devons travailler avec des données dont nous ne pouvons pas prévoir
le nombre et la grandeur lors de la programmation. Ce serait alors un gaspillage de
réserver toujours l'espace maximal prévisible. Il nous faut donc un moyen de gérer la
mémoire lors de l'exécution du programme.
 Exemple
Nous voulons lire 10 phrases au clavier et mémoriser les phrases en utilisant un
tableau de pointeurs sur char. Nous déclarons ce tableau de pointeurs par:
char *TEXTE[10];
Pour les 10 pointeurs, nous avons besoin de 10*p octets. Ce nombre est connu dès le
départ et les octets sont réservés automatiquement. Il nous est cependant impossible
de prévoir à l'avance le nombre d'octets à réserver pour les phrases elles-mêmes qui
seront introduites lors de l'exécution du programme ...
 Allocation dynamique
La réservation de la mémoire pour les 10 phrases peut donc seulement se faire
pendant l'exécution du programme. Nous parlons dans ce cas de l'allocation
dynamique de la mémoire.

Programmation langage C -
ENIT 23-24 208
La fonction malloc

 La fonction malloc de la bibliothèque <stdlib> nous aide à localiser et à réserver de la


mémoire au cours d'un programme.
 syntaxe
malloc( <N> )
fournit l'adresse d'un bloc en mémoire de <N> octets libres ou la valeur zéro s'il
n'y a pas assez de mémoire.
 Remarque:
Sur notre système, le paramètre <N> est du type unsigned int. A l'aide de malloc,
nous ne pouvons donc pas réserver plus de 65535 octets à la fois!
 Exemple: Supposons que nous avons besoin d'un bloc en mémoire pour un texte de
4000 caractères. Nous disposons d'un pointeur T sur char (char *T). Alors
l'instruction:
T = malloc(4000);
fournit l'adresse d'un bloc de 4000 octets libres et l'affecte à T.
S'il n'y a plus assez de mémoire, T obtient la valeur zéro.
 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 grandeur effective d'une
donnée de ce type. L'opérateur sizeof nous aide alors à préserver la portabilité du
programme.

Programmation langage C -
ENIT 23-24 209
L'opérateur unaire sizeof(1)

sizeof <var> fournit la grandeur de la variable <var>


sizeof <const> fournit la grandeur de la constante <const>
sizeof (<type>) fournit la grandeur pour un objet du type <type>
 Exemple
Après la déclaration,
short A[10];
char B[5][10];
nous obtenons les résultats suivants sur un IBM-PC (ou compatible):

sizeof A s'évalue à 20
sizeof B s'évalue à 50
sizeof 4.25 s'évalue à 8
sizeof "Bonjour !" s'évalue à 10
sizeof(float) s'évalue à 4
sizeof(double) s'évalue à 8

Programmation langage C -
ENIT 23-24 210
L'opérateur unaire sizeof(2)
 Exemple
Nous voulons réserver de la mémoire pour X valeurs du type int; la
valeur de X est lue au clavier:
int X;
int *PNum;
printf("Introduire le nombre de valeurs :");
scanf("%d", &X);
PNum = malloc(X*sizeof(int));

 exit
S'il n'y a pas assez de mémoire pour effectuer une action avec
succès, il est conseillé d'interrompre l'exécution du programme à
l'aide de la commande exit (de <stdlib>) et de renvoyer une valeur
différente de zéro comme code d'erreur du programme.

Programmation langage C -
ENIT 23-24 211
Exemple(1)
 Le programme suivant lit 10 phrases au clavier, recherche des blocs
de mémoire libres assez grands pour la mémorisation et passe les
adresses aux composantes du tableau TEXTE[]. S'il n'y a pas assez
de mémoire pour une chaîne, le programme affiche un message
d'erreur et interrompt le programme avec le code d'erreur -1.
 Nous devons utiliser une variable d'aide INTRO comme zone
intermédiaire (non dynamique). Pour cette raison, la longueur
maximale d'une phrase est fixée à 500 caractères.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main() {
/* Déclarations */
char INTRO[500];
char *TEXTE[10];
int I;

Programmation langage C -
ENIT 23-24 212
Exemple(2)

/* Traitement */
for (I=0; I<10; I++) {
gets(INTRO);
/* Réservation de la mémoire */
TEXTE[I] = malloc(strlen(INTRO)+1);
/* S'il y a assez de mémoire, ... */
if (TEXTE[I]) /* copier la phrase à l'adresse fournie par malloc, ... */
strcpy(TEXTE[I], INTRO);
else { /* sinon quitter le programme après un message d'erreur. */
printf("ERREUR: Pas assez de mémoire \n");
exit(-1);
}
}
return 0; }

Programmation langage C -
ENIT 23-24 213
Remarques(1)

 Dans le programme :
#include <stdio.h>
main()
{
int i ;
int *p ;
p=&i ;
}
i et *p sont identiques et on n’a pas besoin d’allocation
dynamique puisque l’espace mémoire à l’adresse &i est
déjà réservé pour un entier.

Programmation langage C -
ENIT 23-24 214
Remarques(2)

 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 à 0. Sa
syntaxe est la suivante :
calloc( nb_objets, taille_objet_octets)
 Exemple :
Int n=10;
Int *p ;
p= (int*) calloc (n, sizeof(int)); /* tableau de n entiers*/
 Est équivalent à:
Int n=10;
Int *p ;
p= (int*) malloc (n * sizeof(int)); /* tableau de n entiers*/
For (i=0; i<n; i++)
*(p+i)=0;

Programmation langage C -
ENIT 23-24 215
La fonction free
 Si nous n'avons plus besoin d'un bloc de mémoire que nous avons
réservé à l'aide de malloc, alors nous pouvons le libérer à l'aide de
la fonction free de la bibliothèque <stdlib>.
free( <Pointeur> )
libère le bloc de mémoire désigné par le <Pointeur>; n'a pas d'effet
si le pointeur a la valeur zéro.
 Remarque:
 La fonction free peut aboutir à un désastre si on essaie de libérer de la
mémoire qui n'a pas été allouée par malloc.
 La fonction free ne change pas le contenu du pointeur; il est conseillé
d'affecter la valeur zéro au pointeur immédiatement après avoir libéré le
bloc de mémoire qui y était attaché.
 Si nous ne libérons pas explicitement la mémoire à l'aide de free, alors
elle est libérée automatiquement à la fin du programme.

Programmation langage C -
ENIT 23-24 216
Les Pointeurs

Pointeurs et structures
Pointeur et structures
 Pointeur et structures:
Supposons que l'on ait défini la struct personne à l'aide de la déclaration :
struct personne
{
char nom[20] ;
unsigned int age ;
};
On déclare une variable de type pointeur vers une telle structure de la manière
suivante :
struct personne *p ;
On peut alors affecter à p des adresses de struct personne. Exemple :
struct personne pers; /* pers est une variable de type struct personne */
struct personne *p; /* p est un pointeur vers une struct personne */
p = &pers;
(*p).age=20 ; /* parenthèses obligatoires OU */
p -> age=22 ; /* -> opérateur d’accès */

Programmation langage C -
ENIT 23-24 218
Listes chaînées
Une des utilisations fréquentes des structures, est de créer des
listes de structures chaînées. Pour cela, il faut que chaque
structure contienne un membre qui soit de type pointeur vers une
structure du même type. Cela se fait de la façon suivante :
struct personne
{
char nom[20] ;
unsigned int age ;
struct personne *suivant ;
};
Le membre de nom suivant est déclaré comme étant du type
pointeur vers une struct personne. La dernière structure de la liste
devra avoir un membre suivant dont la valeur sera le pointeur
NULL.

Programmation langage C -
ENIT 23-24 219
Allocation et libération d'espace pour les
structures
 Allocation et libération d'espace pour les structures
Quand on crée une liste chaînée, c'est parce qu'on ne sait pas à la
compilation combien elle comportera d'éléments à l'exécution (sinon
on utiliserait un tableau). Pour pouvoir créer des listes, il est donc
nécessaire de pouvoir allouer de l'espace dynamiquement. On
dispose pour cela de deux fonctions malloc et calloc.
 La fonction malloc admet un paramètre qui est la taille en octets de
l'élément désiré et elle rend un pointeur vers l'espace alloué.
Utilisation typique :
struct personne *p ;
p = malloc(sizeof(struct personne));

Programmation langage C -
ENIT 23-24 220
Exemple
 Exemple de liste simplement //Ajout d’un nouvel element
chaînée : void AjoutTete (List **L, int n) {
List *c = nouv(n) ;
#include <stdio.h> c->suiv = *L;
#include <stdlib.h> *L = c ;
typedef struct List { c=NULL;
int val; }
struct List *suiv; void main () {
} List; List *lst = NULL;
//Construction d’un nouvel élément int i;
List *nouv(int n){ for(i=1;i<=5;i++){
List *c = (List *)malloc(sizeof(List)); AjoutTete (&lst,
i*i);
c->val = n; if (lst==NULL)
c->suiv = NULL; printf("liste vide");
return c; else
} printf("%d\n",lst-
>val);
}
}
Programmation langage C -
ENIT 23-24 221
9. Application

Piles et Files
Les piles

Programmation langage C -
ENIT 23-24 223
Pile(1)
 Ex : pile d'assiettes, pile de dossiers à traiter, …
 Une pile est une structure linéaire permettant de stocker et
de restaurer des données en n’autorisant que 4 opérations:
1. consulter le dernier élément de la pile (le sommet de la
pile)
2. tester si la pile es vide
3. empiler un élément, le mettre au sommet de la pile
==> PUSH
4. dépiler un élément (enlever l’élément au sommet)
==> POP

Programmation langage C -
ENIT 23-24 224
Pile(2)

 Toutes les opérations sont effectuées sur la


même extrémité; on parle de structure en
LIFO (Last In First Out)).

Programmation langage C -
ENIT 23-24 225
Exemple de Pile
Empiler B
Empiler A
Empiler E Dépiler D
Empiler C
Empiler D

Programmation langage C -
ENIT 23-24 226
Implémentation de la structure Pile à
l’aide d’une liste chaînée(1)
// Définition du type Pile
typedef int Element; /* les éléments sont des int */
typedef struct cellule {
Element valeur;
struct cellule *suivant;
} Cellule;
typedef Cellule *Pile;
// Déclaration des fonctions gérant la pile
Pile pile_vide ();
Pile empiler ( Pile p, Element e );
Pile depiler ( Pile p );
Element sommet ( Pile p );
int est_vide ( Pile p );

Programmation langage C -
ENIT 23-24 227
Implémentation de la structure Pile à
l’aide d’une liste chaînée(2)
Pile empiler(Pile p, Element e) {
Pile pile_vide(void) { Cellule * pc;
return NULL; pc=(Cellule*)malloc(sizeof
} (Cellule));
int est_vide(Pile p) { pc->valeur=e;
return (p == NULL); pc->suivant=p;
} return pc;
}
Element sommet(Pile p) {
/* pré-condition: pile non Pile depiler(Pile p) {
vide ! */ Cellule * pc = p;
if (est_vide(p)) { if (est_vide(p)) {
printf("Erreur: pile printf("Erreur: pile vide!\n");
vide !\n"); exit(-1);
exit(-1);
} }
return p->valeur; p=p->suivant;
} free(pc);
return p;
}
Programmation langage C -
ENIT 23-24 228
Implémentation de la structure Pile à
l’aide d’une liste chaînée(3)
//Exemple d’utilisation
int main () {
Pile p = pile_vide();

p = empiler(p,50);
p = empiler(p,5);
p = empiler(p,20);
p = empiler(p,10);
printf("%d au sommet après empilement de 50, 5, 20 et 10\n", sommet(p));
p = depiler(p);
p = depiler(p);
printf("%d au sommet après dépilement de 10 et 20\n", sommet(p));
return 0;
}

Programmation langage C -
ENIT 23-24 229
Les files

Programmation langage C -
ENIT 23-24 230
File(1)
 Ex: File d'attente à un guichet, file de documents à imprimer, …
 Une file est une structure de données dynamique dans laquelle
on insère des nouveaux éléments à la fin (queue) et où on enlève
des éléments au début (tête de file).
 L’application la plus classique est la file d’attente, et elle sert
beaucoup en simulation. Elle est aussi très utilisée aussi bien
dans la vie courante que dans les systèmes informatiques. Par
exemple, elle modélise la file d’attente des clients devant un
guichet, les travaux en attente d’exécution dans un système de
traitement par lots, ou encore les messages en attente dans un
commutateur de réseau téléphonique.

Programmation langage C -
ENIT 23-24 231
File(2)
 On retrouve également les files d’attente dans les
programmes de traitement de transactions telle que les
réservations de sièges d’avion ou de billets de théâtre.
 Dans une file, le premier élément inséré est aussi le
premier retiré. On parle de mode d’accès FIFO (First In
Fist Out).

 La file est modifiée à ses deux bouts.

Programmation langage C -
ENIT 23-24 232
File(3)

 Quatre opérations de base:


1. consulter le premier élément de la file
2. tester si la file est vide
3. enfiler un nouvel élément: le mettre en dernier
4. défiler un élément, le premier (le supprimer)

Programmation langage C -
ENIT 23-24 233
Implémentation de la structure File à
l’aide d’une liste chaînée(1)
// Définition du type File
typedef int Element; /* les éléments sont des int */

typedef struct cellule {


Element valeur;
struct cellule *suivant;
} Cellule;

typedef struct {
struct cellule *tete;
struct cellule *queue;
} File;

// Déclaration des fonctions gérant la file


File file_vide ();
File enfiler ( File f, Element e );
File defiler ( File f );
Element tete ( File f );
int est_vide ( File f );

Programmation langage C -
ENIT 23-24 234
Implémentation de la structure File à
l’aide d’une liste chaînée(2) File enfiler(File f, Element e) {
Cellule * pc;
pc=(Cellule *)malloc(sizeof(Cellule));
File file_vide() { pc->valeur=e;
File f; pc->suivant=NULL;
f.tete=f.queue=NULL; if (est_vide(f)
return f; f.tete=f.queue=pc;
} else f.queue=(f.queue)->suivant=pc;
return f;
int est_vide(File f) { }
return
(f.tete==NULL)&&(f.queue==NULL);
}
File defiler(File f) {
Cellule * pc;
Element tete(File f) {
if (est_vide(f)) {
/* pré-condition: file non vide ! */
printf("Erreur: file vide !\n");
if (est_vide(f)) {
exit(-1);
printf("Erreur: file vide !\n");
}
exit(-1);
pc=f.tete;
}
f.tete=(f.tete)->suivant;
return (f.tete)->valeur;
free(pc);
}
if (f.tete==NULL) f.queue=NULL;
return f;
}

Programmation langage C -
ENIT 23-24 235
10. Les chaînes de
caractères
Chaînes de caractères(1)

 Il n’y a pas de type chaîne de caractères prédéfini en C. Par


convention, les chaînes de caractères sont représentées à
l’aide de tableaux de caractères à un indice. Malgré cela, la
manipulation des chaînes de caractères est très souple et très
efficace en C.
 Le principe est le suivant, dans un tableau suffisamment grand,
on stocke à la suite les différents caractères de la chaîne. A la
fin de la chaîne, on rajoute un caractère supplémentaire qui fait
office de marqueur de fin de chaîne. C’est le caractère dont le
code ASCII est zéro, que l’on note ’\0’. Attention toutefois à ne
pas le confondre avec le caractère ’0’ dont le code ASCII est
48!

Programmation langage C -
ENIT 23-24 237
Chaînes de caractères(2)

 Les caractères stockés dans la suite du tableau seront


tout simplement ignorés de toutes les fonctions, la
convention voulant que le caractère ’\0’ soit le dernier de la
chaîne.
 De plus, si une erreur entraîne l’absence de ce marqueur,
les fonctions de manipulation de chaînes de caractères
fonctionneront anormalement, puisqu’elles ne le trouveront
pas.
 L’inconvénient de cette technique est qu’il faut toujours se
souvenir qu’un tableau de N positions ne peut contenir au
maximum qu’une chaîne de longueur N-1, le dernier
élément du tableau devant forcément contenir le marqueur
de fin de chaîne.

Programmation langage C -
ENIT 23-24 238
Chaînes de caractères(3)

 La déclaration d’une chaîne de caractère se fait par l’une des méthodes


suivantes :
char NomChaine [Longueur];
OU
char * NomChaine ;
 Exemples:
 char string[10]; /* définit une chaîne de 9 caractères */
 char nom[20] = "ahmed"; /* déclaration avec initialisation */
 char chaine1 [] = { ‘t’, ‘o’, ‘t’ , ‘o’ , ’\0’} ; /* déclaration avec initialisation */
 char chaine2 [20] = {‘t’, ‘o’, ‘t’ , ‘o’ , ’\0’} ; /* déclaration avec initialisation */
 char * CH1 ; /* déclaration sans initialisation */
 char * CH2= " toto" ; /* déclaration avec initialisation */
 CH1 = "salut tou" /* affectation permise*/
 nom = "chaine"; /*affectation non permise
 char PHRASE [300]; /* déclaration sans initialisation */

Programmation langage C -
ENIT 23-24 239
Chaînes de caractères(4)

 L'accès à un élément d'une chaîne de caractères peut se faire de


la même façon que l'accès à un élément d'un tableau. En déclarant
une chaîne par: char A[6];
nous avons défini un tableau A avec six éléments, auxquels on peut
accéder par: A[0], A[1], ... , A[5]
Exemple

Programmation langage C -
ENIT 23-24 240
Chaînes de caractères(5)

Remarques
 Lorsque le compilateur rencontre une chaîne de caractères constante, il la
convertit automatiquement en tableau et rajoute le caractère nul (’\0’) à la fin.
 Tout comme les tableaux, il n’y a pas d’opérations globales sur les chaînes
(affectation, comparaison, concaténation) dans le langage, il y a par
contre de nombreuses fonctions qui assurent ces tâches.
 La seule exception est pour l’initialisation, une chaîne peut être initialisée par
une chaîne constante lors de sa définition comme on peut le voir dans les
exemples ci-dessus. Par ailleurs, le compilateur peut calculer la longueur
d’une chaîne facilement. On peut donc omettre la longueur de la chaîne entre
les crochets si on veut qu’elle soit ajustée automatiquement.
 Les caractères d’interligne que l’on trouve dans le dernier exemple occupent
deux caractères dans le texte du programme : \ et n. Dans le programme
exécutable et en mémoire centrale, ils n’occupent par contre plus qu’un seul
octet.

Programmation langage C -
ENIT 23-24 241
Lecture/Ecriture de chaînes(1)

LECTURE
scanf()
 Cette fonction permet de lire une chaîne de caractères en spécifiant
un %s dans la chaîne de format.
 Son mécanisme de découpage ne permet toutefois pas de taper des
chaînes de caractères contenant des blancs ou des tabulations. La
lecture se termine aussitôt qu’un caractère séparateur est rencontré.
 Par ailleurs, il ne faut pas utiliser l’opérateur adresse & lors de la
lecture d’une chaîne de caractères, les tableaux étant de toute façon
passés par référence.

Programmation langage C -
ENIT 23-24 242
Lecture/Ecriture de
chaînes(2)
 On préfère généralement la fonction
gets(chaine)
 Cette fonction lit une chaîne depuis le flux d’entrée
standard stdin et la place dans le tableau de caractères
passé en paramètre.
 La lecture se termine à la réception d’un caractère
d’interligne (touche return). Le ’\n’ n’est par inséré dans la
chaîne, il est remplacé par un terminateur ’\0’.
 Contrairement à scanf(), elle permet l’entrée de chaînes
contenant des espaces et des tabulations.

Programmation langage C -
ENIT 23-24 243
Lecture/Ecriture de
chaînes(3)
ECRITURE
printf()
 Cette fonction permet d’afficher une chaîne de caractères
en spécifiant un %s dans la chaîne de format.
 Elle ne rajoute pas d’interligne toute seule, mais on peut
en mettre un dans la chaîne de format si on le désire.
puts( chaine)
 Cette fonction envoie la chaîne de caractères spécifiée
dans le flux de sortie standard stdout. Elle ajoute un
caractère d’interligne à la fin.

Programmation langage C -
ENIT 23-24 244
Lecture/Ecriture de chaînes(4)

 Exemples:
char msg [6] = "hello";
char ch[5] ;
printf ("%s",msg) ; /* affiche hello sans retour à la ligne*/
printf ("%.4s", msg) ; /* affiche hell */
scanf ("%s", ch) ; /* ch contient l’adresse du premier caractère
de la chaine */
puts ( msg) ; /* affiche hello avec un retour à la ligne */
puts (" bonjour") ; /* affiche bonjour avec un retour à la ligne */
gets(ch) ; /* lit une ligne de caractères de stdin et la copie à
l'adresse indiquée par ch */

Programmation langage C -
ENIT 23-24 245
Traitement de chaînes de caractères(1)

 La bibliothèque <string.h> fournit une multitude de fonctions


pratiques pour le traitement de chaînes de caractères. Voici une
brève description des fonctions les plus fréquemment utilisées.
strlen(<s>) fournit la longueur de la chaîne sans compter le '\0' final
strcpy(<s>, <t>) copie <t> vers <s>
strcat(<s>, <t>) ajoute <t> à la fin de <s>
strcmp(<s>, <t>) compare <s> et <t> lexicographiquement et
fournit
un résultat:
négatif si <s> précède <t>
zéro si <s> est égal à <t>
positif si <s> suit <t>
strncpy(<s>, <t>, <n>) copie au plus <n> caractères de <t> vers
<s>
strncat(<s>, <t>, <n>) ajoute au plus <n> caractères de <t> à la fin
de <s>

Programmation langage C -
ENIT 23-24 246
Traitement de chaînes de caractères(2)

 Remarques:
Comme le nom d'une chaîne de caractères représente
une adresse fixe en mémoire, on ne peut pas 'affecter'
une autre chaîne au nom d'un tableau:
A="Hello"

Il faut bien copier la chaîne caractère par caractère ou
utiliser la fonction strcpy respectivement strncpy:
strcpy(A, "Hello");

Programmation langage C -
ENIT 23-24 247
Traitement de chaînes de caractères(3)
 La concaténation de chaînes de caractères en C ne se fait pas par le
symbole '+' comme en langage algorithmique ou en Pascal. Il faut ou bien
copier la deuxième chaîne caractère par caractère ou bien utiliser la fonction
strcat ou strncat.
 Exemple:
#include <string.h>
main ()
{
char ch1[50]=’’bonjour’’ ;
char *ch2=’’ monsieur”;
printf (“avant : %s\n “, ch1);
strcat (ch1, ch2);
printf (“après : %s\n’’,ch 1); Résultat
strncat (ch1,ch2,2);
printf (“après : %s\n’’,ch 1); avant : bonjour
} après : bonjour monsieur
après : bonjour monsieur m

Programmation langage C -
ENIT 23-24 248
Les fonctions de conversion(1)
La bibliothèque <stdlib.h> contient des déclarations de fonctions pour la
conversion de nombres en chaînes de caractères et vice-versa.
 Conversion de chaînes de caractères en nombres
atoi(<s>) retourne la valeur numérique représentée par <s>
comme int
atol(<s>) retourne la valeur numérique représentée par <s>
comme long
atof(<s>) retourne la valeur numérique représentée par <s>
comme double (!)

 Règles générales pour la conversion:


 Les espaces au début d'une chaîne sont ignorés
 Il n'y a pas de contrôle du domaine de la cible
 La conversion s'arrête au premier caractère non convertible
 Pour une chaîne non convertible, les fonctions retournent zéro

Programmation langage C -
ENIT 23-24 249
Les fonctions de conversion(2)
 Exemples: Résultat
#include <stdio. h>
#include <stdlib. h> donnez une chaîne : 123
main() int : 123
{ double : 1.230000e+02
char ch[40] ;
int n;
do
{
printf(’’donnez une chaîne :’’) ;
gets(ch);
printf(‘’int : %d\n’’, atoi(ch));
printf(“double : %e\n” ,atof(ch));
} while(n);
}

Programmation langage C -
ENIT 23-24 250
Les fonctions de conversion(3)
 Conversion de nombres en chaînes de caractères
Le standard ANSI-C ne contient pas de fonctions pour convertir des nombres en
chaînes de caractères. Si on se limite aux systèmes fonctionnant sous DOS, on peut
quand même utiliser les fonctions itoa, ltoa et ultoa qui convertissent des entiers en
chaînes de caractères.
itoa (<n_int>, <s>, <b>)
ltoa (<n_long>, <s>, <b>)
ultoa (<n_uns_long>, <s>, <b>)
 Chacune de ces trois procédures convertit son premier argument en une chaîne de
caractères qui sera ensuite attribuée à <s>. La conversion se fait dans la base <b>.
Exemple:
#include <stdlib. h> do
main() {
{ printf(‘’Donner un nombre et une
char ch[40]; base :’’) ;
int n,b; scanf(’’%d %d”, &n, &b);
printf(”%s\n”, itoa(n, ch, b));
}while(n) ;
}

Programmation langage C -
ENIT 23-24 251
Fonctions de classification et de conversion(1)

 Les fonctions de <ctype.h> servent à classifier et à convertir des


caractères. Les symboles nationaux (é, è, ä, ü, ß, ç, ...) ne sont pas
considérés. Les fonctions de <ctype> sont indépendantes du code
de caractères de la machine et favorisent la portabilité des
programmes.
 Les fonctions de classification suivantes fournissent un résultat du
type int différent de zéro, si la condition respective est remplie, sinon
zéro. <c> représente une valeur du type int qui peut être
représentée comme caractère.
isupper(<c>) si <c> est une majuscule ('A'...'Z')
islower(<c>) si <c> est une minuscule ('a'...'z')
isdigit(<c>) si <c> est un chiffre décimal ('0'...'9')
isalpha(<c>) si islower(<c>) ou isupper(<c>)

Programmation langage C -
ENIT 23-24 252
Fonctions de classification et de conversion(2)

isalnum(<c>) si isalpha(<c>) ou isdigit(<c>)


isxdigit(<c>) si <c> est un chiffre hexadécimal
('0'...'9' ou 'A'...'F' ou 'a'...'f')
isspace(<c>) si <c> est un signe d'espacement
(' ', '\t', '\n', '\r', '\f')

 Les fonctions de conversion suivantes fournissent une valeur du


type int qui peut être représentée comme caractère; la valeur
originale de <c> reste inchangée:
 tolower(<c>) retourne <c> converti en minuscule si <c> est une
majuscule
toupper(<c>) retourne <c> converti en majuscule si <c> est une
minuscule

Programmation langage C -
ENIT 23-24 253
Les fonctions de recherche dans une chaîne(1)

 On trouve des fonctions dans string.h de recherche de “l’occurrence’’ dans une


chaîne, d’un caractère ou d’une autre chaîne (nommée alors sous-chaîne). Ces
fonctions fournissent comme résultat :
 l’adresse de l’information cherchée en cas de succès
 le pointeur null dans le cas contraire.
 strchr (char *chaine, char caractere)
Recherche, dans chaîne la première position où apparaît le caractère mentionné
 strrchr (char *chaine, char caractere)
Réalise le même traitement que strchr, mais en explorant la chaîne mentionné à
partir de la fin. Elle fournit donc la dernière occurrence du caractère mentionné.
 strstr (char *chaine, char *sous-chaine)
Recherche dans chaîne la première occurrence complète de la sous-chaîne
mentionnée (respectant MIN et MAJ).
 strpbrk (char *chaine 1, char *chaine2)
Recherche, dans chaîne1 la première occurrence d’un caractère quelconque de
chaine2.

Programmation langage C -
ENIT 23-24 254
Les fonctions de recherche dans une chaîne(1)

#define c ’e’
#define sch "re"
#define voy "aeiou"
main()
{
char mot[40]; char *adr ; printf(’’donnez un mot : "); gets (mot);
if (adr=strchr(mot,c))
printf(’’Première occurrence de%c en %s\n et pos = %d \n’’,c,adr, adr-mot);
if (adr=strrchr(mot,c))
printf(’’Dernière occurrence de %c en %s\n et pos = %d \n’’,c, adr, adr-mot) ;
if (adr = strstr(mot,sch))
printf (“Première occurrence de %s en %s\n et pos = %d \n’’,sch,adr, adr-mot) ;
if (adr =strpbrk(mot,voy))
printf (“Première occurrence de l’une des lettres de %s en %s\n et pos = %d \
n’’,voy,adr,adr-mot) ;
}

Programmation langage C -
ENIT 23-24 255
Tableau de chaînes de caractères(1)

 Un tableau de chaînes de caractères correspond à un tableau à deux


dimensions du type char, où chaque ligne contient une chaîne de
caractères.
 Déclaration
La déclaration char JOUR[7][9]; réserve l'espace en mémoire pour 7 mots
contenant 9 caractères (dont 8 caractères significatifs).

Programmation langage C -
ENIT 23-24 256
Tableau de chaînes de caractères(2)

 Initialisation
Lors de la déclaration il est possible d'initialiser toutes les composantes du tableau
par des chaînes de caractères constantes:
char JOUR[7][9]= {"lundi", "mardi", "mercredi",
"jeudi", "vendredi", "samedi", "dimanche"};

 Mémorisation
Les tableaux de chaînes sont mémorisés ligne par ligne. La variable JOUR aura
donc besoin de 7*9*1 = 63 octets en mémoire.

Programmation langage C -
ENIT 23-24 257
Tableau de chaînes de caractères(3)

 Accès aux chaînes


Il est possible d'accéder aux différentes chaînes de caractères d'un
tableau, en indiquant simplement la ligne correspondante.
 Exemple
L'exécution des trois instructions suivantes:
char JOUR[7][9]= {"lundi", "mardi", "mercredi", "jeudi",
"vendredi", "samedi", "dimanche"};
int I = 2;
printf("Aujourd'hui, c'est %s !\n", JOUR[I]);

affiche la phrase:
Aujourd'hui, c'est mercredi !

Programmation langage C -
ENIT 23-24 258
11. Les fichiers
Présentation des fichiers(1)

 En C, les communications d'un programme avec son environnement se font par


l'intermédiaire de fichiers. Pour le programmeur, tous les périphériques, même le
clavier et l'écran, sont des fichiers. Jusqu'ici, nos programmes ont lu leurs
données dans le fichier d'entrée standard, (le clavier) et ils ont écrit leurs
résultats dans le fichier de sortie standard (l'écran). Nous allons voir comment
nous pouvons créer, lire et modifier nous-mêmes des fichiers sur les
périphériques disponibles.
 Un fichier (angl.: file) est un ensemble structuré de données stocké en général
sur un support externe (disquette, disque dur, disque optique, bande
magnétique, ...). Un fichier structuré contient une suite d'enregistrements
homogènes, qui regroupent le plus souvent plusieurs composantes appartenant
à un ensemble (champs).
 Fichier séquentiel: Dans des fichiers séquentiels, les enregistrements sont
mémorisés consécutivement dans l'ordre de leur entrée et peuvent seulement
être lus dans cet ordre. Si on a besoin d'un enregistrement précis dans un fichier
séquentiel, il faut lire tous les enregistrements qui le précèdent, en commençant
par le premier.

Programmation langage C -
ENIT 23-24 260
Présentation des fichiers(2)
 Types d’accès aux fichiers
 Accès séquentiel (surtout pour les bandes magnétiques)
 Pas de cellule vide.
 On accède à une cellule quelconque en se déplaçant depuis la cellule
de départ.
 On ne peut pas détruire une cellule.
 On peut par contre tronquer la fin du fichier.
 On peut ajouter une cellule à la fin.
 Accès direct (disques, disquettes, CD-ROM où l'accès
séquentiel est possible aussi).
 Cellule vide possible.
 On peut directement accéder à une cellule.
 On peut modifier (voir détruire) n'importe quelle cellule.

Programmation langage C -
ENIT 23-24 261
Présentation des fichiers(3)
 Codage
 En binaire : Fichier dit « binaire », Ce sont en général des fichiers
de nombres. Ils ne sont pas listables.
 En ASCII : Fichier dit « texte », les informations sont codées en
ASCII. Ces fichiers sont listables. Le dernier octet de ces fichiers
est EOF (caractère ASCII spécifique).
 Fichiers standard
 Il existe deux fichiers spéciaux qui sont définis par défaut pour
tous les programmes:
 stdin : le fichier d'entrée standard, lié en général au clavier (nom
interne = 0)
 stdout : le fichier de sortie standard, lié à l'écran (nom interne = 1)
 stderr : fichier de sortie erreur (nom interne = 2)

Programmation langage C -
ENIT 23-24 262
Présentation des fichiers(4)

 La mémoire tampon
Pour des raisons d'efficacité, les accès à un fichier se font par
l'intermédiaire d'une mémoire tampon (en anglais: buffer). La
mémoire tampon est une zone de la mémoire centrale de la machine
réservée à un ou plusieurs enregistrements du fichier. L'utilisation de
la mémoire tampon a l'effet de réduire le nombre d'accès à la
périphérie d'une part et le nombre des mouvements de la tête de
lecture/écriture d'autre part.
Pour pouvoir manipuler un fichier, un programme a besoin d'un
certain nombre d'informations : l'adresse de l'endroit de la mémoire-
tampon où se trouve le fichier, la position de la tête de lecture, le
mode d'accès au fichier (lecture ou écriture) ...Ces informations sont
rassemblées dans une structure dont le type, FILE *, est défini dans
stdio.h. Un objet de type FILE * est appelé flot de données (en
anglais, stream).

Programmation langage C -
ENIT 23-24 263
Manipulation des fichiers(1)

 Les opérations sur les fichiers les plus courant sont:


Créer - Ouvrir - Fermer - Lire - Ecrire - Détruire -
Renommer. Le langage C ne distingue pas les fichiers
à accès séquentiel des fichiers à accès direct, certaines
fonctions de la bibliothèque livrée avec le compilateur
permettent l'accès direct. Les fonctions standard sont
des fonctions d'accès séquentiel.
 Déclaration :
FILE *fichier ; /* majuscules obligatoires pour FILE */
Définit un pointeur qui va pointer vers une variable de
type FILE qui est une structure (struct).

Programmation langage C -
ENIT 23-24 264
Manipulation des fichiers(2)

 Ouverture:
FILE *fopen(char *nom_fichier, char *mode_ouverture);
nom_fichier est une chaîne de caractères représentant le nom du
fichier à ouvrir.
mode_ouverture est une chaîne représentant le mode d’ouverture du
fichier. Elle peut être l'une des chaînes suivantes :
 Mode (pour les fichiers TEXTES) :
"r" ouverture en lecture seule.
"w" ouverture en écriture seule.
"a" ouverture en écriture à la fin.
"r+" ouverture en lecture/écriture.
"w+" ouverture en lecture/écriture.
"a+" ouverture en lecture/écriture à la fin.

Programmation langage C -
ENIT 23-24 265
Manipulation des fichiers(3)

 Mode (pour les fichiers BINAIRES) :


"rb" ouverture en lecture seule.
"wb" ouverture en écriture seule.
"ab" ouverture en écriture à la fin.
"r+b" ou "rb+" ouverture en lecture/écriture.
"w+b" ou "wb+" ouverture en lecture/écriture.
"a+b" ou "ab+" ouverture en lecture/écriture à la fin.
 A l’ouverture, le pointeur est positionné au début du
fichier (sauf "a+" et "ab+")
 Exemple :
FILE *fichier ;
fichier = fopen( "c:\\fich.dat", "rb") ;

Programmation langage C -
ENIT 23-24 266
Manipulation des fichiers(4)
 Valeur rendue
La fonction fopen retourne une valeur de type pointeur vers FILE, où FILE
est un type prédéfini dans le fichier stdio.h.
 Si l'ouverture a réussi, la valeur retournée permet de repérer le fichier, et devra
être passée en paramètre à toutes les procédures d'entrées-sorties sur le
fichier.
 Si l'ouverture s'est avérée impossible, fopen rend la valeur NULL.
Conditions particulières et cas d'erreur
 Si le mode contient la lettre "r", le fichier doit exister, sinon c'est une erreur.
 Si le mode contient la lettre "w", le fichier peut exister ou pas.
 Si le fichier n'existe pas, il est créé ;
 Si le fichier existe déjà, son ancien contenu est perdu.
 Si le mode contient la lettre "a", le fichier peut exister ou pas.
 Si le fichier n'existe pas, il est créé ;
 Si le fichier existe déjà, son ancien contenu est conservé.

Programmation langage C -
ENIT 23-24 267
Manipulation des fichiers(5)
 Exemple:
FILE *fp;
if ( (fp = fopen("donnees.txt","r") ) == NULL)
{
fprintf(stderr,"Impossible d'ouvrir le fichier
données en lecture\n");
exit(1);
}
else fprintf(stderr, "ouverture avec succès\n " ) ;

Programmation langage C -
ENIT 23-24 268
Manipulation des fichiers(6)

 Fermeture:
int fclose(FILE *fichier);
Retourne 0 si la fermeture s’est bien passée, EOF en cas
d’erreur.
Il faut toujours fermer un fichier à la fin d'une session.
 Exemple :
FILE *fichier ;
fichier = fopen( "c:\\fich.dat ", " rb") ;
/* Ici instructions de traitement */
fclose(fichier) ;

Programmation langage C -
ENIT 23-24 269
Manipulation des fichiers(7)
 Destruction:
int remove(const char *nom_fichier);
Permet de supprimer un fichier fermé. Retourne 0 en cas de succès.
Exemple : remove ( "c:\\fich.dat ");

 Renommage:
int rename(char *AncienNom, char *NouvNom);
Retourne 0 si la fonction s’est bien passée. La valeur -1 Sinon.

 Changement du mode d’accès:


int chmod (const char *nom_fichier, int mode);
Modifie ou définie les droit d’accès à un fichier. « mode » est une constante
(S_IREAD, S_IWRITE, S_IREAD | S_IWRITE) dans la bibliothèque <sys\
stat.h>
Retourne la valeur 0 en cas de succès. La valeur -1 Sinon.

Programmation langage C -
ENIT 23-24 270
Manipulation des fichiers(8)
 Positionnement du pointeur au début du fichier:
void rewind (FILE *fichier);
Repositionne le pointeur du fichier sur le début du fichier.
 Positionnement du pointeur dans un fichier
Int fseek (FILE *fichier, long nbOctet, int direction);
fseek déplace le pointeur de fichier sur le nbOctet+1 dans le sens
indiqué par direction.
Valeurs possibles pour direction:
 0 -> à partir du début du fichier.
 1 -> à partir de la position courante du pointeur.
 2 -> en arrière, à partir de la fin du fichier.

 Détection de la fin d’un fichier séquentiel:


int feof(FILE *fichier) ;
Retourne 0 si la fin du fichier n’est pas atteinte

Programmation langage C -
ENIT 23-24 271
Lecture et écriture dans les fichiers séquentiels(1)

 Les fichiers que nous employons ici sont des fichiers


texte, c-à-d. toutes les informations dans les fichiers
sont mémorisées sous forme de chaînes de caractères
et sont organisées en lignes. Même les valeurs
numériques (types int, float, double, ...) sont stockées
comme chaînes de caractères.
 Pour l'écriture et la lecture des fichiers, nous allons
utiliser les fonctions standard fprintf, fscanf, fputc et
fgetc qui correspondent à printf, scanf, putchar et
getchar si nous indiquons stdout respectivement stdin
comme fichiers de sortie ou d'entrée.

Programmation langage C -
ENIT 23-24 272
Lecture et écriture dans les fichiers séquentiels(2)

 Lecture par caractère :


int fgetc(FILE *fichier);
Lit 1 caractère, mais retourne un entier n en cas de succès et
retourne EOF si erreur ou fin de fichier; (le pointeur avance d'un
octet pour exécuter l'opération de lecture).
 Exemple :
FILE *fichier ; char c ;
fichier = fopen( "c:\\ fich.dat ", " rb") ;
while ( (c = fgetc(fichier)) != EOF)
{
... /* utilisation de c */
}

Programmation langage C -
ENIT 23-24 273
Lecture et écriture dans les fichiers séquentiels(3)

 Ecriture par caractère :


int fputc(int c, FILE *fichier);
Ecrit la valeur de c à la position courante du pointeur, le
pointeur avance d'un octet. Retourne EOF en cas
d’erreur et le caractère injecté en cas de succès.
 Exemple : copier un fichier dans un autre
FILE *fichier_src, *fichier_dest;
char c ;
Fichier_src = fopen(“c:\\autoexec.bat”,”r”);
Fichier_dest = fopen(“c:\\copie_autoexec.bat”,”w”);
while ((c = fgetc(fichier_src)) != EOF)
fputc(c,fichier_dest);

Programmation langage C -
ENIT 23-24 274
Lecture et écriture dans les fichiers séquentiels(4)

 Lecture par chaîne de caractère :


char *fgets (char * chaine, int n,FILE *fichier);
Lit n-1 caractères à partir de la position du pointeur et les range
dans chaine en ajoutant '\0'. Retourne chaine en cas de succès ou
la valeur NULL sinon.
 Exemple :
char ligne[20];
FILE *fichier;
Fichier= fopen (a :\\ fich.dat ", " rb") ;
while (fgets(ligne,20,fichier) != NULL) /* stop sur fin de fichier ou erreur */
{
... /* utilisation de ligne */
}

Programmation langage C -
ENIT 23-24 275
Lecture et écriture dans les fichiers séquentiels(5)

 Ecriture par chaîne de caractère :


int fputs(char * chaine , FILE *fichier);
fputs écrit sur le fichier le contenu de chaine ('\0' n'est
pas rangé dans le fichier). Le pointeur avance de la
longueur de la chaîne.
Retourne : une valeur non négative si l'écriture se
passe sans erreur, et EOF en cas d'erreur
 Exemple :
char ligne[20];
FILE *fichier;
Fichier= fopen ("a :\\ fich.dat ", " a+") ;
fputs ("un texte",fichier) ;

Programmation langage C -
ENIT 23-24 276
Lecture et écriture dans les fichiers séquentiels(6)

 Lecture formatée à partir d‘un fichier:


int fscanf (FILE *fichier, const char *format, liste d'adresses);
fscanf lit une suite de caractères du fichier défini par fichier en
vérifiant que cette suite est conforme à la description qui en est fait
dans format. Cette vérification s'accompagne d'un effet de bord qui
consiste à affecter des valeurs aux variables pointées par les
différents paramètres spécifiés par la liste d’adresse.
fscanf retourne : le nombre de parami affectés en cas de sucées.
S'il y a eu rencontre de fin de fichier ou erreur d'entrée-sortie,
avant toute affectation à un parami, fscanf retourne EOF.
La lecture d’un paramètre s’arrête quand on rencontre un caractère
blanc (espace, tab, new line).

Programmation langage C -
ENIT 23-24 277
Lecture et écriture dans les fichiers séquentiels(7)

 Lecture formatée à partir d‘une chaine:


int sscanf (const char *buffer, const char *format, liste
d'adresses);
La fonction sscanf réalise le même traitement que la
fonction fscanf, avec la différence que les caractères
lus par sscanf ne sont pas lus depuis un fichier, mais
du tableau de caractères chaîne. La rencontre du '\0'
terminal de chaîne pour sscanf est équivalente à la
rencontre de fin de fichier pour fscanf.

Programmation langage C -
ENIT 23-24 278
Lecture et écriture dans les fichiers séquentiels(8)

 Ecriture formatée dans un fichier:


int fprintf(FILE *fichier, char *format, liste d'expressions);
fprintf permet d’écrire dans le fichier la liste des expression selon
les format spécifiés. Elle retourne :
 le nombre de caractères écrits en cas de succès
 une valeur négative s'il y a eu une erreur d'E/S.

 Ecriture formatée dans une chaîne :


int sprintf (const char *buffer, const char *format, liste
d'adresses);
La fonction sprintf réalise le même traitement que la fonction fprintf,
avec la différence que les caractères émis par sprintf n’est pas
écrite dans un fichier, mais dans le tableau de caractères chaîne. Un
'\0' est écrit dans chaîne en fin de traitement.

Programmation langage C -
ENIT 23-24 279
Lecture et écriture dans les fichiers séquentiels(9)

Exemple : copie d’un fichier dans un autre. Le premier fichier contient deux colonnes
(nom, moyenne)
#include <stdio.h>
if( (fichier_dest=fopen("c:\\test2.txt","w"))==NULL)
#include <process.h>
{
void main()
printf("erreur d'ouverture du fichier destination\
{ n");
FILE * fichier_src, *fichier_dest; exit (0);
char nom[20]; }
float moyenne; while (!feof(fichier_src))
if( (fichier_src=fopen("c:\\test.txt","r"))==NULL) {
{ fscanf(fichier_src,"%s%f", nom,&moyenne);
printf("erreur d'ouverture du fichier source\n"); fprintf(fichier_dest,"%s%f\n",nom,moyenne);
exit (0); }
} }

Programmation langage C -
ENIT 23-24 280
Lecture et écriture dans les fichiers séquentiels(10)

 Autre fonctions:
int fwrite(void *p,int taille_bloc, int nb_bloc, FILE *fichier);
p de type pointeur, écrit à partir de la position courante du pointeur fichier
nb_bloc X taille_bloc octets lus à partir de l'adresse p. Le pointeur fichier
avance d'autant.
Le pointeur p est vu comme une adresse, son type est sans importance.
Retourne le nombre de blocs écrits.
 Exemple: taille_bloc=4 (taille d'un entier en C), nb_bloc=3, écriture de 3
entiers
int tab[10] ;
fwrite(tab,4,3,fichier) ;

int fread(void *p, int taille_bloc, int nb_bloc, FILE *fichier);


Analogue à fwrite en lecture.
Retourne le nombre de blocs lus, et 0 à la fin du fichier.

Programmation langage C -
ENIT 23-24 281
Résumé sur les fichiers

Langage algorithmique C

Ouverture en écriture ouvrir <Nom> en écriture <FP> = fopen(<Nom>,"w");

Ouverture en lecture ouvrir <Nom> en lecture <FP> = fopen(<Nom>,"r");

Fermeture fermer <Nom> fclose(<FP>);

Fonction fin de fichier finfichier(<Nom>) feof(<FP>)

fprintf(<FP>,"...",<Adr>);
Ecriture écrire <Nom>:<Exp>
fputc(<C>, <FP>);

fscanf(<FP>,"...",<Adr>);
Lecture lire <Nom>:<Var>
<C> = fgetc(<FP>);

Programmation langage C -
ENIT 23-24 282
Exercice

Lire un fichier texte, avec un contrôle d'erreur : L'utilisateur saisit le nom


du fichier, la machine retourne le listing du fichier s'il existe et un
message d'erreur s'il n'existe pas.

Programmation langage C -
ENIT 23-24 283
Corrigé

#include <stdio.h>
#include <conio.h>
void main()
{
FILE *fichier;
char c,nom[10];
printf("NOM DU FICHIER A LISTER: ");
gets(nom);
if((fichier = fopen(nom,"r"))==NULL)
printf("\nERREUR A L'OUVERTURE, CE FICHIER N'EXISTE PAS\n");
else
{
printf("\n\t\t\tLISTING DU FICHIER\n");
printf("\t\t\t------------------\n\n");
while((c=getc(fichier))!=EOF)printf("%c",c);
}
fclose(fichier);
printf("\n\nPOUR SORTIR FRAPPER UNE TOUCHE ");
getch();
}

Programmation langage C -
ENIT 23-24 284

Vous aimerez peut-être aussi