IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Notes sur le langage C

Notes sur le langage C


pr�c�dentsommairesuivant

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.

D�tails de fonctionnement de fgetc()

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� :

 
Sélectionnez
#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 :

 
Sélectionnez
#include <stdio.h>
 
int main (void)
{
 
   int x = fgetc(stdin);
 
   printf ("x = %d ('%c')\n", x, x);
 
   return 0;
}

Quelques essais de saisie :

 
Sélectionnez
<enter>
x = 10 ('
')

On voit que le caract�re extrait est '\n' (ici, LF, soit le code ASCII 10)

 
Sélectionnez
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.

 
Sélectionnez
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.

 
Sélectionnez
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.

 
Sélectionnez
#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)

 
Sélectionnez
:----------------:--------------:----------------:
: 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>.

 
Sélectionnez
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 :

 
Sélectionnez
   "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 :

 
Sélectionnez
Ceci est un simple fichier
texte de 2 lignes.

et un petit programme permettant de lire ces 2 lignes

 
Sélectionnez
/* 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):

 
Sélectionnez
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.

 
Sélectionnez
     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 :

 
Sélectionnez
#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
 
Sélectionnez
/* 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,

 
Sélectionnez
<...>
   char ligne[16];
<...>
  

on obtient :

 
Sélectionnez
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 :

 
Sélectionnez
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:

 
Sélectionnez
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 ...

 
Sélectionnez

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.


pr�c�dentsommairesuivant