Adloun

informatique (MP2I/MPI) · Chapitre 8 · Exercice de TD

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

Mémoire, fichiers et entrées-sorties · niveau 2

É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.

Exercices semblables

Le cours du chapitre · Tous les exercices du chapitre