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 :

Problème avec la fonction feof


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développement Informatique : Première année
    Inscrit en
    Janvier 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30

    Informations professionnelles :
    Activité : Développement Informatique : Première année

    Informations forums :
    Inscription : Janvier 2013
    Messages : 6
    Points : 5
    Points
    5
    Par défaut Problème avec la fonction feof
    Salut tout le monde .

    J'ai besoin de votre aide à propos du fonctionnement de feof(), cette fonction qui renvoie la valeur 0 si elle arrive à la fin du fichier passer en paramètre.

    Bon, j'ai essayer de travailler avec cette dernière dans un programme qui permet de lire et enregistrés des informations sur des employés dans un fichier texte ' Employe.txt ', et afficher les infos enregistré dans le fichier. Pour la lecture du fichier j'ai utilisé la fonction feof(nom_pointeur_fich) comme condition de fin de lecture, même si j'avais la possibilité d'utilisé simplement for() puisque je connais déjà le nombre d'enregistrement...

    Mais j'ai eu un problème avec la fonctions feof() car la boucle qui permet de lire du fichier et afficher son contenu tant que End of file = faux
    while(feof(F)!=0);
    n'affiche que la première ligne (le premier enregistrement) :/ .

    Voila le code que j'ai utilisé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct employe // Debut structure des employé
    {
           char Nom[51];
           int Matricule;
           char adresse[51];
    }employe;              // Fin structure des emplyé
     
    void viderBuffer()
    {
        int c = 0;
     	   while (c != '\n' && c != EOF)
     	   {
         	   c = getchar();
        }
    }
     
    int main(int argc, char *argv[])
    {
        employe *e; // un pointeur du type employ - role d'un tableau des employé -
        FILE *F=NULL;
        int i=0,j,rep;
        char ch;
     
    F=fopen("Employe.txt","w");
     
    do // Debut du remplissage des infos et écriture sur le fichier .
    {   
        e=malloc(1*sizeof(employe));
     
        printf("\nEntrer le Nom de l'employe Numero %d > ",i+1);
        fgets(e->Nom,50,stdin);
        *(e->Nom+(strlen(e->Nom)-1))='\0';
        fprintf(F," %s |",e->Nom);
     
        printf("Entrer Le Matricule > ");
        scanf("%d",&e->Matricule);
        viderBuffer();
        fprintf(F," %d |",e->Matricule);
     
     
        printf("Entrer L'adresse > ");
        gets(e->adresse);
        fprintf(F," %s\n",e->adresse);
     
        free(e);
        i++;
     
        printf("\n\tAjouter un nouveau employee ?? Oui = 1 | Non = 0 \n > ");
        scanf("%d",&rep);
        viderBuffer();
    }
    while(rep!=0); // Fin du remplissage des infos et écriture sur le ficheier .
    fclose(F);
     
    F=fopen("Employe.txt","r");
        j=0;
        do
        {
                        printf(" %d : ",j+1);
                        do
                        {
                               ch=fgetc(F);
                               putchar(ch);
                        }
                        while(ch!='\n');
     
                        printf("\n");
                        j++;
        }
        while(feof(F)!=0);
     
    fclose(F);
     
     
      system("PAUSE");	
      return 0;
    }
    j’espère que vous pouvez m'aider a trouvé le problème qui empêche ce code de fonctionner , Merci d'avance .


    Si vous avez des suggestions ou bien des remarques sur ce code n'hésitez pas a me le dire, toute aide sera la bienvenue !!

  2. #2
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Bonjour

    En traduisant

    Citation Envoyé par Fog-Thunder
    tant que End of file = faux
    par

    tu fais exactement l'inverse de ce que tu souhaites ! Ce que tu constates (arrêt juste après une première lecture (boucle do ... while)) est donc parfaitement prévisible.

    Et attention : pour que feof renvoie "vrai" (non 0), il faut qu'une erreur de lecture après la fin de fichier se soit déjà produite. C'est donc à manipuler avec des pincettes et à bon escient.

    Tu as un article dans la FAQ traitant du bon usage de feof.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Développement Informatique : Première année
    Inscrit en
    Janvier 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30

    Informations professionnelles :
    Activité : Développement Informatique : Première année

    Informations forums :
    Inscription : Janvier 2013
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Salut tout le monde .

    plxpy ta tout a fait raison, la condition que je dois mètre c'est et non pas puisque la fonction renvoie une valeur !=0 si elle est vrais, ce qui explique le problème que j'avais...

    Bref si j'ai bien compris la fonction feof() a besoin d'une erreur de lecture avant le test pour détermine si l'erreur est le End Of File, c'est ce que j'ai fait avec ce code là est sa marche très bien . Merci pour ton aide plxpy .

    Si ta des suggestions ou bien des remarques concernant le code n'hésite pas a me le dire .

    Voila le Code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct employe // Debut structure des employé
    {
           char Nom[51];
           int Matricule;
           char adresse[51];
    }employe;              // Fin structure des emplyé
     
    void viderBuffer()
    {
        int c = 0;
     	   while (c != '\n' && c != EOF)
     	   {
         	   c = getchar();
        }
    }
     
    int main(int argc, char *argv[])
    {
        employe *e; // un pointeur du type employe
        FILE *F=NULL;
        int rep,c,i=0;
     
    F=fopen("Employe.txt","w");
     
     
    do // Debut du remplissage des infos.
    {   
        e=malloc(1*sizeof(employe));
     
        printf("\nEntrer le Nom de l'employe Numero %d > ",i+1);
        fgets(e->Nom,50,stdin);
        *(e->Nom+(strlen(e->Nom)-1))='\0';
     
        printf("Entrer Le Matricule > ");
        scanf("%d",&e->Matricule);
        viderBuffer();
     
        printf("Entrer L'adresse > ");
        fgets(e->adresse,50,stdin);
     
        printf("\n\tAjouter un nouveau employee ?? Oui = 1 | Non = 0 \n > ");
        scanf("%d",&rep);
        viderBuffer();
     
        if(rep==0)
        *(e->adresse+(strlen(e->adresse)-1))='\0';
     
        fprintf(F,"%s |",e->Nom); //enregistrement des infos saisi par l'utilisateur sur le fichier .
        fprintf(F," %d |",e->Matricule);
        fprintf(F," %s",e->adresse);
     
        free(e);
        i++;
    }
    while(rep!=0); // Fin du remplissage des infos et écriture sur le ficheier .
     
     
    fclose(F);
     
     
    F=fopen("Employe.txt","r");
     
    printf("\n\t\tInformations des employés enregistrés dans le répértoire : \n\n");
    i=0;
     
        do
        {               
                        printf(" %d : ",i+1);
                        c=0;
     
                        while(c!='\n' && c!=EOF)
                        {
                               c=fgetc(F);
                               putchar(c);
                        }
                        i++;
                        printf("\n");
        }
        while(feof(F)==0);
        printf("\n\n");
     
    fclose(F);
     
     
      system("PAUSE");	
      return 0;
    }
    Si vous avez des suggestions ou bien des remarques sur ce code n'hésitez pas a me le dire, toute aide sera la bienvenue !! Merci D'avance .

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Bref si j'ai bien compris la fonction feof() a besoin d'une erreur de lecture avant le test pour détermine si l'erreur est le End Of File, c'est ce que j'ai fait avec ce code là est sa marche très bien .
    Ce n'est pas la vraie fonction de feof().

    feof() doit être appelée seulement si une lecture échoue, pour dire si cet échec est dû à la fin du fichier (dans le cas contraire, il est dû à une erreur).

    En gros, ta lecture devrait plutôt être ainsi:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    void Lecture()
    {
    	int i = 0;
    	int c = 0;
    	FILE *F=fopen("Employe.txt","r");
    	if(NULL == F)
    	{
    		printf("ERREUR d'ouverture du fichier.\n");
    		return;
    	}
     
    	printf("\n\t\tInformations des employés enregistrés dans le répértoire : \n\n");
    	i=0;
     
    	do
    	{
    		printf(" %d : ",i+1);
     
    		c = 0; /*remise à zéro sinon on ne réentrera pas dans la boucle*/
    		while(c!='\n' && c!=EOF)
    		{
    			c=fgetc(F);
    			putchar(c);
    		}
    		i++;
    		printf("\n");
    	}
    	while(c != EOF);
     
    	/*fgetc() a échoué: Si c'est la fin OK, sinon erreur*/
    	if( ! feof(F) )
    		printf("ERREUR!\n"); /*Ce n'est pas la fin...*/
    	printf("\n\n");
     
    	fclose(F);
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Citation Envoyé par Médinoc
    feof() doit être appelée seulement si une lecture échoue, pour dire si cet échec est dû à la fin du fichier (dans le cas contraire, il est dû à une erreur).
    Certes mais, là, c'est quand même le pire exemple qu'on puisse trouver (ici, on sort si et seulement si le caractère lu vaut EOF) pour démontrer qu'il faut d'abord tomber sur une erreur "au sens très large" pour ensuite tester si c'est bien une fin de fichier ...

    "Je suis tombé sur une fin de fichier (EOF) J'ai lu un caractère EOF donc je suis tombé sur une erreur au sens large (mais quelle est-elle ???) je teste ... et oui (feof) c'est bien une fin de fichier !"

    Il y a quand même plein de fois où la seule erreur possible et imaginable quand on lit un fichier (sans décodage aucun) est de tomber sur une fin de fichier. Un raccourci est peut-être possible dans certains cas.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Il y a quand même plein de fois où la seule erreur possible et imaginable quand on lit un fichier (sans décodage aucun) est de tomber sur une fin de fichier. Un raccourci est peut-être possible dans certains cas.
    Je suis d'accord, mais pour moi le raccourci est "ne pas appeler feof() du tout" plutôt que "toujours appeler feof()".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    Citation Envoyé par Medinoc
    Je suis d'accord, mais pour moi le raccourci est "ne pas appeler feof() du tout" plutôt que "toujours appeler feof()".
    Si tu veux dire que, ici, une simple comparaison du caractère lu avec EOF est amplement suffisante, je suis complètement d'accord avec toi.

    Du coup, sous Linux, je me suis creusé les méninges pour trouver un cas où un EOF renvoyé par getchar() correspond à une vraie erreur et pas à une banale fin de fichier (dans un contexte d'utilisation de fichiers disque assez classiques).

    Le seul cas pas trop tordu que j'ai trouvé est un démontage à la hussarde d'un périphérique externe : juste après le montage d'une clé USB, lancement de l'exécutable et retrait manuel de la clé pendant la lecture et plus précisément, dans mon code, entre l'ouverture du fichier à lire et la première lecture, au moment d'un appel à sleep (un démontage propre avec les outils Ubuntu m'envoye paître en me signalant que le périphérique est utilisé et que le démontage ne peut être fait).


    Le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <assert.h>
    #include <errno.h>
     
    #define SOMMEIL     3   // nb secondes pour le sleep()
     
    int main(int argc,char *argv[])
    {
        FILE *fp;
        FILE *output;
        int   character;
        int   count = 0;
     
        assert(fp = fopen(argv[1],"r"));
        clearerr(fp);   // ceinture ET bretelles (pour etre sur a 100%)
     
        // afin de pouvoir comparer entree et sortie quand
        // je ne retire pas la cle et valider le code
        assert(output = fopen("SORTIE","w"));
     
        printf("mise en sommeil pour %d secondes\n",SOMMEIL);
        sleep(SOMMEIL);
     
        while ((character = fgetc(fp)) != EOF)
        {
            count++;
            fputc(character,output);
        }
        fclose(output);
     
        printf("%d caractere(s) lu(s)\n",count);
        printf("feof(fp)   : %d\n",feof(fp));
        printf("ferror(fp) : %d\n",ferror(fp));
        perror("perror");
     
    }

    En retirant donc la clé pendant l'appel à sleep :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    plx@sony:~/Bureau/DVP/feof$ ./feof /media/PLX4GB/detect.c 
    mise en sommeil pour 3 secondes
    0 caractere(s) lu(s)
    feof(fp)   : 0
    ferror(fp) : 1
    perror: Input/output error

    Pour valider le code, après remontage, si je ne touche à rien, tout est OK et le fichier créé ne diffère pas du fichier en entrée :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    plx@sony:~/Bureau/DVP/feof$ ./feof /media/PLX4GB/detect.c 
    mise en sommeil pour 3 secondes
    601 caractere(s) lu(s)
    feof(fp)   : 1
    ferror(fp) : 0
    perror: Success
    plx@sony:~/Bureau/DVP/feof$ # comparaison avec SORTIE
    plx@sony:~/Bureau/DVP/feof$ cmp /media/PLX4GB/detect.c SORTIE
    plx@sony:~/Bureau/DVP/feof$

    Il y a peut-être d'autres cas plus simples auxquels je n'ai pas pensé ou des contextes d'utilisation que je ne connais pas bien mais j'ai l'impression que les situations où la gestion fine des fins de fichier (via feof, ...) est luxueuse sont assez courantes.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

Discussions similaires

  1. Problème avec la fonction feof ?
    Par kevine2710 dans le forum Débuter
    Réponses: 4
    Dernier message: 28/02/2013, 22h54
  2. Problème avec la fonction findfirst ()
    Par Angelico dans le forum Windows
    Réponses: 3
    Dernier message: 05/08/2004, 20h40
  3. [Requete SQL en VBA] Problème avec la fonction FLOOR
    Par zubral dans le forum Langage SQL
    Réponses: 4
    Dernier message: 13/07/2004, 13h24
  4. Problème avec les fonctions
    Par jvachez dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 13/01/2004, 12h06
  5. [Postgresql]Problème avec les fonctions ...
    Par fet dans le forum Requêtes
    Réponses: 4
    Dernier message: 02/10/2003, 09h04

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