IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

lecture d'un fichier et feof


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut lecture d'un fichier et feof
    Bonjour, je suis en train de reprendre un code. La fonction qui lit le fichier texte contenant les inputs est comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while(feof(file))
    {
      fgets(blabla);
    }
    Ce n'est pas très joli...

    J'ai lu http://c.developpez.com/faq/?page=fi...RS_fin_fichier.

    Pouvez-vous s'il vous plait me donner un exemple ou le code précédent ne fait pas ce que l'on croit : feof() détecte une fin de fichier alors que ce n'est pas vrai.

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    C'est pas tant ça le problème mais plutôt de continuer dans une boucle de lecture alors que tu peux avoir une erreur. D'où, l'idéé de la faq: lire tant que pas d'erreur. Puis, traiter soit fin de fichier, soit erreur.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    OK, je comprends mieux la nuance

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 476
    Par défaut
    Citation Envoyé par salseropom Voir le message
    Bonjour, je suis en train de reprendre un code. La fonction qui lit le fichier texte contenant les inputs est comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while(feof(file))
    {
      fgets(blabla);
    }
    Ce n'est pas très joli...

    Pouvez-vous s'il vous plait me donner un exemple ou le code précédent ne fait pas ce que l'on croit : feof() détecte une fin de fichier alors que ce n'est pas vrai.
    Je me suis effectivement fait reprendre comme un débutant sur ce piège-là. Mais déjà, ce code est erroné : il faudrait un point d'exclamation dans ta condition while avant le feof().

    Comme indiqué dans la page que tu nous donnes - et contrairement à d'autres langages - feof() n'indique pas directement si un fichier a atteint sa fin, mais si la dernière erreur est due à une fin de fichier en particulier ou pas. À y réfléchir, c'est vrai que ça se tient car quand le flux de caractères vient en fait de la console, du port série ou même d'une connexion TCP, par exemples, on ne peut pas savoir à l'avance si l'on a atteint la fin du fichier ou pas. Il faut attendre le signal. Un while(feof()) réentrerait alors dans la boucle, et le signal de fin de fichier tomberait au moment de la lecture du caractère suivant.

    Cependant, il est bien possible que ton code fonctionne quand même (modulo le point d'exclamation), car tu fais un fgets(), fonction conçue pour lire itérativement les caractères, jusqu'à tomber sur un retour à la ligne. Or, si le caractère reçu est un marqueur EOF, il est clair que fgets() ne va pas l'intégrer à la chaîne ainsi composée, contrairement à un fgetc() qui va renvoyer le résultat tel quel. Néanmoins, la fin de fichier ayant quand même été atteinte, et le code EOF renvoyé, feof() va renvoyer un signal positif.

    Ça n'en fait pas pour autant un programme valide car le problème exposé plus haut demeure. Le dernier caractère envoyé peut être une fin de ligne. Cela ferait sortir fgets(), faire faire un tour de plus à while(feof()) qui retomberait sur un nouveau fgets(), laquelle fonction serait alors obligée de renvoyer une ligne vide si le signal de fin de fichier arrive à ce moment-là. Et cette ligne vide est fantôme dans le sens où elle ne proviendrait pas du fichier original.

    Si tu fais, par exemple, un programme qui compte le nombre de lignes, ce compte serait faussé.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    OK, merci de tes explications. Je comprends mieux maintenant pourquoi le code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while(!feof(file))
    {
      fgets(blabla);
    }
    est foireux.

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 476
    Par défaut
    Citation Envoyé par salseropom Voir le message
    OK, merci de tes explications. Je comprends mieux maintenant pourquoi le code [...] est foireux.
    Pour être tout-à-fait complet, je m'aperçois que si ce que je dis est vrai, il n'y a pas moyen pour autant de recevoir un code EOF avec fgets(). Donc, un petit tour dans la man-page s'impose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
           char *fgets(char *s, int size, FILE *stream);
    
    RETURN VALUE
           ...
    
           gets() and fgets() return s on success, and NULL on
           error or when end of file occurs while no characters
           have been read.
    On peut donc écrire de façon sûre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char buffer [LENGTH];
    FILE * f = stdin;
    
    while (fgets(buffer,LENGTH,f)==buffer)
    {
        traitement ...
    }
    
    if (ferrof(f)) { erreur ... }

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    On peut donc écrire de façon sûre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char buffer [LENGTH];
    FILE * f = stdin;
    
    while (fgets(buffer,LENGTH,f)==buffer)
    {
        traitement ...
    }
    
    if (ferrof(f)) { erreur ... }
    Généralement, on utilise plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(fgets(buffer,sizeof buffer,f) != NULL)

  8. #8
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    On peut donc écrire de façon sûre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char buffer [LENGTH];
    FILE * f = stdin;
    
    while (fgets(buffer,LENGTH,f)==buffer)
    {
        traitement ...
    }
    
    if (ferrof(f)) { erreur ... }
    Oui, enfin, la forme canonique est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    char buffer [LENGTH];
    FILE * f = stdin; /* ou fopen(..., "r"); */
     
    while (fgets (buffer, sizeof buffer, f) != NULL)
    {
        /* traitement ...*/
    }
    Ne pas trop chercher à s'en éloigner...

  9. #9
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Oui, enfin, la forme canonique est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    char buffer [LENGTH];
    FILE * f = stdin; /* ou fopen(..., "r"); */
     
    while (fgets (buffer, sizeof buffer, f) != NULL)
    {
        /* traitement ...*/
    }
    Ne pas trop chercher à s'en éloigner...
    plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    char buffer [LENGTH];
    FILE * f = stdin; /* ou fopen(..., "r"); */
     
    while (fgets (buffer, LENGTH, f) != NULL)
    {
        /* traitement ...*/
    }

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 476
    Par défaut
    Citation Envoyé par Emmanuel Delahaye Voir le message
    Oui, enfin, la forme canonique est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while (fgets (buffer, sizeof buffer, f) != NULL)
    {
        /* traitement ...*/
    }
    Ne pas trop chercher à s'en éloigner...
    J'évite volontairement « != NULL » dans ce cas précis car la man page précise que la fonction renvoie le premier argument en cas de succès ou NULL en cas d'échec, à l'exclusion, donc, de toute autre valeur. Si, pour une raison quelquonque, une autre valeur est retournée (par exemple, si la bibliothèque est mise à jour), ce code de retour sera considéré comme un succès implicite au lieu d'être vu comme une anomalie et provoquer l'interruption du programme.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. lecture fichier avec feof
    Par broumbroum dans le forum Langage
    Réponses: 3
    Dernier message: 28/11/2006, 16h15
  2. Réponses: 6
    Dernier message: 02/09/2003, 15h12
  3. Lecture et ecriture fichier .ini
    Par despe dans le forum C
    Réponses: 6
    Dernier message: 23/07/2003, 20h40
  4. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 4
    Dernier message: 05/02/2003, 08h54
  5. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 2
    Dernier message: 11/06/2002, 10h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo