Documente Academic
Documente Profesional
Documente Cultură
Rappels et compléments du
langage C
1
Rappels
2
Types d’objet
◮ Types scalaires : objets élémentaires proches du
matériel
Types arithmétiques : pour faire des calculs au sens
classique
Pointeurs : référence à d’autres objets ou fonctions
◮ Types structurés
Vecteurs : répétition ordonnée d’un même type
Structures : rassemble éléments hétérogènes
Union : fait coexister plusieurs types au même
endroit mémoire
• Types de fonction : précise à la fois type valeur de
retour et type
arguments
• Types incomplets
◮ Incomplétude totale void
◮ Vecteur de taille non précisée
3
LES STRUCTURES
Le langage C permet de définir des modèles de structures
comme les autres langages évolués.
struct art // déclaration de structure
{ int numero;
int qte;
double prix;
};
Typedef struct
{ int numero;
int qte;
double prix;
}article;
4
Opérations sur structures
5
Unions
6
Exemple
7
Exemple
8
Accès aux champs
9
Les classes d’allocation
de variables
10
Déclaration et définition
11
Variables et déclarations
12
Règle fondamentale de visibité
13
Exemple
int a; /*variable globale*/
void f1(){
long a; ; /*variable locale à f1*/
a = 50; /*modification locale à f1*/
}
void f2(void){
a= 10; /*modification globale*/
}
void f3(float a ){/*paramètre de f3*/
a = 10; /*modification paramètre local à f3*/
}
les règles de visibilité de noms nous permettent de dire
:
1. la fonction f3 peut appeler les fonctions f3, f2, et f1 ;
2. la fonction f2 peut appeler la fonction f2, et f1 ;
3. la fonction f1 ne peut que s’appeler elle-même ;
14
Les classes d’allocation
mémoire
15
Les classes d’allocation
mémoire
Les classes mémoire sont :
global cette classe est celle des variables définies en
dehors d’une fonction. Ces variables sont accessibles à
toutes les fonctions. La durée de vie des variables de type
global est la même que celle du programme en cours
d’exécution.
local ou auto : cette classe comprend l’ensemble des
variables définies dans un bloc. C’est le cas de toute
variable définie à l’intérieur d’une fonction. L’espace
mémoire réservé pour ce type de variable est alloué dans
la pile d’exécution. C’est pourquoi elles sont appelées
aussi auto c.a.d automatique car l’espace mémoire
associé est créé lors de l’entrée dans la fonction et il
est détruit lors de la sortie de la fonction. La durée
de vie des variables de type local est celle de la
fonction dans laquelle elles sont définies.
16
Les classes d’allocation
mémoire
17
Exemple sur l’utilisation de
static
18
Exemple sur l’utilisation de
static : commentaire
19
Les classes extern et registre
extern ce qualificatif permet de spécifier que la ligne
correspondante n’est pas une tentative de définition mais
une déclaration . Il précise les variables globales
(noms et types) ou fonctions qui sont définies dans
un autre fichier source et qui sont utilisées dans ce
fichier source.
20
Qualificatifs d’aide au
compilateur
Une définition de variable qualifiée du mot const informe le compilateur
que cette variable est considérée comme constante et ne doit pas être
utilisée dans la partie gauche d’une affectation. Ce type de définition
autorise le compilateur à placer la variable dans une zone
mémoire accessible en lecture seulement à l’exécution.
Le qualificatif volatile informe le compilateur que la variable
correspondante est placée dans une zone de mémoire qui peut
être modifiée par d’autres parties du système que le programme
lui-même. Ceci supprime les optimisations faites par le compilateur lors
de l’accès en lecture de la variable. Ce type de variable sert à décrire des
zones de mémoire partagées entre plusieurs programmes ou encore des
espaces mémoires correspondant à des zones d’entrées-sorties de la
machine.
Les deux qualificatifs peuvent être utilisés sur la même variable, spécifiant
que la variable n’est pas modifiée par la partie correspondante du
programme mais par l’extérieur.
21
Les pointeurs
22
Introduction
23
Illustration
24
Pointeur - définition
type *identifiant;
définit identifiant comme variable de
type pointeur vers type
25
Exemple
26
Attribuer une valeur à une
variable de type pointeur
27
Première démarche
28
Seconde démarche
Utiliser
des fonctions d’allocation dynamique. Par exemple :
px =
malloc(sizeof(int));
permet
d’allouer un espace mémoire de la taille d’un entier et
affecte son adresse à px.
Autre
façon, si on déclare deux pointeurs :
int *ad1,
*ad2;
ad1 =
ad2;
ad2
pointe alors sur le même objet que ad1
29
Illustration
200
Schématiquement:
p
30
L’opérateur * pour manipuler
un objet pointé
p = (int*)malloc(sizeof(int));
*p = 30; /*place la valeur 30 dans
l’emplacement préalablement alloué*/
31
Illustration
*p
Valeur de ad
Adresses mémoire
Valeur de p
33 55
33 55 20 30
ad p x
*ad valeur de x
Schématiquement:
Objet pointé par ad
p ad 20
30
x
Objet pointé par p
32
Exemple
Si un pointeur P
pointe sur une variable X, alors *P peut être utilisé partout où on peut
écrire 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++
Dans le dernier cas, les
parenthèses sont nécessaires:
Comme les opérateurs
unaires * et ++ sont évalués de droite à gauche, sans les parenthèses le pointeur P
serait incrémenté, non pas l'objet sur lequel P pointe.
33
Priorité de * et &
34
Déclarateur de forme pointeur
* déclarateur
35
Cas simples : pointeurs sur des objets
d’un type de base, structure ou défini
par typedef :
38
Déclarateur de forme pointeur ne
correspondant pas à un pointeur
int *chose[10]est un int
*chose[10]; chose[10]est un pointeur sur
un int
chose est un tableau de 10
pointeurs sur un int
40
Soustraction de deux pointeurs
Il est possible de soustraire deux pointeurs de même type.
41
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).
NB.
Comme les pointeurs jouent un rôle si important, le langage C
soutient une série d'opérations arithmétiques sur les pointeurs que
l'on ne rencontre en général que dans les langages machines. Le
confort de ces opérations en C est basé sur le principe suivant:
Toutes les opérations avec les pointeurs tiennent compte
automatiquement du type et de la grandeur des objets
pointés.
42
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[9]+1;/* dernier élément + 1 -> légal */
P = &A[9]+2; /* dernier élément + 2 -> illégal */
P = &A[0]-1; /* premier élément - 1 -> illégal */
43
Pointeurs et structures
44
Pointeurs et structures
Exemple :
(*p).prix p->prix
45
TABLEAUX ET POINTEURS
46
Equivalence entre référence à
un tableau et pointeur
Régle générale
Lorsqu’un nom de tableau apparait dans un
programme, il est converti en un pointeur constant
sur son premier élément
Supposons ces déclarations:
int t[10], * adr;
Voici quelques expressions équivalentes :
scanf(" %d" , t); scanf(" %d" , &t[0]);
t+i &t[i]
*(t+i) t[i]
adr[i] *(adr+i).
adr = t+3; /*adr pointe sur le troisième élément
de t*/
*adr = 50; t[3] = 50
47
TABLEAUX ET POINTEURS
A 6
int A[10], *p; 8
4
p = A;
3
p
9
1
p prend l’adresse du premier élément
de t 5
NB. Les noms de tableaux étant des
constantes, il n’est pas possible de les 4
affecter
3
2
48
TABLEAUX ET POINTEURS
A
7
p[0]++; 8
p
4
*(p) ou p[0]désigne le contenu de
A[0] 3
*(p+1) désigne le contenu de A[1] 9
*(p+2) désigne le contenu de A[2] 1
…
5
*(p+i) désigne le contenu de A[i]
4
3
2
49
TABLEAUX ET POINTEURS
p = &A[4]; A
6
8
4
p
Si p pointe sur une composante 3
quelconque d'un tableau, alors p+1 pointe
sur la composante suivante.
9
Plus généralement, p+i pointe sur la ième 1
composante derrière p et p-i pointe sur la
ième composante devant p 5
4
3
2
50
Remarque
51
TABLEAUX ET POINTEURS
p++; A 6
p 8
4
3
9
le pointeur contient
maintenant l'adresse du 1
deuxième élément du tableau 5
!on ne peut pas incrémenter le 4
pointeur A car c'est un
pointeur constant. 3
2
52
Remarques
Il existe toujours une 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>
Presque tous les processeurs disposent de plusieurs registres spéciaux
(registres index) à l'aide desquels on peut effectuer l'adressage indexé
de façon très efficace.
53
Formalisme tableau -
formalisme pointeur
int t[10];
int i;
for (i = 0 ; i < 10 ; i++)
*(t+i) = 1;
55
Pointeurs et chaines de
caractères
NB.
char ch[20];
ch = " bonjour "; //incorrect
char ch[20] = " bonjour";//correct
56
Tableaux de pointeurs
Si nous avons besoin d’un ensemble de pointeurs, nous pouvons
les réunir dans 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.
57
Tableaux de pointeurs
58
Tableaux de pointeurs sur char
59
Illustration
60
Exemple de manipulation
On
peut afficher les 7 chaînes de caractères en fournissant les adresses
contenues dans le tableau JOUR à printf (ou puts) :
for
(int I=0; I<7; I++) printf("%s\n", JOUR[I]);
Comm
e 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' :
for
(I=0; I<7; I++) printf("%c\n", *JOUR[I]);
L'expre
ssion 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:
for
(int I=0; i<7; I++) printf("%c\n",*(JOUR[I]+2));
61
Exemple
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{ int i; char *chaine1, *chaine2, *res, *p;
chaine1 = "chaine ";
chaine2 = "de caracteres";
res = (char*)malloc((strlen(chaine1) + strlen(chaine2))
* sizeof(char));
p = res;
for (i = 0; i < strlen(chaine1); i++)
*p++ = chaine1[i];
for (i = 0; i < strlen(chaine2); i++)
*p++ = chaine2[i];
*p = '\0';
printf("%s\n",res);
}
62
La gestion dynamique de la
mémoire
63
déclaration statique de
données
La
mémoire réservée pour les données déclarées d’une
manière statique est connue à la compilation.
Exe
mple :
float
A, B, C; /* réservation de 12 octets */
shor
t 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 */
64
Déclaration d’un pointeur
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
connu à la compilation. Un pointeur est aussi déclaré
statiquement. Supposons qu’un pointeur ait besoin de p
octets en mémoire ( en général p = 4 )
Exempl
es :
double
*G; /* réservation de p octets */
char
*H; /* réservation de p octets */
float
*I[10]; /* réservation de 10*p octets */
65
Chaines de caractères
constantes
L
’espace pour les chaines de caractères constantes
qui sont affectées à des pointeurs ou utilisées
pour initialiser des pointeurs sur char est aussi
réservé automatiquement c. à. d à la compilation.
E
xemples :
c
har *J = "Bonjour ! "; /* réservation de p+10
octets */
c
har *K[] = {"un", "deux", "trois", "quatre"}; /*
réservation de 4*p+3+5+6+7 octets */
66
Position du problème
Souvent nous devons travailler avec des données dont nous ne
pouvons prévoir le nombre et la grandeur lors de la programmation.
Exemple
Nous voulons lire 10 phrases : le nombre de caractères par phrase
est imprévisible. Nous pouvons 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ême
qui seront introduites lors de l’exécution du programme.
67
Données dynamiques
Le tas est l'espace en mémoire laissé libre une fois mis en place le
DOS, les gestionnaires, les programmes résidents, le programme lui-
même et la pile (stack).
68
Allocation dynamique de la
mémoire
la fonction malloc
69
Allocation dynamique de la
mémoire
Sizeof(float) s’évalue à 4
Sizeof(double) s’évalue à 8
70
La fonction free
int *p;
p =(int *) malloc(10*sizeof(int));
if(p) {
for ( i=0 ; i < 10 ; i++){
p[i] = i; printf("%d",p[i]);
}
free(p);
}
L'instruction malloc retourne un pointeur sur une
zone mémoire de la taille de 10 entiers. Ce qui
correspond à un tableau de 10 entiers.
Le rôle de la fonction free() est de de libérer un
emplacement préalablement alloué. (n’a pas d’effet
si le pointeur a la valeur zéro)
Syntaxe : void free(void* p)
71
La fonction free
72
La fonction exit
73
La fonction exit
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{char INTRO[500]; char *TEXTE[10]; int I;
for (I=0; I<10; I++) {
gets(INTRO);
TEXTE[I] = malloc(strlen(INTRO)+1); /* Réservation de la
mémoire */
if (TEXTE[I]) /* S'il y a assez de mémoire, ... */
strcpy(TEXTE[I], INTRO); /* copier la phrase à l'adresse
fournie par malloc, ...*/
else{/* sinon quitter le programme après un message d'erreur.
*/ printf("ERREUR: Pas assez de mémoire \n");
exit(-1);
}
}
}
74
Fonction calloc
p = (int*)calloc(N,sizeof(int));
p = (int*)malloc(N * sizeof(int));
for (i = 0; i < N; i++)
*(p + i) = 0;
75
La fonction realloc
p = (int*)malloc(5*sizeof(int));
p = realloc(p, sizeof(int));
76
Tableaux multidimensionnels
77
Adresses des sous-tableaux et Noms des
différents éléments du tableau mat
mat
mat[0][0]mat[0][1]mat[0][2]mat[0][3]mat[0][4]
mat[0]
mat[1][0]mat[1][1]mat[1][2]mat[1][3]mat[1][4]
mat+1
mat+2
mat+3
78
Pointeur vers pointeur
79
Pointeurs et tableaux
multidimensionnels
80
Schéma illustratif de la
mémoire
pt
Pt[0]
=*pt Pt[1] =*(pt+1)
Pt[0][0]
Pt[1][0]
Pt[0][1]
Pt[1][1]
Pt[1][2]
81
Commentaire
La première allocation dynamique réserve
pour l'objet pointé par pt l'espace mémoire pour
nl pointeurs vers des réels.
Ces nl pointeurs correspondent aux lignes .
Les allocations dynamiques suivantes
réservent pour chaque pointeur pt[i] l'espace
mémoire nécessaire pour stocker nc réels.
On peut choisir des tailles différentes pour
chacune des lignes pt[i].
for (i = 0; i < nl; i++) pt[i] = (int*)malloc((i
+ 1) * sizeof(double));
pour initialiser tous les éléments du tableau à
zéro, on met:
pt[i] = (double*)calloc(nc, sizeof(double));
82
Schéma illustratif : nl = 6 nc =
5
83
Pointeurs et tableaux
multidimensionnels
84
Pointeurs et fonctions
85
Simuler une transmission par
adresse avec un pointeur
86
Illustration
À l’appel
x 10 y 11
ad1 ad2
Début d’exécution
x 10 y 11
ad1 ad2
t = *ad1; 10 t
87
Illustration
x 11 y 11
*ad1 = *ad2;
ad1 ad2
t 10
x 11 y 10
ad1 ad2
*ad2 = t;
10 t
88
Tableaux transmis en
argument
89
Tableaux transmis en
argument
90
TRANSMISSION DE LA VALEUR
D’UNE STRUCTURE
#include <stdio.h>
Struct enreg { int a;double b;}
int main (void)
{ struct enreg x;
void fct (struct enreg y);
x.a = 1; x.b = 12.5;
printf(" \navant appel fct : %d %e",x.a,x.b);
fct(x);
printf(" \nretour à main: %d %e: "x.a,x.b);
Return 0;
}
void fct(struct enreg s){
s.a = 0; s.b = 1;
Printf(" \ndans fct %d %e ", s.a, s.b);
}
91
TRANSMISSION DE L’ADRESSE
D’UNE STRUCTURE
#include <stdio.h>
Struct enreg { int a;double b;}
int main (void)
{ struct enreg x;
void fct (struct enreg *);
x.a = 1; x.b = 12.5;
printf(" \navant appel fct : %d %e",x.a,x.b);
fct(&x);
printf(" \nau retour à main: %d %e: "x.a,x.b);
return 0;
}
void fct(struct enreg *ps){
ps->a = 0; ps->b = 1;
Printf(" \ndans fct %d %e ", ps->a, ps->b);
}
92
Exécution
93
Fonction qui renvoie un objet
de type structure.
94
Exemple: tableau et structures
#include <stdio.h>
#include <stdlib.h>
Typedef struct
{ int numero, qte;
double prix;
}article;
main()
{ int n, i; article* tab;
printf("nombre d‘articles = ");
scanf("%d",&n);
tab = (article *)malloc(n * sizeof(article));
/* saisie des articles dans un tableau*/
for (i =0 ; i < n; i++) {
95
Exemple: tableau et structures
96
Remarques
97
Pointeurs génériques
98
Pointeurs génériques
99
Pointeurs génériques
100
La fonction memcpy
101
Applications
102
Fonction echange version
générique
103
Utilisation
Ainsi en déclarant :
int i =2, j=3; float x=3.4, y=6.5;
Struct complexe cx={1,2},cy={3,4};
L’appel peut être effectué pour
différents types de données
echange(&i,&j,sizeof(i));
echange(&x,&y,sizeof(x));
echange(&cx,&cy,sizeof(cx);
104
Les pointeurs de fonction
105
Les pointeurs de fonction
106
Pointeurs de fonctions
107
Exemples d’utilisation
int(*pmax)(int*, int);
pmax = max;
pmax prend comme valeur l’adresse du
code exécutable de la fonction max
pmax(Tab,10) max(tab,10)
108
Recherche du minimum d’une
fonction y =f(x) entre deux
bornes- sans pointeur de fonction
#include <stdio.h>
float carre(float x)
{ return x*x; }
float parabole(float x)
{ return x∗x - 4 ∗ x + 2; }
float min_carre(float a, float b)
{ int i; float pas; float vmin; float valeur;
pas =(b-a)/100;
vmin = carre(a);
for (i =1 ; i < 101 ; i++){
valeur = carre(a+i*pas);
if (vmin > valeur)
vmin = valeur;
}
return vmin;
}
109
Recherche du minimum d’une
fonction y =f(x) entre deux
bornes- sans pointeur de fonction
(suite)
110
Exemple : Recherche du minimum
d’une fonction y =f(x) entre deux
bornes
#include <stdio.h>
float carre(float x)
{ return x*x; }
float parabole(float x)
{ return x∗x - 4 ∗ x + 2; }
float min_fct(float a, float b, float
(* pF) ( float x))
{ int i; float pas; float vmin; float
valeur;
pas =(b-a)/100;
vmin = pF(a);
111
Recherche du minimum d’une
fonction y =f(x) entre deux bornes
(suite)
112
Les fichiers
113
Les fichiers
114
Accès séquentiel - Accès direct
115
Fichiers binaires - Fichiers texte
116
Déclaration
Lorsqu’un programme doit lire ou écrire des données dans
un fichier, ces données sont acheminées à leur destination
en passant par un tampon (buffer). Ce tampon est une
zone de mémoire RAM dans laquelle on range une quantité
(assez importante ) de données.
L’emplacement mémoire du tampon d’E/S d’un fichier est
donné par une variable structurée de type FILE.
Le type FILE est défini dans le header stdio.h. Ses champs
contiennent l’adresse du tampon ainsi que d’autres
informations sur le fichier concerné.
La déclaration d’un fichier se fait par l’instruction suivante:
FILE *f;
f est défini en tant que pointeur sur un objet de type FILE.
Cette déclaration réserve un emplacement pour le pointeur
f. f est une variable logique qui sera associée dans le
programme au fichier physique en mémoire.
117
Instruction d’ouverture d’un
fichier
Exemple :
FILE *f;
f = fopen(" exemple ", " wb ");
118
Le valeurs possibles de mode pour
les fichiers textes :
119
Mode pour les fichiers binaires:
120
Opérations de lecture et
d’écriture
121
Lecture et écriture en mode
caractère
122
Exemple : lecture caractère par
caractère
#include<stdio.h>
#include <stdlib.h>
void main()
{
FILE * fichier; char c, nom[21];
printf ("entrer le nom du fichier");
gets(nom);
if ((fichier = fopen(nom, "r "))== NULL) {
printf( "erreur d’ouverture"); exit (-1);
}
while ((c = fgetc(fichier)) !=EOF)
printf("%c",c);
fclose(fichier);
}
123
Lecture et écriture en mode
chaine
124
Lecture et écriture formatées
La fonction fprintf écrit des données dans un fichier en les
formatant. Elle admet le prototype :
int fprintf(FILE *fichier, char *format, liste d’expressions);
Comme printf, fprintf accepte un nombre variable de
paramètres. Elle retourne comme résultat le nombre de
caractères écrits. Une valeur de retour négative (comme EOF)
indique une erreur.
fprintf(stdout, … ) et printf( …) sont équivalents.
125
Ecriture dans un fichier texte
#include <stdio.h>
#include <stdlib.h>
main () {
char c; int x, y; char nomfich[21]; FILE *sortie;
printf("nom du fichier à créer :");
scanf("%20s", nomfich);
sortie = fopen (nomfich,"w");
if (!sortie ){
printf ("erreur d'ouverture"); exit(-1);
}
printf("donner les noms (* pour finir) et les coordonnées
des points");
do {
scanf(" %c%d%d", &nom, &x, &y);
if (c != ‘*’ )
fprintf(sortie, "%c%d%d",c, x, y);
} while (c != ‘*’ )
fclose(sortie);
}
126
Lecture à partir d’un fichier
texte
#include <stdio.h>
#include <stdlib.h>
main () {
char c; int x, y; char nomfich[21]; FILE *entree;
printf("nom du fichier à lister :"); scanf("%20s",
nomfich);
entree = fopen (nomfich,"r");
if (!entree ){
printf ("erreur d'ouverture"); exit(-1);
}
do{
fscanf(entree, " %c%d%d", &c, &x, &y);
if ( !feof(entree) )
printf( "%c%d%d",c, x, y);
} while (!feof(entree) );
printf("***fin de fichier***");
fclose(entree);
}
127
Instructions de lecture et
d’écriture
128
Instruction de lecture
129
La fonction feof
Syntaxe :
int feof(FILE *fichier);
Cette fonction est surtout utilisée en lecture.
Elle retourne 0 tant que la fin de fichier n’est pas
atteinte. elle est vrai lorsque le pointeur est
positionné au-delà de la fin du fichier c à d quand
la dernière lecture a échoué
feof n’est jamais vrai après l’ouverture (en lecture )
du fichier même lorsque celui-ci est vide. Il faut au
moins une lecture.
Exemple :
do
{ fread(&n, sizeof(int), 1, fichier);
if (!feof(fichier)) printf(« \n %d », n);
} while (!feof(fichier));
130
Fermeture d’un fichier
131
Création d’un fichier
#include <stdio.h>
#include <stdlib.h>
int main()
{char *nom = " exemple "; int n;
FILE *fichier = fopen(nom, "wb ");
if (fichier == NULL) {
printf ("erreur d'ouverture"); exit(-1);
}
do {
printf(" donner un entier ");
scanf(" %d ", &n);
fwrite(&n, sizeof(int), 1, fichier);
}while (n);
fclose(fichier);
return 0;
}
132
Liste séquentielle d’un fichier
#include <stdio.h>
#include <stdlib.h>
void main()
{char *nom = " exemple "; int n; FILE *fichier;
fichier = fopen(nom, " rb ");
if (!fichier ){
printf ("erreur d'ouverture"); exit(-1);
}
do
{ fread(&n, sizeof(int), 1, fichier);
if (!feof(fichier)) printf("\n %d " , n);
} while (!feof(fichier));
fclose(fichier);
}
133
Accès direct
Il est possible d’accéder à partir d’une position dans le fichier
vers une autre position à l’aide de la fonction fseek.
Cette fonction est utilisée surtout pour les fichiers binaires.
int fseek(FILE * f, int p, int position); déplace le pointeur
de p cases à partir de position.
Valeurs possibles pour position :
SEEK_SET (ou 0) : à partir du début du fichier
SEEK_CUR (ou 1) : à partir de la position courante du pointeur.
SEEK_END (ou 2) : en arrière à partir de la fin du fichier
Retourne 0 si le pointeur a pu être déplacé.
long int ftell(FILE *f); retourne le nombre d'octets du
début de fichier jusqu'à la position courante. Cette fonction
est habituellement utilisée avant fseek.
134
Exemple
#include <stdio.h>
#include <stdlib.h>
void main()
{char *nom = "exemple"; int n; long num;
FILE *fichier = fopen (nom," rb ");
if (!fichier ){
printf ("erreur d'ouverture"); exit(-1);
}
do {
printf(" rang dans le fichier : ");
scanf("%d" , &num);
if (num) {
fseek(fichier, (num -1) *sizeof(int), SEEK_SET);
fread(&n,sizeof(int),1,fichier);
printf ("%d \n" , n);
}
} while (num)
fclose(fichier);
}
135
ANNEXES
136
Principaux codes de conversion
- printf
137
Principaux codes de conversion
- scanf
c char
d int
u unsigned int
hd short int
hu unsigned short int
ld long int
lu unsigned long int
f, e float écrit indifféremment dans l’une
des deux notations: décimale
(éventuellement sans point, c’est-à-dire
comme un entier) ou exponentielle(avec la
lettre e ou E)
lf , le double avec la même présentation
que ci-dessus
s chaîne de caractères
138
Les chaînes de caractères
139
Principales fonctions de la
bibliothèque string.h
140
Principales fonctions de la
bibliothèque string.h
141
Branchement multiple switch
switch (expression ){
case constante-1: liste d’instructions 1 ;
break;
case constante-2: liste d'instructions 2 ;
break;
...
case constante-n: liste d'instructions n;
break;
default: liste d'instructions ;
break;
}
Si la valeur de expression est égale à l'une des
constantes, la liste d'instructions correspondant est
exécutée. Sinon la liste d'instructions correspondant
à default est exécutée. L'instruction default est
facultative
142
Branchement non conditionnel
break
main()
{ int i;
for (i = 0; i < 5; i++) {
printf("i = %d\n",i);
if (i == 3) break;
}
printf(" i a la sortie de la boucle= %d\n",i);
}//i = 3
143
Branchement non conditionnel
continue
144