Adloun

Ouvrir, vérifier, fermer

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

Énoncé

Écrire une fonction qui rend la somme des entiers contenus dans un fichier, en distinguant l'échec d'ouverture du fichier vide. Donner sa spécification.

Corrigé

Le premier travail n'est pas d'écrire la boucle, c'est de décider ce que la fonction rend dans chaque cas. Trois situations sont possibles — fichier absent, fichier vide, fichier lisible — et la valeur ne peut pas les distinguer. On rend donc le succès à part.


/* Range dans *somme la somme des entiers ecrits dans le fichier chemin.
   Renvoie le nombre d'entiers lus, ou -1 si le fichier n'a pas pu etre ouvert.
   Precondition  : chemin et somme non nuls.
   Postcondition : en cas de succes, *somme est la somme des entiers lus ;
                   un fichier vide donne 0 entiers lus et *somme = 0. */
int somme_fichier(const char* chemin, long* somme) {
    assert(chemin != NULL && somme != NULL);
    FILE* f = fopen(chemin, "r");
    if (f == NULL) { return -1; }        /* PAS de deref, PAS de fclose */
    *somme = 0;
    int combien = 0, x = 0;
    /* INVARIANT : *somme est la somme des `combien` premiers entiers du
       fichier, et la position courante est juste apres le dernier lu. */
    while (fscanf(f, "%d", &x) == 1) {
        *somme = *somme + x;
        combien = combien + 1;
    }
    fclose(f);
    return combien;
}

Terminaison. Le variant est le nombre d'octets restant à lire : chaque tour réussi en consomme au moins un, et fscanf rend autre chose que dès qu'il n'y a plus d'entier à lire. Complexité : où est la taille du fichier en octets, et en mémoire — on ne stocke rien.

Les quatre fautes que cette écriture évite, et qui sont les quatre fautes classiques du chapitre :

*Le type de </em>somme.** On l'a pris long et non int : une somme déborde bien plus vite qu'un terme, et un débordement d'entier signé est silencieux (chapitre chap:langage-c). Une version défensive complète testerait aussi ce débordement avant chaque addition.

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.