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 :

parser un fichier csv pour le traiter en C


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 38
    Par défaut parser un fichier csv pour le traiter en C
    Bonjour à tous,

    j'ai un petit soucis avec mon programme en C qui pourtant semble simple mais me pose vraiment problème (je suis debutant):
    je lance:
    gcc -o truc.exe truc.c
    truc.exe "/essai.csv"

    essai.csv contient un tableau de 27 lignes et 17 colonnes que je souhaite charger en mémoire pour faire un traitement ensuite. Certaines cases contiennent des NA, je pense que ça me provoque des erreurs (étant donné que c'est soit un entier soit NA, qui sera surement considéré comme un char ou bien il va me traduire ce qui est en mémoire comme un chiffre, ce qui n'est pas du tout ce que je souhaite!)

    Chose importante: ma structure contient 20 champs, mon fichier csv 17: c'est parce que je souhaite remplir ces champs dans la suite de mon programme...

    PS: je verrai plus tard pour l'organisation en .h etc.


    Voici truc.c :

    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
     
    //truc.c
     
    #include<stdio.h>
    #include <stdlib.h>
     
    typedef struct {
      int n1;
      long int n2; //  peut aller jusque 200000
      int n3;
      int n4;
      int n5;
      int n6;
      int n7;
      int n8;
      int n9;
      int n10;
      int n11;
      int n12;
      int n13;
      int n14; //peut etre NA dans le csv :s ce serait pour ça que ça ne fonctionne pas? (entre autres)
      int n15; //peut etre NA dans le csv
      int n16; //peut etre NA dans le csv
      int n17;
      int n18; //booleen
      int n19; 
      int n20; 
    } maStructure;
     
     
    //prototype
    maStructure * parser(char filename);
     
     
     
    /** 
    * read the csv file and load it in a C table
    * IN: filename
    * OUT: data which contains all the lines of the csv file in "maStructure" format
    **/
    maStructure * parser(char filename){
     
      FILE* file = NULL; //fichier vide
      char buffer[BUFSIZ]; //tableau tampon de taille n  =>ma principale source d'erreur lorsque je compile: je ne vois pas trop quoi lui donner comme taille: chaque ligne peut avoir une taille différente... Je ne sais pas trop comment fabriquer mon buffer pour la suite en fait... :s
      int i = 0;
      file = fopen(filename, "r+");
     
      if (file==NULL) {
        printf("cannot open file %s\n", filename);
        exit(1);
      }
     
      //attribution de l'espace pour les donnees en memoire
      maStructure data = malloc(sizeof(maStructure)*nfile);
     
      printf("loading %s\n", filename); 
      fgets(buffer, bufsiz, file);		// pour lire la ligne header du csv
     
      //tant qu'il existe des lignes à lire
      while (fgets(buffer, sizeof(buffer), file)){
     
        //on stock chaque element de la ligne dans la colonne de data correspondante ==> problème pour le traitement des NA?
        sscanf(buffer, "%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d", 
    	  &data[i].n1;
    	  &data[i].n2;
          &data[i].n3;
          &data[i].n4;
          &data[i].n5;
          &data[i].n6;
          &data[i].n7;
          &data[i].n8;
          &data[i].n9;
          &data[i].n10;
          &data[i].n11;
          &data[i].n12;
          &data[i].n13;
          &data[i].n14; 
          &data[i].n15;
          &data[i].n16;
          &data[i].n17);
     
    &data[i].n18=NULL;
    &data[i].n19=NULL; 
    &data[i].n20=NULL; 
     
    #if (DEBUG > 1)
        printf("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d,%d,%d, %d, %d, %d, %d, %d",
          data[i].n1;
          data[i].n2;
          data[i].n3;
          data[i].n4;
          data[i].n5;
          data[i].n6;
          data[i].n7;
          data[i].n8;
          data[i].n9;
          data[i].n10;
          data[i].n11;
          data[i].n12;
          data[i].n13;
          data[i].n14; 
          data[i].n15;
          data[i].n16;
          data[i].n17);  
    #endif
        i++;
      }
     
    /**
    //  while ((c = fgetc (file)) != EOF) {
    //    if (c == ';' || c == '\n') {
    //        printf ("%ld\n", strtol (buffer, NULL, 10));
    //        i = 0;
    //        memset (buffer, 0, sizeof buffer);
    //      } else {
    //      buffer[i++] = c;
    //    }
    //  }
    **/
     
      fclose (file);
     
      return(&data);
    } 
     
     
     
     
    int main(int argc, char *argv[]) {
      global int nfile = 27; //mauvaise idée de le mettre en globale?
      maStructure * a = parser(*argv[0]);
     
      return(a);
    }

    Merci par avance!!

    (n'hésitez pas à critiquer ma façon de coder, c'est comme ça que l'on apprend! )

  2. #2
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Déjà : Tu as donné 20 "%d" à ton printf, alors que tu ne lui as mis que 17 arguments... il ne va pas trop trop aimer....

    Ensuite : ajoute un '\n' à la fin du printf pour immédiatement afficher.

    Le "filename" est en char, alors que tu veux donner un nom, donc un char* !
    N'envoie pas "*argv[0]", mais "argv[1]" (argv[0] == le nom de l'exécutable)

    Essaye de compiler avec -W -Wall -Werror -ansi -pedantic pour avoir toutes les erreurs.

    Et euh... j'attends le résultat avec les nouveaux flags de compilation
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    @Metalman : Ca fait plusieurs fois que je veux te le dire mais là, c'est l'occasion :
    Citation Envoyé par http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
    -Wextra
    This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)
    Mieux vaut donc mettre -Wextra (dans ta signature notamment ^^)

    @EaudeRoche : au lieu de faire 36 champs de type int, fais donc un tableau de 36 int dans ta structure ! :o Utilise alors des boucles et non des listes à rallonge incroyablement sujette aux erreurs et impropre à la maintenabilité !

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    maStructure * parser(char filename){
     ....
       //attribution de l'espace pour les donnees en memoire
      maStructure data = malloc(sizeof(maStructure)*nfile);
     ....
      return(&data);
    }
    - nfile inconnu

    - Le malloc est faux (d'ailleurs le compilateur doit renacler): un malloc typique pour n objets de type T est de la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    T * x = malloc(n* sizeof(T))
    //ou
    T * x = malloc(n* sizeof *x)
    - Le return est faux : on ne doit jamais retourner l'adresse d'une variable locale de quelque façon que ce soit. En fin de fonction, la variable locale est détruite et son adresse n'a plus de sens.

    L'allure de la fonction doit être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    maStructure * parser(char filename){
     ....
       //attribution de l'espace pour les donnees en memoire
      maStructure * data = malloc(sizeof(maStructure)*nfile);
     ....
      return(data);
    }
    Je n'ai pas regardé le détail de la fonction vu qu'elle ne peut pas marcher avec ces erreurs

  5. #5
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2010
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2010
    Messages : 38
    Par défaut
    Modification faite!

    Voici mes erreurs "normales" (après avoir retiré 2-3 erreurs de syntaxe ou autres erreurs bêtes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    In file included from truc.c:10:
    truc.h: In function ‘main’:
    truc.h:44: warning: passing argument 1 of ‘parser’ makes integer from pointer without a cast  //je ne comprends pas vraiment ce warning: en quoi je cast quelque chose ici?
    truc.h: In function ‘parser’:
    truc.h:61: warning: passing argument 1 of ‘fopen’ makes pointer from integer without a cast     //je ne comprends pas vraiment ce warning: en quoi je cast quelque chose ici?
    truc.h:70: error: ‘bufsiz’ undeclared (first use in this function) //===>je ne vois pas comment corriger ça...
    truc.h:70: error: (Each undeclared identifier is reported only once
    truc.h:70: error: for each function it appears in.)      // se rapporte à la ligne fgets(buffer, bufsiz, file); mais je ne vois pas comment je peux corriger ça... j'ai créé un buffer, sa taille je ne peux pas la connaitre et je veux y stocker chaque ligne de mon fichier, c'est tout
    truc.h:94: error: invalid lvalue in assignment    //===> correspond à mes &data[i].qqch=NULL :(
    truc.h:96: error: invalid lvalue in assignment
    truc.h:97: error: invalid lvalue in assignment
    truc.h:135: warning: return from incompatible pointer type
    truc.h:135: warning: function returns address of local variable
    Celles avec ta commande:
    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
    In file included from dontot.c:10:
    truc.h:33: error: syntax error before ‘/’ token   //correspond à des commentaires précédés par "//"... je ne comprends pas...
    cc1: warnings being treated as errors
    truc.h:33: warning: no semicolon at end of struct or union
    truc.h:34: error: missing terminating ' character
    truc.h:35: error: missing terminating ' character
    truc.h:36: warning: type defaults to ‘int’ in declaration of ‘cell’
    truc.h:36: warning: data definition has no type or storage class
    truc.h:38: error: syntax error before ‘*’ token
    truc.h:38: warning: type defaults to ‘int’ in declaration of ‘parser’
    truc.h:38: warning: data definition has no type or storage class
    truc.h: In function ‘main’:
    truc.h:42: error: syntax error before ‘/’ token
    truc.h:41: warning: unused variable ‘nfile’
    truc.h: At top level:
    truc.h:40: warning: unused parameter ‘argc’
    truc.h:40: warning: unused parameter ‘argv’
    truc.h:56: error: syntax error before ‘*’ token
    truc.h:56: warning: return type defaults to ‘int’
    truc.h: In function ‘parser’:
    dontot.h:58: error: syntax error before ‘/’ token
    truc.h:61: warning: passing argument 1 of ‘fopen’ makes pointer from integer without a cast
    truc.h:62: error: ‘data’ undeclared (first use in this function)
    truc.h:62: error: (Each undeclared identifier is reported only once
    truc.h:62: error: for each function it appears in.)
    truc.h:65: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
    truc.h:69: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
    truc.h:70: error: ‘buffer’ undeclared (first use in this function)
    truc.h:70: error: ‘bufsiz’ undeclared (first use in this function)
    truc.h:70: error: syntax error before ‘/’ token
    truc.h:73: error: missing terminating ' character
    truc.h:94: error: ‘i’ undeclared (first use in this function)
    truc.h:95: error: syntax error before ‘/’ token
    truc.h:96: error: missing terminating ' character
    truc.h:120: warning: control reaches end of non-void function
    truc.h: At top level:
    truc.h:133: warning: type defaults to ‘int’ in declaration of ‘fclose’
    truc.h:133: warning: parameter names (without types) in function declaration
    truc.h:133: warning: data definition has no type or storage class
    truc.h:135: error: syntax error before ‘return
    Je n'ai pas d'erreur pour mes NA semble t il... ça ne fonctionne pas en rajoutant un printf sur ces valeurs (ce qui est logique puisque je ne compile toujours pas...)
    J'espère que ça n'affecte pas une valeur entière correspondant au code binaire de la chaîne de caractère NA...

    Bref, merci pour ton aide Metalman...

    @Bktero ce n'est pas vraiment moi qui ai choisi la structure de mes données... Je n'ai pas l'impression (mais je me trompe sûrement) qu'un tableau sera forcément plus simple à traiter que cette structure...
    Disons que là je n'aurais qu'une dimension d'élément de type maStructure à utiliser...
    Et puis maintenant que j'y suis, j'ai pas trop envie de tout revoir depuis le début.



    J'ai aussi regardé ce que ça donnait avec -Wextra:

    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
    In file included from dontot.c:10:
    truc.h:33: error: syntax error before ‘/’ token
    cc1: warnings being treated as errors
    truc.h:33: warning: no semicolon at end of struct or union
    truc.h:34: error: missing terminating ' character
    truc.h:35: error: missing terminating ' character
    truc.h:36: warning: type defaults to ‘int’ in declaration of ‘cell’
    truc.h:36: warning: data definition has no type or storage class
    truc.h:38: error: syntax error before ‘*’ token
    truc.h:38: warning: type defaults to ‘int’ in declaration of ‘parser’
    truc.h:38: warning: data definition has no type or storage class
    truc.h: In function ‘main’:
    truc.h:42: error: syntax error before ‘/’ token
    truc.h:41: warning: unused variable ‘nfile’
    truc.h: At top level:
    truc.h:40: warning: unused parameter ‘argc’
    truc.h:40: warning: unused parameter ‘argv’
    truc.h:56: error: syntax error before ‘*’ token
    truc.h:56: warning: return type defaults to ‘int’
    truc.h: In function ‘parser’:
    truc.h:58: error: syntax error before ‘/’ token
    truc.h:61: warning: passing argument 1 of ‘fopen’ makes pointer from integer without a cast
    truc.h:62: error: ‘data’ undeclared (first use in this function)
    truc.h:62: error: (Each undeclared identifier is reported only once
    truc.h:62: error: for each function it appears in.)
    truc.h:65: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
    truc.h:69: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
    truc.h:70: error: ‘buffer’ undeclared (first use in this function)
    truc.h:70: error: ‘bufsiz’ undeclared (first use in this function)
    truc.h:70: error: syntax error before ‘/’ token
    truc.h:73: error: missing terminating ' character
    truc.h:94: error: ‘i’ undeclared (first use in this function)
    truc.h:95: error: syntax error before ‘/’ token
    truc.h:96: error: missing terminating ' character
    truc.h:120: warning: control reaches end of non-void function
    truc.h: At top level:
    truc.h:133: warning: type defaults to ‘int’ in declaration of ‘fclose’
    truc.h:133: warning: parameter names (without types) in function declaration
    truc.h:133: warning: data definition has no type or storage class
    truc.h:135: error: syntax error before ‘return

    Merci à vous pour votre aide

  6. #6
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Sans le nouveau code, ce n'est pas évident de te dire ce qui se passe et comment le corriger....

    Si, ce sera bien plus facile avec un tableau ! Compare les deux façons de faire suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(int i=0; i<17; i++) printf("%d ", struct.tab[i]);
    printf("%d %d %d ...... %d", struct.x0, struct.x1, ......, struct.x16);
    Es-tu certain qu'il y a 17 "%d" et que tu n'as pas oublié ou dupliqué un struct.xi ? Si maintenant, tu as 19 champs, ou 36, ou 9, tu veux vraiment tout modifier à la main ou tu ne préfères pas modifier le 17 pour limiter la boucle ? 17 qui en plus pourra être la valeur produite avec une macro #define NB_CHAMPS 17 que tu pourras utiliser partout et changer à un seul endroit pour adapter ton code rapidement ? Non, tu ne veux pas ?

    Vite fait sur les messages du compilateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    truc.h:44: warning: passing argument 1 of ‘parser’ makes integer from pointer without a cast  //je ne comprends pas vraiment ce warning: en quoi je cast quelque chose ici?
    Toi tu ne castes sûrement rien mais le paramètre n'est pas du bon type. Tu pas un pointeur alors qu'un integer est attendu (ou l'inverse) et le compilateur fait un cast.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    truc.h:70: error: ‘bufsiz’ undeclared (first use in this function) //===>je ne vois pas comment corriger ça...
    En mettant la déclaration (ou au moins son prototype) de la fonction avant l'endroit où tu l'utilises ou d'inclure le fichier d'en-tête contenant le prototype de cette fonction.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    truc.h:94: error: invalid lvalue in assignment    //===> correspond à mes &data[i].qqch=NULL :(
    Une lvalue est une variable modifiable (à gauche, Left, dans une affectation). Tu essayes donc de modifier quelque chose qui ne peut pas l'être.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    truc.h:135: warning: function returns address of local variable
    Voir le message de diogene.

Discussions similaires

  1. [DOM XML] Parser un fichier XML pour insertion dans la base
    Par npirard dans le forum Bibliothèques et frameworks
    Réponses: 7
    Dernier message: 08/09/2008, 15h44
  2. [bash] utilisation de CAT/AWK pour parser un fichier CSV
    Par arnaudperfect dans le forum Shell et commandes GNU
    Réponses: 32
    Dernier message: 25/07/2007, 23h34
  3. [JDOM] Parser plusieurs fichiers xml pour en faire 1
    Par Mygush dans le forum Format d'échange (XML, JSON...)
    Réponses: 11
    Dernier message: 05/07/2007, 16h15
  4. Réponses: 3
    Dernier message: 19/05/2007, 17h19
  5. Parser un fichier csv
    Par alison239 dans le forum C
    Réponses: 3
    Dernier message: 10/05/2006, 08h59

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