Page suivante Page précédente Table des matières

6. Manipulation des fichiers, opérations de haut niveau

Ici on utilise le terme « fichier » dans son sens Unixien le plus large, ce qui inclue les périphériques (comme /dev/tty, /dev/audio,...) aussi bien que les « pseudo-fichiers » comme /proc/cpuinfo, /proc/sound, etc.

6.1 Flots standards

Il y a trois flots prédéclarés, qui correspondent à l'entrée et la sortie standards, et à la sortie d'erreur :

#include <stdio.h>
FILE *stdin;
FILE *stdout;
FILE *stderr;

Quelques fonctions agissent implicitement sur ces flots:

int printf(const char *format, ...);     
int scanf(const char *format, ...);      
int getchar(void);                       
char *gets(char *s);                     

printf(...) écrit sur stdout la valeur d'expressions selon un format donné. scanf(...) lit sur stdin la valeur de variables.


 
  1     /* facture.c */

  2     /* exemple printf(), scanf() */

  3     #include <stdlib.h>
  4     #include <stdio.h>

  5     int main(void)
  6     {
  7             char article[10];
  8             float prix;
  9             int quantite;
 10             int n;

 11             printf("article, prix unitaire, quantité ?\n");
 12             n = scanf("%s %f %d", article, &prix, &quantite);

 13             if (n != 3) {           /* on n'a pas réussi à lire 3 choses ? */
 14                     printf("Erreur dans les données");
 15                     exit(EXIT_FAILURE);
 16             }

 17             printf("%d %s à %10.2f =  %10.2f\n",
 18                    quantite, article, prix, prix * quantite);
 19             exit(EXIT_SUCCESS);
 20     }
 

scanf() renvoie le nombre d'objets qui ont pu être effectivement lus sans erreur.

gets() lit des caractères jusqu'à une marque de fin de ligne ou de fin de fichier, et les place (marque non comprise) dans le tampon donné en paramètre, suivis par un caractère NUL. gets() renvoie finalement l'adresse du tampon. Attention, prévoir un tampon assez grand, ou (beaucoup mieux) utilisez fgets().

getchar() lit un caractère sur l'entrée standard et retourne sa valeur sous forme d'entier positif, ou la constante EOF (-1) en fin de fichier.

6.2 Opérations sur les flots

#include <stdio.h>
FILE *fopen(char *path, char *mode);
int fclose(FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);

fopen() tente d'ouvrir le fichier désigné par la chaîne path selon le mode indiqué, qui peut être "r" (lecture seulement), "r+" (lecture et écriture), "w" (écriture seulement), "w+" (lecture et écriture, effacement si le fichier existe déjà), "a" (écriture à partir de la fin du fichier si il existe déjà), "a+" (lecture et écriture, positionnement à la fin du fichier si il existe déjà).

Si l'ouverture échoue, fopen() retourne le pointeur NULL.

int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);

Les trois premières fonctions ne diffèrent de printf(), scanf() et getchar() que par le premier paramètre, qui précise sur quel flot porte l'opération.

Comme gets(), fgets() lit une ligne de caractères pour la placer dans un tampon, mais

  1. la longueur de ce tampon est précisée (ceci empêche les débordements)
  2. le caractère de fin de ligne (newline) est effectivement stocké dans le tampon.

Exemple : comptage du nombre de caractères et de lignes d'un fichier. Affichage du résultat sur la sortie standard.


 
  1     /* comptage.c */

  2     #include <stdio.h>
  3     #include <stdlib.h>

  4     void compter(char nom[], FILE * f)
  5     {
  6             int c, cars = 0, lignes = 0;
  7             while ((c = fgetc(f)) != EOF) {
  8                     cars++;
  9                     if (c == '\n')
 10                             lignes++;
 11             };
 12             printf("%s: %d cars, %d lignes\n", nom, cars, lignes);
 13     }

 14     int main(int argc, char *argv[])
 15     {
 16             char *nomfichier, *prog = argv[0];
 17             FILE *f;
 18             switch (argc) {
 19             case 1:
 20                     compter("entrée standard", stdin);
 21                     break;
 22             case 2:
 23                     nomfichier = argv[1];
 24                     f = fopen(nomfichier, "r");
 25                     if (f == NULL) {
 26                             fprintf(stderr,
 27                                     "%s: fichier %s absent ou illisible\n",
 28                                     prog, nomfichier);
 29                             exit(EXIT_FAILURE);
 30                     };
 31                     compter(nomfichier, f);
 32                     fclose(f);
 33                     break;
 34             default:
 35                     fprintf(stderr, "Usage: %s [fichier]\n", prog);
 36                     exit(EXIT_SUCCESS);
 37             };
 38             exit(EXIT_SUCCESS);
 39     }
 

6.3 Positionnement

int feof(FILE *stream);
long ftell(FILE *stream);
int fseek(FILE *stream, long offset, int whence);

feof() indique si la fin de fichier est atteinte. ftell() indique la position courante dans le fichier (0 = début). fseek() déplace la position courante : si whence est SEEK_SET la position est donnée par rapport au début du fichier, si c'est SEEK_CUR : déplacement par rapport à la position courante, SEEK_END : déplacement par rapport à la fin.

6.4 Divers

int ferror(FILE *stream);
void clearerr(FILE *stream);
int fileno(FILE *stream);
FILE *fdopen(int fildes, char *mode);

La fonctionferror() indique si une erreur a eu lieu sur un flot, clearerr() efface l'indicateur d'erreur et fileno() renvoie le numéro de fichier de bas niveau (descripteur de fichier) correspondant à un flot. Inversement, fdopen() ouvre un fichier de haut niveau à partir d'un fichier de bas niveau déjà ouvert.


Page suivante Page précédente Table des matières