17.4.3 Lecture d'un fichier texte par fgets combiné à sscanf (conseillé)

Icône de l'outil pédagogique Lecture d'un fichier texte par fgets combiné à sscanf (conseillé)

Quand on manipule un fichier texte, tapé par exemple avec un éditeur, il arrive souvent qu'on veuille analyser le contenu du fichier mot après mot, ligne après ligne (comme le fait un compilateur de langage quelconque). Il existe pour cela beaucoup de fonctions de traitement de chaînes très utiles, en particulier pour les recherches et les comparaisons (cf paragraphe 12.3.2 du chapitre "Chaînes de caractères"). Encore faut‐il que le texte à analyser existe sous forme de chaînes de caractères. C'est l'application rêvée pour la fonction fgets, qui lit une ligne entière du fichier et la range dans une chaîne.

Comme fgets lit une ligne entière, elle est aussi utile à ceux qui cherchent les fins de ligne. Mais de façon générale, si on la combine avec sscanf (ou strtok ou ...), elle se substitue complètement à fscanf, tout en étant plus simple.

La syntaxe d'utilisation de fgets est :

ptr = fgets ( chaine, taille_chaine, ptr_fic );
ou plus souvent
while ( fgets( chaine, taille_chaine, ptr_fic ) != NULL ) { … }

fgets lit au maximum taille_chaine‐1 caractères de la ligne du fichier, et s'arrête au caractère fin de ligne s'il est rencontré (attention : il est aussi copié dans la chaîne). Elle renvoie NULL si la fin du fichier est rencontrée ou si un problème se produit. Le test de la valeur renvoyée est donc indispensable, ne serait‐ce que pour savoir si on a atteint la fin du fichier.

Voici un exemple d'utilisation de fgets, qui copie à l'écran le contenu d'un fichier texte.

Exemple 104 : Copie à l'écran d'un fichier texte (lecture des lignes par fgets)

char ligne[81] ;
/* le fichier est supposé ouvert en mode "rt" */
while ( fgets(ligne, 81, fichier) != NULL ) /*fin de fichier non atteinte*/
printf("%s", ligne ) ; /*affiche la ligne lue à l'écran*/

Conseil (rappel) : préférez toujours l'utilisation de fgets, suivie éventuellement par sscanf (ou strtok), à celle de fscanf. Entre autres avantages, la gestion de la fin de fichier est beaucoup plus simple avec fgets.

La fonction fgets peut être complétée par une fonction de lecture dans une chaîne nommée sscanf (String scanf), ou par des fonctions de recherche comme strtok. L'intérêt de fgets est justement de permettre l'utilisation des nombreuses fonctions de traitement de chaînes de caractères pour l'exploitation d'une ligne du fichier.

La combinaison de fgets avec sscanf remplace complètement fscanf, et permet de mieux gérer les problèmes de saisie. D'ailleurs, sscanf se combine aussi bien avec fgets qu'avec gets (lecture d'une ligne au clavier).
sscanf fait le même travail que scanf ou fscanf, mais au lieu de travailler sur le tampon de saisie du C ou sur un fichier, elle lit dans la chaîne de caractères qu'on lui fournit en paramètre. Ce paramètre supplémentaire est la seule différence avec scanf.

Pour la lecture de données dans un fichier :

- on lit une ligne du fichier avec fgets et on la mémorise dans une chaîne de caractères, qu'on appelle par exemple ligne ; on est ensuite ramené à un traitement de chaîne de caractères.

- on isole le contenu utile de ligne avec sscanf, en utilisant les codes formats qui conviennent (comme pour scanf). On peut aussi utiliser des fonctions de recherche comme strtok si la ligne comporte des séparateurs connus.

Exemple 105 : Lecture de fichier texte avec fgets + analyse par sscanf

Chaque ligne du fichier de données essai.dat a le format imposé suivant :

un nom (sans espaces) suivi par une date de naissance de la forme « 12 janvier 1970 ».

La première ligne vaut par exemple : "Anne-Laure 2 septembre 1980".

On choisit ici de mémoriser les données lues dans le fichier dans une variable structurée (sinon, voir Exemple 106).

On peut indiquer à sscanf que des éléments non significatifs doivent être ignorés à la lecture ; il suffit d’insérer le symbole * dans le code format, entre % et la lettre du format. Par exemple : %*s pour ignorer un mot (un seul !), %*d pour ignorer un entier. Cela permet de « sauter » les chaînes de caractères ou les valeurs non désirées, sans les mémoriser (et sans les comptabiliser dans la valeur renvoyée par sscanf).

Par exemple, supposons qu’une ligne du fichier précédent contienne des éléments non utiles et se présente comme suit : "Anne-Laure ; née le 2 septembre 1980". Le sscanf s’écrit alors :

sscanf(ligne,"%s%*s%*s%*s%hd%s%hd", pers.nom, &pers.jour, pers.mois,&pers.annee )

Rappelons que les espaces, les tabulations et les passages à la ligne sont considérés comme des séparateurs par scanf et ses dérivés, et qu'ils sont automatiquement sautés lors de la lecture d'une valeur numérique ou d'une chaîne de caractères (mais pas d'un caractère !!).

La lecture d’un fichier texte est délicate : pour la simplifier, il suffit souvent de s’imposer un format de ligne bien choisi, le plus simple possible.

Dans l’Exemple 106. suivant, le fichier texte à lire dispose d’une en‐tête de longueur variable dont chaque ligne commence par $. Voici un exemple pour ce fichier :

$ Fichier TEXTE de test
$ pour lecture par fgets + sscanf

Ariane - age: 21 ans - taille: 1.61 m
Chloé - age: 23 ans - taille: 1.63 m
Eve - age: 25 ans - taille: 1.65 m
Iris - age: 29 ans - taille: 1.69 m

 

Et voici l’affichage qui sera obtenu à la fin du programme de l’Exemple 106 :

 

Exemple 106 : Lecture de fichier texte avec fgets + analyse par sscanf

 

Exemple 107 : Lecture par fgets et comptage de mots avec sscanf