XXXII. Saisie de donn�es par un op�rateur (stdin)▲
XXXII-A. Introduction▲
Il est courant en C standard d'utiliser le flux stdin pour acqu�rir des donn�es en provenance d'un op�rateur. (Mode conversationnel). On admettra pour la suite que stdin est connect� � la partie 'clavier' d'un p�riph�rique console.
Le langage C offre plusieurs fonctions permettant de lire des donn�es sur un flux en g�n�ral et sur stdin en particulier.
- fgetc()
- getc()
- getchar()
- gets()
- scanf()
- fgets()
XXXII-B. fgetc(), getc(), getchar()▲
Ces trois fonctions extraient un caract�re du flux entrant (pour getchar(), ce flux est stdin). C'est insuffisant pour saisir autre chose qu'un simple <ENTER>. Ces fonctions ne sont absolument pas adapt�es � la saisie d'un caract�re comme un choix de menu par exemple.
Par contre, ces fonctions peuvent �tre utilis�es pour construire des fonctions d'entr�es de plus haut niveau plus ou moins sp�cialis�es.
XXXII-C. gets()▲
Pour des raisons �videntes de s�curit� (pas de limitation du nombre de caract�res saisis), la fonction gets() ne devrait pas �tre utilis�e. Bien que, � ma connaissance, cette fonction ne soit pas officiellement d�pr�ci�e pour des raisons de compatibilit� avec le code existant, il est fortement conseill� de ne pas l'utiliser pour de nouveaux d�veloppements.
XXXII-D. scanf()▲
Malgr� ce que l'on constate dans l'abondante litt�rature consacr�e � l'initiation au langage C, l'utilisation de scanf() n'est pas adapt�e.
En effet, le 'f' de scanf() est l� pour nous rappeler que l'entr�e doit �tre format�e (formated), ce qui n'est �videmment pas le cas avec un op�rateur humain qui peut entrer n'importe quoi. D'autre part, scanf() g�re difficilement le '\n', ce qui entraine des comportements aberrants dans les saisies si on ne prend pas certaines pr�cautions d'usage.
L'utilisation correcte et s�re de scanf() est complexe, et n'est pas � la port� d'un d�butant (ni m�me � celle de la plupart des programmeurs exp�riment�s). N�anmoins, il est possible d'utiliser correctement scanf() si on se forme correctement. En lisant par exemple l'article Scanf d�mythifi�e.
XXXII-E. fgets()▲
Cette fonction est parfaitement adapt�e � la saisie d'une ligne, (m�me de 1 caract�re). Son usage est recommand�.
S'il faut saisir une valeur num�rique, celle-ci sera d'abord saisie sous forme de ligne, puis traduite par la fonction appropri�e (strtol(), strtoul(), strtod()) ou sscanf()) avec le filtre appropri� :
#
include
<stdio.h>
#
include
<stdlib.h>
int
main
(void
)
{
int
ret;
char
temp[20
];
do
{
char
saisie[20
];
printf
("
Entrez
un
nombre
:
"
);
fflush (stdout);
fgets (saisie, sizeof
saisie, stdin);
/*
Filtrage
des
caracteres
(entier
decimal)
*
Nota
:
la
saisie
s'arrete
a
la
premiere
erreur.
*
Ce
qui
est
saisi
avant
est
considere
comme
valide.
*
*
"123a"
->
"123"
:
ret
=
1
*
*
"a123"
->
""
:
ret
=
0
*/
ret =
sscanf (saisie, "
%[0-9-]s
"
, temp);
}
while
(ret !
=
1
);
{
long
n =
strtol (temp, NULL
, 10
);
printf ("
La
chaine
est
'%s',
soit
%ld\n
"
, temp, n);
}
return
0
;
}
D'autres exemples dans le chapitre sur les fichiers
XXXII-F. Ressources▲
XXXII-G. Comment fonctionne fgetc(stdin) alias getchar()▲
Cette fonction d'apparence simple a en fait un comportement plus complexe qu'il n'y parait. En effet, elle regroupe un certain nombre de comportements non triviaux qui sont rarement expliqu�s dans la litt�rature C.
XXXII-G-1. Comportement visible.▲
L'appel de cette fonction provoque une suspension de l'ex�cution du programme. Durant cette suspension, il est possible de rentrer des caract�res (par exemple � l'aide du clavier) et m�me �ventuellement de supprimer le ou les derniers caract�res saisis � l'aide de la touche 'BackSpace'. La fin de saisie (et la reprise de l'ex�cution du programme) est marqu�e par la frappe de la touche <enter>.
XXXII-G-2. Comportement interne.▲
Les caract�res saisis sont stock�s dans le flux stdin. Lorsque l'on frappe la touche <enter>, le caract�re '\n' est aussi plac� dans stdin, et l'ex�cution reprend. Le caract�re le plus ancien est alors extrait du flux et il est retourn�. En cas d'erreur de lecture ou d'entr�e d'un caract�re sp�cial dit 'de fin de fichier' (Ctrl-D, Ctrl-Z etc. selon le syst�me), la valeur EOF (int < 0) est retourn�e.
Ensuite, si on rappelle fgetc(), deux cas sont possibles. Soit le flux est vide, soit il ne l'est pas. Si le flux est vide, la fonction fgetc() suspend l'ex�cution, et on retrouve le comportement pr�c�dent. S'il n'est pas vide, l'ex�cution n'est pas suspendue, et le caract�re le plus ancien est extrait et retourn�.
Dans la grande majorit� des cas la lecture du '\n' signifie que la ligne saisie a �t� compl�tement lue.
XXXII-G-3. Quelques exp�rimentations.▲
A l'aide de simples programmes, il est possible de v�rifier un certain nombre de comportements d�crits pr�c�demment :
#
include
<stdio.h>
int
main (void
)
{
int
x =
fgetc
(stdin);
printf ("
x
=
%d
('%c')\n
"
, x, x);
return
0
;
}
Quelques essais de saisie :
<enter>
x = 10 ('
')
On voit que le caract�re extrait est '\n' (ici, LF, soit le code ASCII 10)
a<enter>
x = 97 ('a')
On voit que le caract�re extrait est 'a' (ici, le code ASCII 97). Le <enter> ('\n') n'a pas �t� extrait. Si on appelait fgetc() une nouvelle fois, il n'y aurait pas de suspension.
a<backspace>b<enter>
x = 98 ('b')
On constate que, bien que le premier caract�re saisi fut 'a', le caract�re extrait est 'b' (ici, le code ASCII 98). En effet, la touche <backspace> a permis de corriger la derni�re saisie.
abcd<enter>
x = 97 ('a')
On voit que le caract�re extrait est 'a', bien que d'autres caract�res aient �t� saisis apr�s. C'est donc bien le plus ancien caract�re qui est extrait. Les autres caract�res sont en attente de lecture. Une boucle de fgetc() permettrait de les extraire.
#
include
<stdio.h>
int
main (void
)
{
int
x;
do
{
x =
fgetc
(stdin);
printf ("
x
=
%d
('%c')\n
"
, x, x);
}
while
(1
);
return
0
;
}
Je laisse au lecteur le soin de refaire les exp�riences pr�c�dentes et d'en tirer les conclusions qui s'imposent.
XXXIII. Les fichiers▲
XXXIII-A. Introduction▲
Le langage C n'offre pas, � proprement parler, de gestion de fichiers. Il d�finit plut�t des flux d'entr�es / sorties (I/O streams) sur lesquels il peut agir (ouverture/fermeture, lecture/�criture). L'unit� d'information g�r�e par un flux est le byte.
Certains de ces flux sont connect�s � des p�riph�riques permettant par exemple de r�aliser une interface entre la machine et l'utilisateur (IHM) en mode texte. Mais la plupart du temps, le nom associ� au flux est en fait un 'fichier', c'est-�-dire une sorte de m�moire (disque, flash) accessible en �criture et en lecture par l'interm�diaire du syst�me. L'avantage �vident est que les donn�es sont permanentes, m�me apr�s mise hors tension de la machine.
En cons�quence, dans la pratique, les termes flux et fichiers sont souvent confondus.
XXXIII-B. Texte ou binaire ?▲
Le langage C fait la distinction entre les fichiers binaires et les fichiers textes. Cette distinction est historique. Elle d�pend en fait du syst�me utilis�. Sur certains syst�mes, il n'existe aucune diff�rence physique entre les fichiers textes et les fichiers binaires. Sur d'autres syst�mes, il existe une diff�rence. Par souci de portabilit�, il est recommand� de respecter cette distinction.
Le choix entre fichier texte ou binaire provient du contenu de ce fichier.
XXXIII-B-1. Fichier texte▲
On appelle fichier texte un fichier qui contient des informations de type texte, c'est � dire des s�quences de lignes.
Une ligne est une s�quence de caract�res imprimables termin�e par une marque de fin de ligne.
Selon le syst�me, la marque de fin de ligne est compos�e de un ou plusieurs caract�res de contr�le (par exemple, CR, LF, ou une s�quence de ces caract�res)
:----------------:--------------:----------------:
: Syst�me : Fin de ligne : Fin de fichier :
:----------------:--------------:----------------:
: Unix : : :
: Mac X : 0x0A LF : Sans objet :
: Linux : : :
:----------------:--------------:----------------:
: Mac (non unix) : 0x0D CR : Sans objet :
:----------------:--------------:----------------:
: MS-DOS : 0x0D CR : 0x1A :
: Windows : 0x0A LF : ^Z :
: Windows NT : : :
:----------------:--------------:----------------:
: VMS STREAM_CR : 0x0D CR : Sans objet :
:----------------:--------------:----------------:
: VMS STREAM_LF : 0x0A LF : Sans objet :
:----------------:--------------:----------------:
: VMS STREAM_CRLF: 0x0D CR : Sans objet :
: : 0x0A LF : :
:----------------:--------------:----------------:
L'ensemble des valeurs num�riques des caract�res (charset) d�pend du syst�me. La plupart du temps, il s'agit du codage ASCII (0-127) avec des extensions plus ou moins standards au del� de 127. Il existe d'autres codes, comme EBCDIC utilis� sur certains mainframes IBM.
Pour �crire une fin de ligne dans un fichier texte, il suffit d'�crire le caract�re '\n'. Celui-ci sera alors automatiquement traduit en marqueur de fin de ligne.
De m�me, lors de la lecture d'un fichier texte, le marqueur de fin de ligne est automatiquement traduit en '\n', quel qu'il soit.
Nota : Certains syst�mes marquent la fin des fichiers textes d'un caract�re sp�cial. Par exemple MS-DOS ajoute un code 26 (^Z). Cela signifie que, pour ce syst�me, la lecture d'un fichier texte s'arr�te d�s la rencontre de ce caract�re.
XXXIII-B-2. Fichier binaire▲
N'importe quel fichier, y compris un fichier texte, peut �tre consid�r� comme binaire. Dans ce cas, l'�criture et la lecture des caract�res se fait sans interpr�tation.
Par exemple, sur une plateforme utilisant le jeu de caract�res ASCII, CR vaut 13 ou 0x0D ou '\r'. De m�me, LF vaut 10 ou 0x0A ou '\n'.
XXXIII-B-3. Modes d'ouverture d'un fichier▲
La fonction d'ouverture de fichier est fopen(). Comme pour les autres fonctions de gestion des fichiers, le fichier d'interface est <stdio.h>.
FILE *
fopen (char
const
*
filename, char
const
*
mode);
Le mode d'ouverture est d�termin� par une chaine de caract�re. Voici les cha�nes correspondant aux principaux modes :
"r" : mode texte en lecture
"w" : mode texte en �criture (cr�ation)
"a" : mode texte en �criture (ajout)
"rb" : mode binaire en lecture
"wb" : mode binaire en �criture (cr�ation)
"ab" : mode binaire en �criture (ajout)
XXXIII-B-4. Lecture d'un fichier▲
Le langage C offre plusieurs fonctions permettant de lire les donn�es d'un fichier.
- fgetc()
- getc()
- fread()
- fscanf()
- fgets()
XXXIII-B-4-a. fgetc(), getc()▲
Ces fonctions sont identiques. Elles permettent de lire un caract�re.
XXXIII-B-4-b. fread()▲
Cette fonction permet de lire un bloc de caract�res d'une longueur donn�e. Elle est tout � fait adapt�e � la lecture des donn�es binaires brutes (non interpr�t�es).
XXXIII-B-4-c. fscanf()▲
Cette fonction permet de lire des donn�es 'texte' format�es. Cette fonction est d'une utilisation complexe et son usage est peu recommand�.
XXXIII-B-4-d. fgets()▲
Cette fonction permet de lire une ligne de texte. Elle est tout � fait adapt�e � la lecture d'un fichier texte ligne par ligne.
Sa simplicit� d'utilisation et sa robustesse en font la fonction pr�f�r�e des programmeurs qui doivent analyser des fichiers textes.
XXXIII-B-4-d-i. Exemple d'utilisation▲
Soit le fichier texte :
Ceci est un simple fichier
texte de 2 lignes.
et un petit programme permettant de lire ces 2 lignes
/*
fichier1.c
*/
#
include
<stdio.h>
int
main (void
)
{
/*
ouverture
du
fichier
en
mode
texte
*/
FILE *
fp =
fopen ("
data.txt
"
, "
r
"
);
/*
L'ouverture
du
fichier
est-elle
realisee
?
*/
if
(fp !
=
NULL
)
{
/*
definition
d'un
tableau
de
char
destine
a
recevoir
la
ligne
*
La
taille
est
arbitraire.
Elle
doit
etre
cependant
adaptee
*
aux
besoins
courants.
*
Pour
les
grandes
tailles
(disons
>
256
char),
*
il
est
preferable
d'utiliser
une
allocation
dynamique.
*/
char
ligne[32
];
/*
lecture
de
la
premiere
ligne
*/
fgets (ligne, sizeof
ligne, fp);
/*
Affichage
de
la
premiere
ligne
*/
printf ("
1:
%s\n
"
, ligne);
/*
lecture
de
la
deuxieme
ligne
*/
fgets (ligne, sizeof
ligne, fp);
/*
Affichage
de
la
deuxieme
ligne
*/
printf ("
2:
%s\n
"
, ligne);
/*
Fermeture
du
fichier
*/
fclose (fp);
}
else
{
printf ("
Erreur
d'ouverture
du
fichier\n
"
);
}
return
0
;
}
On doit obtenir ceci sur la sortie standard (stdout):
1: Ceci est un simple fichier
2: texte de 2 lignes.
XXXIII-B-4-d-ii. Explication▲
La ligne lue est stock�e dans la variable ligne, y compris le '\n'. La fonction d'affichage printf() affiche le num�ro de ligne, suivit de ': ', la ligne (avec son '\n') et un '\n' en plus, ce qui explique la pr�sence de lignes "vides".
XXXIII-B-4-d-iii. Critique de cet exemple▲
Cet exemple de codage 'na�f' souffre d'un d�faut majeur : Il fait l'hypoth�se que le fichier fait 2 lignes, et il continue � lire le fichier m�me si une erreur de lecture s'est produite. En fait, tout simplement, il ne g�re pas les erreurs de lecture.
Il est facile de g�rer les erreurs de lecture. Toutes les fonctions de lecture retournent une valeur. Celle-ci peut prendre une valeur particuli�re qui signifie 'Arr�t de la lecture'. La cause n'est pas pr�cis�e. �a peut �tre � cause d'une erreur (support en panne, donn�es corrompu, fichier inexistant etc.) ou tout simplement par ce que la fin de fichier a �t� atteinte.
XXXIII-B-4-d-iv. D�tection d'une erreur▲
La fonction fgets() retourne une valeur de type char *. Si la lecture a r�ussi, la valeur retourn�e est l'adresse du tableau de char pass� en param�tre. En cas d'�chec, la valeur NULL est retourn�e. Il suffit donc de surveiller cette valeur pour savoir si on peut continuer ou non. Comme une des causes d'�chec est la "fin de fichier atteinte", on peut donc parfaitement int�grer ce test dans une boucle de lecture "ligne par ligne".
Une fois l'�chec de la lecture constat�, il est possible d'en identifier la cause. Le langage C met � disposition les deux fonctions feof() et ferror() qu'il faut appeler apr�s la boucle de lecture, mais avant la fermeture du fichier.
while
(fonction_de_lecture
(fp) !
=
ERREUR)
{
...
}
if
(feof
(fp))
{
/*
la
fin
de
fichier
a
ete
detectee
*/
puts ("
EOF
"
);
}
if
(ferror
(fp))
{
/*
une
erreur
s'est
produite
*/
perror (NOM_DU_FICHIER);
}
fclose (fp);
XXXIII-B-4-d-v. Gestion des fins de ligne▲
On constate que lorsque fgets() lit une ligne enti�re, un '\n' se retrouve � la fin de la chaine saisie. La pr�sence de '\n' est g�nante ou non selon l'application.
Ceci dit, dans tous les cas, il est conseill� d'en d�tecter la pr�sence. En effet, sa pr�sence indique que la ligne a �t� lue enti�rement, alors que son absence indique que la ligne a �t� tronqu�e, et que d'autres caract�res (au minimum un '\n') attendent pour �tre lus. Il est donc conseill� d'�crire ces quelques lignes apr�s un fgets() pour clarifier la situation :
#
include
<stdio.h>
#
include
<string.h>
...
{
char
ligne[123
];
/*
test
d'erreur
omis
*/
fgets (ligne, sizeof
ligne, fp);
{
/*
chercher
le
'\n'
*/
char
*
p =
strchr
(ligne, '
\n
'
);
if
(p !
=
NULL
)
{
/*
si
on
l'a
trouve,
on
l'elimine.
*/
*
p =
0
;
}
else
{
/*
Le
traitement
depend
de
l'application.
*
Par
exemple,
ici,
on
choisi
d'ignorer
*
les
autres
caracteres.
*/
/*
sinon,
on
lit
tous
les
caracteres
restants
*/
int
c;
while
((c =
fgetc
(fp)) !
=
'
\n
'
&
&
c !
=
EOF)
{
}
}
}
}
Il est clair que dans la pratique, l'ensemble de ce code devra �tre int�gr� dans une fonction unique de lecture d'une ligne � partir d'un flux.
XXXIII-B-4-d-vi. Exemple am�lior� avec d�tection de la fin de lecture▲
/*
fichier2.c
*/
#
include
<stdio.h>
int
main (void
)
{
FILE *
fp =
fopen ("
data.txt
"
, "
r
"
);
if
(fp !
=
NULL
)
{
char
ligne[32
];
/*
definition
d'un
compteur
de
lignes
et
initialisation
*/
int
cpt =
0
;
/*
lecture
des
lignes
*/
while
(fgets (ligne, sizeof
ligne, fp) !
=
NULL
)
{
/*
Mise
a
jour
du
compteur
*/
cpt+
+
;
/*
Affichage
des
lignes
*/
printf ("
%d:
%s\n
"
, cpt, ligne);
}
/*
On
peut
ajouter
ici
la
detection
de
la
cause
*
de
l'erreur
decrite
ci-dessus
*/
fclose (fp);
}
else
{
printf ("
Erreur
d'ouverture
du
fichier\n
"
);
}
return
0
;
}
Cet exemple met en oeuvre un m�canisme qui s'adapte automatiquement au nombre de lignes du fichier. Cependant, attention, le fonctionnement, bien qu'il reste s�r, risque d'�tre surprenant si la longueur de la ligne est sup�rieure � celle du tableau 'ligne'.
Par exemple, si on diminue la taille de 'ligne' � 16 au lieu de 32,
<
...>
char
ligne[16
];
<
...>
on obtient :
1: Ceci est un sim
2: ple fichier
3: texte de 2 lign
4: es.
XXXIII-B-4-d-vii. Explication▲
Rappelons que la taille du tableau de char a �t� transmise � la fonction fgets().
Celle-ci tente de lire la ligne, mais celle-ci est trop longue pour tenir dans le variable 'ligne'. fgets(), qui conna�t la taille de la variable 'ligne', applique alors une strat�gie d'adaptation qui consiste � stocker ce qui est possible dans la variable, en laissant une place pour le 0 final. En effet, fgets() a pour obligation de produire une chaine de caract�res valide dans tous les cas.
C'est pourquoi la premi�re ligne est partiellement lue ainsi :
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
: Indice
'
C
'
'
e
'
'
c
'
'
i
'
'
'
'
e
'
'
s
'
'
t
'
'
'
'
u
'
'
n
'
'
'
'
s
'
'
i
'
'
m
'
0
: Donn�es
Mais les caract�res manquants ne sont pas perdus, et ils sont lus par l'appel suivant:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
: Indice
'
p
'
'
l
'
'
e
'
'
'
'
f
'
'
i
'
'
c
'
'
h
'
'
i
'
'
e
'
'
r
'
'
\n
'
0
: Donn�es
Cette fois, la place est suffisante, et l'ensemble de la chaine est lue, y compris le '\n'.
XXXIII-B-5. �criture dans un fichier▲
Le langage C offre plusieurs fonctions permettant d'�crire des donn�es dans un fichier.
- fputc()
- putc()
- fwrite()
- fprintf()
- fputs()
XXXIII-B-5-a. fputc(), putc()▲
Ces fonctions sont identiques. Elles permettent d'�crire un caract�re.
XXXIII-B-5-b. fwrite()▲
Cette fonction permet d'�crire un bloc de caract�res d'une longueur donn�e. Elle est tout � fait adapt�e � l'�criture de donn�es binaires brutes (non interpr�t�es).
XXXIII-B-5-c. fprintf()▲
Cette fonction permet d'�crire des donn�es 'texte' format�es. Elle comporte de nombreuses possibilit�s de conversion de valeurs num�riques en texte. (Entiers, flottants etc.)
XXXIII-B-5-d. fputs()▲
Cette fonction permet d'�crire une chaine de caract�res.
XXXIII-B-6. Bien utiliser les formats de donn�es▲
Il n'est pas rare que des donn�es enregistr�es dans un fichier par une machine soient lues par une autre machine, ou par autre programme ou par le m�me programme mais compil� avec des options diff�rentes. Pour pouvoir r�cup�rer les donn�es, il faut qu'en aucun cas, le format des donn�es enregistr�es ne d�pende de l'impl�mentation.
XXXIII-B-6-a. Format orient� texte▲
Le format texte est un bon choix, car il utilise une s�quence de caract�res simple et �vidente (chronologique) et un codage tr�s r�pandu (ASCII). Il peut y avoir quelques probl�mes de transcodage pour les valeurs de 128 � 255 (ANSI, OEM etc.), mais rien qui ne soit insurmontable. D'autre part, la conversion ASCII/EBCDIC est triviale.
Il subsiste le probl�me des fins de ligne qui sont diff�rentes d'un syst�me � l'autre. Il existe des utilitaires bien connus (dos2unix, unix2dos etc.) g�n�ralement fournis avec ces syst�mes qui font les conversions. Rappelons que la fonction system() permet d'appeler une commande ext�rieure. Si n�anmoins, cet utilitaire n'existait pas, il serait facile de le faire soi-m�me. Bien s�r, il faudrait travailler en mode binaire de fa�on � contr�ler les donn�es du fichier de mani�re 'brute' (raw).
Les cha�nes et les valeurs num�riques sont encod�es et �ventuellement format�es avec fprintf(). Une organisation en ligne est souhaitable. Elles sont ensuite lues ligne par ligne avec fgets() et analys�es soit par strtol(), strtoul() ou strtod() pour les cas les plus simples (valeurs num�riques pures), soit par sscanf() pour les cas plus complexes, � condition que le formatage soit clairement d�fini. Il est souhaitable d'utiliser des formats simples � analyser et surtout sans ambigu�t� quant aux s�parateurs. Le format CSV est recommand�.
XXXIII-B-6-b. Format orient� binaire▲
Une mauvaise utilisation des formats binaires (raw) peut apporter des probl�mes de portabilit�. Il est recommand� d'utiliser des formats ind�pendants comme XDR (RFC 1832).
XXXIII-C. Supprimer un enregistrement dans un fichier binaire▲
Pour supprimer un enregistrement, le plus simple est de proc�der ainsi:
- Le fichier original est ouvert en lecture. Un nouveau fichier est ouvert en �criture. L'original est lu enregistrement par enregistrement (fread()), et recopi� dans le nouveau fichier (fwrite()) en omettant l'enregistrement � supprimer (if ...).
- Par un jeu subtil de suppression et de renommage (remove(), rename()), on se retrouve avec une copie de l'original (genre .old ou .bak) et le nouveau fichier qui a maintenant le nom de l'ancien. L'op�ration reste simple, et a l'avantage de permettre l'annulation (par renommage de l'ancien fichier).
Toute autre op�ration bas�e sur l'�criture/lecture dans le m�me fichier est dangereuse, non portable et se traduit souvent par la destruction du fichier original sans recours possible.
XXXIII-D. En guise de conclusion▲
Il ne faut pas se tromper d'outil. Les flux du C sur disque sont tr�s pratiques pour enregistrer quelques donn�es statiques dans un fichier texte. En binaire, c'est d�j� plus risqu� � moins de passer par un format ind�pendant comme XDR. Pour g�rer des enregistrements, les fichiers C sont trop rustiques. Il faut une v�ritable base de donn�es (comme SQLite ou MySQL par exemple).
XXXIV. Pourquoi fflush (stdout) ?▲
Il arrive parfois de rencontrer ce genre de code ...
printf
("
Entrez
un
nombre
:
"
);
fflush (stdout);
... et on se demande alors � quoi peut bien servir ce fflush (stdout).
Le printf() pr�c�dent envoie une chaine de caract�res � stdout. Or cette chaine n'est pas termin�e par un '\n'.
Il faut savoir que stdout est souvent un flux "bufferis�", ce qui signifie, en bon fran�ais, que les caract�res sont plac�s dans un tampon (buffer) de sortie avant d'�tre r�ellement �mis.
Il y a trois crit�res qui d�clenchent l'�mission r�elle des caract�res :
- Le tampon d'�mission est plein (incontr�lable)
- Un '\n' a �t� plac� dans le tampon[1]
- La commande de for�age a �t� activ�e
La commande de for�age est activ�e par l'appel de la fonction fflush (stdout), ce qui explique sa pr�sence dans le code mentionn�.
[1] sauf en cas de redirection dudit flux vers un fichier.