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 :

séparation des champs d'une ligne d'un fichier en C


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 32
    Points : 19
    Points
    19
    Par défaut séparation des champs d'une ligne d'un fichier en C
    bonjour tout le monde,

    j'ai un fichier de type .csv que je veux séparer les champs et les mettre chacun dans un tableau de chaine de caractères.
    j'ai eu l'idée de développer une fonction qui prend en paramètre une ligne du fichier (stockée dans un tableau de char) et le nbr des champs et ensuite de lire cette chaine et séparer les champs.
    par exple la ligne est la suivante:
    meriem, ensi, pfe
    on la stocke dans un tableau : meriem, ensi, pfe \0
    ensuite je veux mettre le champs "meriem" dans un tableau de chaine de caractère, le champs "ensi" dans un autre et le champs "pfe" dans un autre.

    SVP comment puis-je faire cela????
    est ce qu'une boucle for fera l'affaire??


    i need your help!!!!!!
    Thanks
    best regards

  2. #2
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Tout dépend des spécifications exactes sur le format des données :
    Le nombre d'éléments sur une ligne est-il fixe et connu ?
    Ces éléments peuvent-ils comporter des blancs à l'intérieur ?
    Les éléments peuvent-ils être précédés et/ou suivis par des blancs ?
    Certains des éléments peuvent-ils manquer (avec un nombre de séparateurs ',' correct) ?
    ...

    Si on connait le nombre d'éléments à séparer et si les éléments ne comportent pas de blancs mais peuvent être précédés ou suivis par des blancs ou être omis, on peut analyser la ligne par un sscanf(). Par exemple :
    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
    #define N 6
      const char tab[N][50] =
         { "meriem, ensi, pfe ",
          "  meriem1 ,,  ",
          "meriem2   , ensi2 , pfe2 ",
          " meriem3   ,  , pfe3 " ,
          ",   , pfe4 ",
          ",,"
         };
      char dest1[N][10+1]={0}; // 10 longueur max d'un élément
      char dest2[N][10+1]={0};
      char dest3[N][10+1]={0};
      int i;
      for(i=0;i<N;i++)
         sscanf(tab[i]," %[^ ,] , %[^ ,] , %[^ ,]",dest1[i],dest2[i],dest3[i]);
      // attention aux blancs du format
    Sinon, on peut utiliser strtok()

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    Je vous remercie pour votre réponse.
    voilà la spécification des champs:
    -les champs ne comportent pas des blancs mais parfois un champs peut être vide.
    -pour un même fichier, le nombre des champs a séparer est le même.
    -les éléments ne comportent pas des blancs à l'intérieur.
    -les champs sont séparés par exactement un et un seul "," qui suit directement le champs
    -les champs n'ont pas tous la même longueur.

    voilà un exple du fichier

    meriem,ensi,pfe
    maha,isg,stage
    marouane,insat,pfe

    vous remerciant,

  4. #4
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Cela correspond donc au code exemple que j'ai donné (qui supporte et élimine en plus les blancs qui peuvent précéder ou suivre les champs).

    Pour la réalisation effective du stockage, cela dépend de ce que tu veux faire.

  5. #5
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    32
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 32
    Points : 19
    Points
    19
    Par défaut
    je vous remercie encore.

    dans ce cas je vous ai donné un fichier dont chaque ligne contient 3 champs mais ce n'est pas le cas toujours.
    mon programme va ouvrir le fichier, calculer le nombre de champs d'une ligne
    ce nombre va correspondre aux nombre de tableaux dest (comme vous l'avez nommez)
    donc je dois créer un tableau dest à chaque fois que je termine la lecture d'un champs càd à chaque fois que je rencontre un "," je dois créer un tableau qui va contenir la chaine déjà lue.

    vous remerciant,

  6. #6
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Comme il y a beaucoup de choses qui varient suivant le fichier traité, on a intérêt à se tourner vers l'allocation dynamique. On peut traiter le problème soit avec des tableaux que l'on redimensionne au besoin, soit par des listes chainées. C'est assez lourd à mettre en oeuvre à cause de la gestion des échecs des allocations qu'il faut prévoir, mais permet de traiter un cas général.

    Version avec des tableaux :

    - Chaque champ de chaque enregistrement (ligne) est une chaine de caractères qui sera allouée dynamiquement (à la taille juste nécessaire et suffisante). Cette allocation nous donnera un char*

    - un champ, pour l'ensemble de tous les enregistrements, correspond donc à un tableau de char* (tableau qui contiendra l'adresse des chaines). Comme on ne connait pas le nombre final d'enregistrements, ce tableau sera alloué dynamiquement et redimensionné si besoin. Cette allocation nous donnera un char**.
    Pour éviter de redimensionner trop fréquemment le tableau, on aura intérêt à allouer plus, et à ne réallouer que si le besoin se présente. Par exemple, si le tableau alloué a N éléments et est plein, un nouvel enregistrement provoquera un accroissement de l'allocation de k*N au lieu de N+1 (k voisin de 1.6 est souvent considéré comme un bon choix). A la fin, on saura le nombre total d'éléments et on pourra, si on veut, récupérer la mémoire inutilisée.
    Il faudra conserver quelque part le nombre d'enregistrements stockés et la quantité allouée.

    - Le nombre de champs étant inconnu à la compilation, ces tableaux de champs doivent être créés dynamiquement dès qu'on connaitra le nombre de champs. On va donc créer un tableau de tableaux de champs qui nous donnera un char***.
    Pour connaitre le nombre de champs, on utilise la première ligne et on compte les ','. Par exemple, si la ligne est dans tab :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        int nbChamps = 1;
        const char * q;
        for(q=tab; (q= strchr(q,','))!= NULL; q++) nbChamps ++ ;
    - On a sans doute intérêt à regrouper toutes ces informations dans une structure. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct
    {
      int nbChamps;     // nb de champs par ligne (dimension allouée pour champs)
      int nbEnreg;      // nb d'enregistrements effectués (nb de lignes lues)
      int nbAlloue;     // nb d'enregistrements alloués
      float facteur;    // facteur d'accroissement de la quantité nbAlloue;
      char *** champs;  // tableaux des champs
    }ListeChamps;
    Pour accéder à la liste des enregistrements du champ n°i (0..nbChamps-1), on fera champs[i]
    Pour accéder à l'enregistrement n°j (0..nbEnreg-1) du champ n°i (0..nbChamps-1), on fera champs[i][j]

    - Il reste à écrire une fonction qui va créer une telle structure. Elle aura l'allure suivante :
    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
    ListeChamps* InitChamps(const char * chaine, int alloc, float facteur)
    {
      const char * q;
      int i, j;
      ListeChamps *p;
      if(chaine == NULL) return NULL;
      p = malloc(sizeof *p);
      if(p== NULL) return NULL;
      p->champs = NULL;
      p->facteur = facteur;
      p->nbAlloue = alloc;
      p->nbEnreg = 0;
     // chercher le nombre de champs : compter le nombre de ','
      p->nbChamps = 1;
      for(q=chaine;(q= strchr(q,','))!= NULL;q++) p->nbChamps ++ ;
     // allouer le tableau de tableaux
      p->champs = malloc(p->nbChamps*sizeof *(p->champs));
      if(p->champs == NULL)
      {
         free(p);
         return NULL;
      }
     // allouer chaque tableau
      for(i=0; i<p->nbChamps; i++)
      {
         p->champs[i] = malloc(p->nbAlloue*sizeof *(p->champs[i]));
         if(p->champs[i] != NULL)
            for(j=0; j<p->nbAlloue; j++) p->champs[i][j] = NULL;
         else
         {
            for(j=0; j<i; j++) free(p->champs[j]);
            free(p->champs);
            free(p);
            return NULL;
         }
      }
      return p;
    }
    - Il faut maintenant écrire la fonction de destruction de cette structure de données : void DetruireChamps(ListeChamps* p).

    - Puis ensuite, écrire une fonction qui à partir d'une ligne, fait l'analyse des champs. Son prototype peut être int InsereChamps(ListeChamps* p , char* ligne) et elle peut renvoyer un code indiquant le succès ou l'erreur.
    * Si il n'y a plus de place dans les tableaux (p->nbEnreg == p->nbAlloue) réallouer la quantité mémoire allouée aux p->champs[i]. Tester la réussite de ces allocations et prendre des dispositions en cas d'échec.
    * Si le champ n°i de la ligne n'est pas vide, allouer de la mémoire pour ce champ (strlen(champ)+1) (tester la réussite de l'allocation etc ...) et le copier dedans
    * mettre l'adresse obtenue (ou NULL si le champ est vide) dans le bon tableau, à la bonne place : en p->champs[i][p->nbEnreg]. Incrémenter p->nbEnreg


    L'ennui est la gestion des erreurs d'allocations qui alourdissent beaucoup le code, mais on n'y échappe pas si on veut faire un travail sérieux.

Discussions similaires

  1. Copier les valeurs des champs d'une ligne dans la ligne suivante
    Par xoxo72 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 15/09/2014, 11h10
  2. Réponses: 3
    Dernier message: 16/04/2011, 12h49
  3. Problème pour modifier ordre des champs d'une ligne
    Par zram29 dans le forum Langage
    Réponses: 4
    Dernier message: 02/06/2010, 14h05
  4. mise à jour des champs d'une ligne de table
    Par laurentSc dans le forum Langage SQL
    Réponses: 6
    Dernier message: 25/12/2009, 20h09
  5. Hauteur adapté à l'ensemble des champs d'une ligne: Pas de réponses?!
    Par mikebo74 dans le forum SAP Crystal Reports
    Réponses: 0
    Dernier message: 05/12/2007, 16h22

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