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 séquencielle fichier texte


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut lecture séquencielle fichier texte
    Salut,

    J' écris deux fonctions pour lire de manière séquentielle
    un fichier. Une tourne, l' autre non. Le problème est de lire la dernière ligne du fichier si elle est vide, après un retour de chariot.

    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
     
    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
     
    int fget_buf( char * s , size_t nb, FILE * fd )
    { char * c, c1 ;
      int err =  0 ;
      if(  s == NULL  || nb <= 0 ||  fd == 0 ) return err = 2 ;
      if( fgets(s, nb , fd ) != NULL )
      {
        if( ( c = strchr( s , '\n' )) != NULL )
        { *c = '\0' ;
          err = 0 ;
          return err ;
        } else
        {
          while( (c1 = fgetc(fd) ) != '\n' && c1 != EOF);
          err = 1 ;
          return err ;
        }
       }
       else
       if( strlen(s) ) s[0] = '\0' ;
       return err ;
    }
     
    int fget_line( char * s , const size_t nb, FILE * fd  )
    { int err = 0;
      int c ;
      size_t w = 0 ;
      if( !s  || nb <= 0 ||  ! fd )
      { err = 2 ;
        return err ;
      }
      while ((c = fgetc (fd)) != '\n' && c != EOF)
      { if( w < nb - 1 )
        s[w++] = c;
        else
        { while((c = fgetc(fd)) != '\n' && c != EOF);
          err = 1;
          return err ;
        }
      }
     s[w] = '\0';
     return err;
    }
     
     
    int main ()
    { char z[128] ;
      int r = 1 ;
      FILE * fd = 0 ;
      fd = fopen("toto.txt", "r")  ;
      assert( fd != 0 ) ;
     
      while( ! feof(fd) )
      { memset( z, 0 , sizeof(z) ) ;
        r = fget_buf( z, sizeof(z), fd ) ;  // pas bon 
        //r = fget_line( z, sizeof(z), fd ) ;  // ok
     
        if( r == 0 )
        printf("%02d) =>%s\n", strlen(z), z ) ;
        else
        if( r == 2 )
        { printf("erreur globale\n") ;
          fclose(fd) ;
          return  ;
        }
        else
        if( r == 1 )
        { printf("saisie trop longue\n") ;
          fclose(fd) ;
          return ;
        }
      }
      fclose(fd) ;
      return 0 ;
    }
    C'est fget_buf qui pose problème. Si vous avez une idée ?

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    Lorsque tu ne trouves pas \n dans la chaine de caractères, il y a deux possibilités :
    1. il reste des caractères sur la ligne que tu n'as pas encore lu
    2. tu as atteint la fin du fichier.
    Tu ne traites que le cas 1.

  3. #3
    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 dj.motte
    C'est fget_buf qui pose problème. Si vous avez une idée ?
    Déjà, y'a ça...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Project   : Forums
    Compiler  : GNU GCC Compiler (called directly)
    Directory : C:\dev\forums2\
    --------------------------------------------------------------------------------
    Switching to target: default
    Compiling: main.c
    main.c:51: warning: function declaration isn't a prototype
    main.c: In function `main':
    main.c:68: warning: `return' with no value, in function returning non-void
    main.c:74: warning: `return' with no value, in function returning non-void
    main.c:79: warning: this function may return with or without a value
    Linking console executable: console.exe
    Process terminated with status 0 (0 minutes, 6 seconds)
    0 errors, 4 warnings
    http://emmanuel-delahaye.developpez....tm#cfg_compilo
    • attention, assert() pourrait ne pas être compilé en mode release. L'usage que tu en fais est OK pour du quick'n dirty, mais jamais en production.
    • Dans un contexte pointeur, on utilise plutôt NULL que 0. C'est plus clair.
    • feof() ne fait pas ce que tu crois. Il faut tester la valeur retournée par la fonction de lecture. Un des codes retour devrait donc signaler la fin de lecture.
    • Il est inutile de remplir la chaine de 0. C'est à la fonction de positionner correctement le 0 final.
    • Le code retour étant un entier, apprendre à utiliser switch-case pour l'évaluer...
    • Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      if (strlen (s))
            s[0] = '\0';
      est totalement inutile.
    • nb étant un size_t, il ne peut être < 0...
    • et des dizaines de détails . Voir la correction.

    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
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    /* erreurs
     
       0 = normal
       1 = ligne trop longue
       2 = erreur generale
       EOF = fin de lecture
    */
     
    #if 1                           /* 0|1 */
    int fget_line (char *s, const size_t nb, FILE * fd)
    {
       /* OK */
       int err = 0;
       if (s == NULL || nb == 0 || fd == NULL)
       {
          err = 2;
       }
       else
       {
          if (fgets (s, nb, fd) != NULL)
          {
             char *c = strchr (s, '\n');
             if (c != NULL)
             {
                *c = '\0';
             }
             else
             {
                int c;
                while ((c = fgetc (fd)) != '\n' && c != EOF)
                {
                }
                err = 1;
             }
          }
          else
          {
             err = EOF;
          }
       }
       return err;
    }
     
    #else
    int fget_line (char *s, const size_t nb, FILE * fd)
    {
       /* OK */
       int err = 0;
       size_t w = 0;
       if (s == NULL || nb == 0 || fd == NULL)
       {
          err = 2;
       }
       else
       {
          int c;
          while ((c = fgetc (fd)) != '\n' && c != EOF)
          {
             if (w < nb - 1)
                s[w++] = c;
             else
             {
                err = 1;
             }
          }
          s[w] = '\0';
          if (c == EOF)
          {
             err = EOF;
          }
       }
       return err;
    }
    #endif
     
    int main (void)
    {
       int ret = EXIT_SUCCESS;
    #define FNAME "test.txt"
     
       FILE *fd = fopen (FNAME, "r");
       if (fd != NULL)
       {
          int r = 0;
     
          while (ret == EXIT_SUCCESS && r != EOF)
          {
             char z[9];
             r = fget_line (z, sizeof (z), fd); // pas bon
     
             switch (r)
             {
             case 0:
                printf ("%02d) =>'%s'\n", strlen (z), z);
                break;
             case 2:
                printf ("erreur globale\n");
                fclose (fd);
                ret = EXIT_FAILURE;
                break;
             case 1:
                printf ("ligne trop longue\n");
                fclose (fd);
                ret = EXIT_FAILURE;
             case EOF:
                if (feof (fd))
                {
                   puts ("<EOF>");
                }
                if (ferror (fd))
                {
                   perror (FNAME);
                }
                break;
             default:
                printf ("Erreur %d inconnue\n", r);
             }
          }
          fclose (fd), fd = NULL;
       }
       else
       {
          perror (FNAME);
          ret = EXIT_FAILURE;
       }
       return ret;
    }

  4. #4
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut
    Salut,

    Merçi Emmanuel. Mon algo de lecture dans main était un peu obscur. Néanmoins j'ai testé votre implémentation, et il apparait qu'elle ne permet pas de lire en entier un fichier texte lorsqu'il n'est pas terminé par un saut de ligne. (ce qui peut arriver)

    Dans ce cas précis la fonction avec fgets renvoit un segmentation fault, l'autre avec fgetc tronque la dernière ligne. Je vais me pencher sur ce problème.

  5. #5
    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 dj.motte
    il apparait qu'elle ne permet pas de lire en entier un fichier texte lorsqu'il n'est pas terminé par un saut de ligne. (ce qui peut arriver)
    Oups, j'ai pas vérifié ça. C'est donc tout à fait possible.
    Pas le temps ce soir... musique...

  6. #6
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut
    Salut,

    En fait le buffer n'est pas vidé dans un cas de fin de fichier.

    J'ai apporté ce correctif, testé, mais qui sait ...

    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
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    /* erreurs
     
       0 = normal
       1 = ligne trop longue
       2 = erreur generale
       EOF = fin de lecture
    */
     
    #if 1                           /* 0|1 */
    int fget_line (char *s, const size_t nb, FILE * fd)
    {
       /* OK */
       int err = 0;
       if (s == NULL || nb == 0 || fd == NULL)
       {
          err = 2;
       }
       else
       {
          if (fgets (s, nb, fd) != NULL)
          {
             char *c = strchr (s, '\n');
             if (c != NULL)
             {
                *c = '\0';
             }
             else
             if( c == NULL && ! feof(fd) )  // ajouté
             {
                int c;
                while ((c = fgetc (fd)) != '\n' && c != EOF)
                {
                }
                err = 1;
             }
          }
          else
          {
             err = EOF;
          }
       }
       return err;
    }
     
    #else
    int fget_line (char *s, const size_t nb, FILE * fd)
    {
       /* OK */
       int err = 0;
       size_t w = 0;
       if (s == NULL || nb == 0 || fd == NULL)
       {
          err = 2;
       }
       else
       {
          int c;
          while ((c = fgetc (fd)) != '\n' && c != EOF)
          {
             if (w < nb - 1)
                s[w++] = c;
             else
             {
                err = 1;
             }
          }
          s[w] = '\0';
          if (c == EOF && strlen(s) == 0 )  // ajouté
          {
             err = EOF;
          }
       }
       return err;
    }
    #endif
     
    int main (void)
    {
       int ret = EXIT_SUCCESS;
    #define FNAME "test.txt"
     
       FILE *fd = fopen (FNAME, "r");
       if (fd != NULL)
       {
          int r = 0;
     
          while (ret == EXIT_SUCCESS && r != EOF)
          {
             char z[9];
             r = fget_line (z, sizeof (z), fd); // pas bon
     
             switch (r)
             {
             case 0:
                printf ("%02d) =>'%s'\n", strlen (z), z);
                break;
             case 2:
                printf ("erreur globale\n");
                // fclose (fd);  supprimé inutile
                ret = EXIT_FAILURE;
                break;
             case 1:
                printf ("ligne trop longue\n");
                // fclose (fd);  supprimé inutile
                ret = EXIT_FAILURE;
             case EOF:
                if (feof (fd))
                {
                   puts ("<EOF>");
                }
                if (ferror (fd))
                {
                   perror (FNAME);
                }
                break;
             default:
                printf ("Erreur %d inconnue\n", r);
             }
          }
          fclose (fd), fd = NULL;
       }
       else
       {
          perror (FNAME);
          ret = EXIT_FAILURE;
       }
       return ret;
    }
    Si on ferme deux fois le même fichier, puis affecté à NULL, ça fait un bogue sur mon ordi.

Discussions similaires

  1. Réponses: 2
    Dernier message: 08/11/2006, 20h57
  2. [C#]Lecture gros fichier texte
    Par kekesilo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 20/05/2006, 13h58
  3. Lecture d´un fichier texte .
    Par pilouface dans le forum C
    Réponses: 5
    Dernier message: 20/01/2006, 23h48
  4. [AS2] Lecture Ecriture Fichier Texte
    Par cpr0 dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 13/09/2005, 11h22
  5. lecture de fichier texte
    Par prorider dans le forum C
    Réponses: 36
    Dernier message: 08/09/2004, 20h55

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