Adloun

Ce que fscanf renvoie, et ce qu'il coûte de l'ignorer

Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 8 — Mémoire, fichiers et entrées-sorties

Énoncé

Le fichier mixte.txt contient la ligne 12 7 abc 5. Que fait la première boucle ? La seconde ?


/* (A) */  while (!feof(f)) { fscanf(f, "%d", &x); somme = somme + x; }

/* (B) */  while (fscanf(f, "%d", &x) == 1) { somme = somme + x; }

Corrigé

(B) est correcte : elle lit puis , échoue sur abc, et s'arrête. Mesure : somme après tours.

(A) est une boucle infinie, et la mesure le montre : bridée à douze tours, elle donne . Voici pourquoi, et il y a deux fautes indépendantes.

Première faute : fscanf peut échouer sans consommer. Devant abc, la conversion %d échoue ; fscanf rend et laisse les caractères dans le flux. On les retrouvera au tour suivant, à l'identique, indéfiniment.

Seconde faute : x n'est pas modifié en cas d'échec. La boucle ajoute donc onze fois la dernière valeur lue, . Ce n'est même pas de la mémoire indéterminée — c'est une vieille valeur, parfaitement plausible, ce qui rend le résultat d'autant plus difficile à mettre en doute.

Troisième piège, celui du nom : feof ne prédit pas la fin, il constate qu'une lecture a déjà buté dessus. Tant qu'aucune lecture n'a atteint la fin du fichier, feof rend faux — et ici aucune ne l'atteindra jamais, puisqu'on est bloqué sur abc.

La règle, et elle vaut pour toute la famille : une fonction de lecture rend le nombre de conversions réussies, et c'est cette valeur — pas feof — qui pilote la boucle. On écrit == 1 et non != EOF : fscanf rend sur une donnée malformée et EOF seulement en fin de fichier, et l'on veut s'arrêter dans les deux cas.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.