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 :

mauvaise lecture d'un fichier


Sujet :

C

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

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut mauvaise lecture d'un fichier
    Bonjour, je désire lire des informations concernant un espèce chimique. Cette espèce est définie par un nom (name), une masse molaire (M), une température critique (T) et 2*7 coefficients. Voici mon fichier donnees.txt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    CH3
    12.5 1000.2
    12.3 45.2 10.2 45.3 63.22 78 45.1
    45.0 56.3 78.98 56.32 478.63 56.32 896.3
    je veux lire ces données et les afficher à l'écran (pour un début en tout cas). Voici mon prgm

    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
     
    #include<stdlib.h>
    #include<stdio.h>
     
    int main()
    {
        int i,j;
        double var,M,T;
        char name[10];
     
        FILE * file=fopen("donnees.txt","r");
     
        for(i=0;i<1;++i)
        {
    	switch(i)
    	{
    	    case 0 : fscanf(file,"%s",name);
    		printf("name = %s\n",name);
    		break;
    	    case 1 : fscanf(file,"%lf%lf",&M,&T);
    		printf("%f\t%f\n",M,T);
    		break;
    	    case 2 : for(j=0;j<7;++j)
    	    {
    		fscanf(file,"%lf",&var);
    		printf("%f\t",var);
    	    }
    		printf("\n");
    		break;
    	    case 3 : for(j=0;j<7;++j)
    	    {
    		fscanf(file,"%lf",&var);
    		printf("%f\t",var);
    	    }
    		printf("\n");
    		break;
    	} // fin du switch
        } // fin du for
     
        fclose(file);
     
        return 0;
    }
    Mais la sortie est bizarre. J'obtiens :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    name = //CH3
    12.500000       1000.200000
    12.300000       45.200000       10.200000       45.300000       63.220000       78.000000       45.100000
    45.000000       56.300000       78.980000       56.320000       478.630000      56.320000       896.300000
    Pourquoi ai-je name=//CH3 ? et non pas name=CH3 ??
    J'ai esayé avec char * name, mais le compilo me renvoie une erreur de segmentation.

    D'où peut provenir cette erreur (ou ce mauvais affichage) ?

    Merci.

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    pardon, il y a une petite erreur, il faut lire

    et non

    Merci.

  3. #3
    Membre habitué Avatar de semaj_james
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    193
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 193
    Points : 139
    Points
    139
    Par défaut
    J'ai teste ton programme et je trouve bien: name = CH3

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: mauvaise lecture d'un fichier
    Citation Envoyé par salseropom
    Pourquoi ai-je name=//CH3 ? et non pas name=CH3 ??
    Avec ton code, on a pas du tout ça...

    Correction, sécurisation : (pose des questions si tu ne comprends pas)
    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
     
    #include <stdlib.h>
    #include <stdio.h>
     
    #define fname "../../data/data.txt"
     
    int main ()
    {
       FILE *file = fopen (fname, "r");
     
    /* -ed- fopen() peut echouer... */
       if (file != NULL)
       {
          int i = 0;
          int err = 0;
     
          /* -ed-
             Un compteur de lignes sans gestion d'erreur est insuffisant.
           */
          while (!err)
          {
             int n;
     
             switch (i)
             {
             case 0:
                /* -ed-
     
                   fscanf (file, "%s", name);
     
                   fscanf() est peu recommande.
                   De plus, il peut echouer.
                   Ajoute gestion d'erreur.
                 */
                {
                   char name[10];
     
                   n = fscanf (file, "%9s", name);
     
                   if (n != 1)
                   {
                      err = 1;
                   }
                   else
                   {
                      printf ("name = %s\n", name);
                   }
                }
                i = 1;
                break;
     
             case 1:
                {
                   double M, T;
                   n = fscanf (file, "%lf%lf", &M, &T);
                   if (n != 2)
                   {
                      err = 1;
                   }
                   else
                   {
                      printf ("%8.2f%8.2f\n", M, T);
                   }
                }
                i = 2;
                break;
     
             case 2:
                while (!err)
                {
                   double var;
                   n = fscanf (file, "%lf", &var);
                   if (n != 1)
                   {
                      err = 1;
                   }
                   else
                   {
                      printf ("%8.2f", var);
                   }
                }
                printf ("\n");
                i = 3;
     
                break;
     
             case 3:
                while (!err)
                {
                   double var;
                   n = fscanf (file, "%lf", &var);
                   if (n != 1)
                   {
                      err = 1;
                   }
                   else
                   {
                      printf ("%8.2f", var);
                   }
                }
                printf ("\n");
                break;
             }                      // fin du switch
     
          }                         // fin du for
     
          if (err)
          {
             if (ferror (file))
             {
                perror (fname);
             }
             else if (feof (file))
             {
                printf ("OK\n");
             }
             else
             {
                printf ("format error\n");
             }
          }
          fclose (file);
     
       }
       else
       {
          perror (fname);
       }
       return 0;
    }
    qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    name = CH3
       12.50 1000.20
       12.30   45.20   10.20   45.30   63.22   78.00   45.10   45.00   56.30   78.98
       56.32  478.63   56.32  896.30
    OK
    Pas de Wi-Fi à la maison : CPL

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

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Merci de vos réponses. Après avoir rebooté ma machine, j'ai effectivment name=CH3 et non plus name=//CH3.
    Mercis Emmanuel de ton long code. Il m'est très instructif (je débute dans le C). Et effectivement j'ai qq questions
    1) tu as dit que fscanf est peu recommandé. Qu'utiliser alors ?
    2) quand est-ce que la variable err change de valeur ? (donc quand sort-on du while(!err) ?

    Avant de te poser d'autres questions, je me documente sur les fonctions ferror et perror.
    Merci.

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par salseropom
    Merci de vos réponses. Après avoir rebooté ma machine, j'ai effectivment name=CH3 et non plus name=//CH3.
    Mercis Emmanuel de ton long code. Il m'est très instructif (je débute dans le C). Et effectivement j'ai qq questions
    1) tu as dit que fscanf est peu recommandé. Qu'utiliser alors ?
    Lire les lignes avec fgets()
    Les analyser avec sscanf() ou strtol(), strtoul() ou strtod().

    http://emmanuel-delahaye.developpez....tes.htm#saisie
    http://emmanuel-delahaye.developpez....s.htm#fichiers
    2) quand est-ce que la variable err change de valeur ? (donc quand sort-on du while(!err) ?
    la variable err est mise à jour par l'analyse de la valeur retournée par fscanf(). err vaut 1 dès que la valeur attendue n'est pas conforme. (voir la doc de fscanf())
    Ensuite, on analyse l'état courant du flux pour déterminer la cause de l'erreur... J'aurais plus l'appeler 'end' (fin) plutôt que err, car une fin de fichier est une fin 'normale'...
    Avant de te poser d'autres questions, je me documente sur les fonctions ferror et perror.
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Re salut Emmanuel,
    je suis en train de lire toute la doc que tu m'as transmise (et sur google). Mais une question me vient après cette lecture : fscanf n'est pas adaptée (tout comme scanf) car le "f" veut dire que la saise doit être formatée (et que toute erreur est humaine). Mais dans mon pb bien particulier, je connais d'avance le format du fichier que je lis :

    une chaine de caractère
    deux doubles
    7 doubles
    7 doubles

    donc pourquoi ne pas utiliser fscanf (avec bien sur le test après le fopen) ?

    Sinon je me rends bien compte que le fgets est fort puissant et je m'en servirai pour la suite de mon prgm : pour l'instant je veux etre capable de lire mes 4 lignes mais ensuite il faudra que je lise 4 lignes bien particulières de mon fichier.

    Merci encore de ta patience, et je continue ma lecture (et mes essais) avec le fgets et le sscanf.

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par salseropom
    je suis en train de lire toute la doc que tu m'as transmise (et sur google). Mais une question me vient après cette lecture : fscanf n'est pas adaptée (tout comme scanf) car le "f" veut dire que la saise doit être formatée (et que toute erreur est humaine).
    Ban oui, cette remarque est dans l'article sur le saisies, pas sur celui sur les fichiers. J'ai mis les deux articles, parce que ce sont les mêmes fonctions qui sont utilisées. Mais il est vrait que fscanf() peut être utilisé dans ton cas, encore que pour lire une chaine, il y a des risques de débordement si n'y prend pas garde. D'où ma modif.

    D'autre part, un fichier de données peut être altéré... Il faut donc rester vigilant.
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    ok
    bon alors je continue de faire ma fonction et ensuite je la poste afin que tu (ou quelqu'un d'autre) me dise ton (leur) opinion dessus (je suis en ce moment en train de me prendre la tête avec le fgets() et les char * tab et char tab[20]

    Merci de tes explications.

Discussions similaires

  1. Lecture d'un fichier .dbf
    Par San Soussy dans le forum Autres SGBD
    Réponses: 8
    Dernier message: 07/07/2004, 16h30
  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