Page suivante Page précédente Table des matières
11. La bibliothèque standard sous Linux : seconde partie
Par James M. Rogers.
11.1 Les entrées/sorties de caractères de
<stdio.h>
L'article précédent traitait des opérations sur les fichiers de la bibliothèque d'E/S standard
<stdio.h>
. Cet article parle de la lecture et de l'écriture de caractères, de chaînes de caractères et de tableaux, à partir de, et vers un flux. Je considère que le lecteur a une certaine connaissance de la programmation C. Aucune garantie quant à l'exactitude des informations données ici ou à leur utilisabilité n'est donnée pour quelque usage que ce soit.Comme exemple de traitement basé sur des caractères, nous allons utiliser un programme qui lit le nombre de caractères, de mots et de lignes d'un fichier sur l'entrée standard et affiche les résultats sur la sortie standard. Les erreurs éventuellement rencontrées seront affichées sur l'erreur standard. Ce sera en fait une version simplifiée de
wc
(tapezman wc
pour plus d'informations sur ce programme utilitaire UNIX).Les exemples de code donnés pour chaque fonction ne fonctionneront normalement pas à moins que les objets entre chevrons ne soient remplacés par du code réel. Normalement, ce sont des choses qui doivent être traitées différement selon ce que vous essayez de faire. Comme toujours, si vous voyez une erreur dans ma documentation, veuillez me le signaler et je me corrigerai dans un futur document.
#include <stdio.h> /* inclure les en-têtes appropriées */ #define IN 1 /* en train de regarder à l'intérieur d'un mot */ #define OUT 0 /* en train de regarder un espace */ /* compte le nombre de lignes, de mots et de caractères sur l'entrée standard */ main() { int c, /* stocke le caractère retourné par getchar */ characters, /* le nombre de caractères */ lines, /* le nombre de lignes */ words, /* le nombre de mots */ state; /* sommes-nous à l'intérieur d'un mot ou non */ /* initialise le compteur et positionne l'état à "à l'extérieur d'un mot" */ state=OUT; characters = words = lines = 0; /* prend un caractère à la fois sur l'entrée standard jusqu'à EOF */ while ((c = getchar()) != EOF) { characters++; /* incrémente le compteur de caractères */ switch(c) { case '\n' : lines++; /* incrémente le compteur de lignes */ state = OUT; /* un caractère de nouvelle ligne est un espace en dehors d'un mot */ break; case ' ' : state = OUT; /* un espace, en dehors d'un mot */ break; case '\t': state = OUT; /* une tabulation est un espace, en dehors d'un mot */ break; default : /* nous sommes dans un mot */ if (state == OUT) { /* si state est toujours out et que nous sommes dans un mot, c'est que nous sommes à la première lettre du mot */ state = IN; /* met à jour state vers "in" */ words++; /* incrémente le nombre de mots */ } break; } } /* affiche les résultats de manière formatée */ printf("%d %d %d\n", characters, words, lines); }
Pour lire un caractère sur un flux :
int getchar (void); int getc(FILE *stream); int fgetc(FILE *stream); int ungetc(int c, FILE *stream);
void
ceci est laissé blanc.FILE *stream
est un flux déjà existant.int c
est un caractère à remettre dans le flux.Ces fonctions retournent un
int
avec la valeur du prochain caractère dans le flux. S'il n'y a plus de caractères, un indicateur EOF est positionné pour le flux et la fonction retourne EOF. S'il s'est produit une erreur de lecture alors l'indicateur d'erreur est positionné pour le flux et la fonction retourne EOF.getchar est utilisé pour lire un unique caractère sur l'entrée standard.
int c; while((c = getchar()) != EOF) { <tant que non EOF, traiter le caractère> }
getc est utilisé pour lire un unique caractère sur un flux.
int c; FILE *stream; if((stream = fopen ("filename", "r")) != (FILE *)0) { while((c = getc(stream)) != EOF) { <traiter chaque caractère> } } else { <faire le traitement d'erreur> }
fgetc est utilisé pour lire un unique caractère sur un flux.
getchar
etgetc
peuvent être écrits à l'aide defgetc
:getchar()
est la même chose quefgetc(stdin)
etgetc(x)
est identique àfgetc(x)
.
int c; FILE *stream; if ((stream = fopen ("filename", "r")) != (FILE *)0) { while((c = fgetc(stream)) != EOF) { <traiter chaque caractère> } } else { <faire le traitement d'erreur> }
ungetc est utilisé pour envoyer un caractère dans un flux quand vous en avez lu un de trop. C'est un problème courant avec les compilateurs et les analyseurs de motifs. Il est possible de renvoyer plus d'un caractère mais cela n'est pas recommandé dans la mesure où ce n'est pas portable. Un
ungetc
devrait suivre unread
et ne renvoyer qu'un unique caractère.
int c; FILE *stream; if((stream = fopen ("filename", "r")) != (FILE *)0) { while((c = fgetc(stream)) != EOF) { <traiter chaque caractère> if (some_condition) { ungetc(c,stream); break; } } } else { <faire le traitement d'erreur> }
Pour écrire un caractère dans un flux
int putchar(int c); int putc(int c, FILE *stream); int fputc(int c, FILE *stream);
FILE *stream
est un flux déjà existant.int c
est un caractère à écrire dans le flux.Ces fonctions retournent le caractère écrit en cas de succès. Si une erreur d'écriture intervient, l'indicateur d'erreur est positionné pour le flux et la fonction retourne EOF.
putchar écrit un caractère sur la sortie standard.
putchar(x)
fait la même chose quefputc(x, stdout)
.
putchar('x')
putc écrit un caractère vers le flux.
putc(x,y)
est identique àfputc(x,y)
.
int c; FILE *stream; c='x'; if((stream = fopen ("filename", "w")) != (FILE *)0) { putc(c, stream); } else { <traitement d'erreur> }
fputc écrit un caractère vers le flux.
int c; FILE *stream; c='y'; if((stream = fopen ("filename", "w")) != (FILE *)0) { fputc(c, stream); } else { <traitement d'erreur> }
Pour lire un caractère sur un flux
char *gets(char *s); char *fgets(char *s, int n, FILE *stream);
char *s
est la chaîne qui va contenir le résultat.int n
est le nombre maximal de caractères à lire.FILE *stream
est un flux déjà existant.Si le read réussit, le pointeur vers
s
est retourné. Si EOF est rencontré et qu'aucun caractère n'a été lu dans la chaîne de caractères, celle-ci reste inchangée et un pointeur NULL est retourné. Si une erreur de lecture intervient, le contenu de la chaîne de caractères peut avoir été modifié d'une manière indéterminée et un pointeur NULL est retourné.gets lit du flux vers la chaîne de caractères jusqu'à rencontrer un caractère de nouvelle ligne ou un marqueur de fin de fichier. N'utilisez jamais cette fonction. Utilisez
fgets
à la place. Il n'y a pas de vérifications d'espace pour voir si la chaîne de caractères retournée tient dans l'espace qu'on lui a alloué. De nombreuses applications ont été utilisées comme trou de sécurité dans le passé en se basant sur l'écrasement de la fin d'une chaîne de caractères.fgets lit au moins n caractères du flux vers la chaîne de caractères.
char s[1024]; FILE *stream; if((stream = fopen ("filename", "r")) != (FILE *)0) { while((fgets(s, 1023, stream)) != (char *)0 ) { <traiter chaque ligne> } } else { <faire le traitement d'erreurs de fopen> }
Pour écrire une chaîne de caractères dans un flux,
int puts(const char *s); int fputs(const char *s, FILE *stream);
const char *s
FILE *stream
est un flux déjà existant.Retourne une valeur non négative en cas de succès. Retourne un EOF en cas d'erreur d'écriture.
puts écrit la chaîne pointée par
s
vers le flux STDIO et rajoute un caractère nouvelle ligne à la fin. Le caractère NULL de terminaison n'est pas écrit dans le flux.
char s[1024]; FILE *stream; strcpy(s,"a typical string"); if((stream = fopen ("filename", "w")) != (FILE *)0) { if(puts(s, stream) == EOF ) { <gérer l'erreur d'écriture> } } else { <gérer l'erreur de lecture> }
fputs écrit la chaîne pointée par
s
vers le flux nommé. Le caractère NULL de terminaison n'est pas écrit dans le flux.
char s[1024]; FILE *stream; strcpy(s,"a typical string"); if((stream = fopen ("filename", "w")) != (FILE *)0) { if(fputs(s, stream) == EOF ) { <gérer l'erreur d'écriture> } } else { <gérer l'erreur de lecture> }
Pour lire/écrire entre des tableaux et des flux,
size_t fread(const void *ptr, size_t size, size_t nmemb, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
const void *ptr
est un pointeur vers le tableau.size_t size
est la taille de chaque élément du tableau.size_t nmemb
est le nombre d'éléments à traiter.FILE *stream
est un flux déjà existant.fread lit vers le tableau pointé par
ptr
, jusqu'à concurrence denmemb
éléments de taillesize
à partir du flux. Ces fonctions retournent le nombre d'éléments qui ont été lus avec succès : cette valeur peut être inférieure à ce qui avait été demandé si la fonction rencontre une erreur de lecture ou un marqueur EOF. Une erreur de lecture laisse l'élément fautif dans un état indéterminé. Sisize
ounmemb
sont égaux à zéro, la fonction retourne zéro.
int a[10]; FILE *stream; if((stream = fopen ("filename", "r")) != (FILE *)0) { if (fread(a, sizeof(a), 10, stream) < 10){ <gérer l'erreur de lecture> } } else { <gérer une erreur d'ouverture de fichier> }
fwrite écrit d'un tableau pointé par
ptr
un nombre maximal nmeb d'éléments de taillesize
vers le flux. Cette fonction retourne le nombre d'éléments écrits avec succès, ce qui devrait être égal ànmemb
si il n'y a pas eu d'erreurs d'écriture.
int a[10]; FILE *stream; if((stream = fopen ("filename", "w")) != (FILE *)0) { if (fwrite(a, sizeof(a), 10, stream) < 10){ <gérer une erreur d'écriture> } } else { <gérer une erreur d'ouverture de fichier> }
11.2 Bibliographie :
- The ANSI C Programming Language, Second Edition, Brian W. Kernighan, Dennis M. Ritchie, Printice Hall Software Series, 1988
- The Standard C Library, P. J. Plauger, Printice Hall P T R, 1992
- The Standard C Library, Parts 1, 2, and 3, Chuck Allison, C/C++ Users Journal, Janvier, Février, Mars 1995
- STDIO(3), BSD MANPAGE, Linux Programmer's Manual, 29 Novembre 1993
- The Standard C Library for Linux, Part One, James M. Rogers, Janvier 1998
Copyright © 1998, James Rogers - Publié dans le n°31 de la Linux Gazette.
Adaptation française de Pierre Tane
Page suivante Page précédente Table des matières