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 des chaines de caracteres


Sujet :

C

  1. #1
    Membre confirmé Avatar de dlecteur
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 147
    Par défaut parser des chaines de caracteres
    Bonsoir,

    J'ai un fichier contenant plusieurs lignes et chacune d'elles contient un étudiant et dont les champs(char *) sont séparés par des ";" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nom;prenom;adresse;annee;
    ...(nombre de champs variable) // le nombre de champs varie d'un étudiant a l'autre

    et je dispose de plusieurs structures pour bien présenter ces lignes sous un format plus visible:

    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
    typedef struct {
        char math[] = "Mathematiques";
        char phy[] = "Physique";
        char info[] = "Informatique";
        } matieresA_t;
     
    typedef struct {
            char his[] = "Histoire";
            char spo[] = "Sport" ;
            char eng[] = "English";       
        } matieresB_t;
     
    typedef struct {
            char nom[] = "nom: ";
            char prenom[] = "prenom: ";
            char num[] = "numero: ";       
            char adresse[] = "Adresse: ";
        } etatCivile_t;
     
    typedef struct {
            char annee[] = "Annee d'etudes: ";
            char option[] = "Option: ";
            char projet[] = "Titre du projet: ";       
        } packageEtudiant_t;
    J'ai transformé chaque ligne en un tableau d'éléments "texte" (char *), et donc j'ai pu obtenir l'écriture suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    etudiant1 : nom prenom annee matiere1 option1 projet1 ...
    ce que je voudrais c'est faire correspondre les éléments des structures a mes différents champs(variables) afin d'aboutir a cette affichage:

    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
    etudiant1:
    nom: "du texte ici"
    prenom : "du texte ici"
    adresse : "du texte ici"
    annee : "du texte ici"
    .
    .
    .
    .
    .
    etudiant2:
    nom: "du texte ici"
    prenom: "du texte ici"
    projet: "du texte ici"
    .
    .
    .
    etc
    mais je sais pas vraiment comment m y prendre! donc votre aide est plus que la bienvenue. Merci.

  2. #2
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct {
        char math[] = "Mathematiques";
        char phy[] = "Physique";
        char info[] = "Informatique";
        } matieresA_t;
    Il faut écrire par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct {
        char math[100];
        char phy[100];
        char info[100];
        } matieresA_t;
    100 ou n'importe quelle autre valeur bien sûr, et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    matieresA_t m = {"Math", "Phy", "Info"};
    Ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    matieresA_t m;
    init_matieresA(&m);
    etc.

    Pour le reste de la question je n'ai pas compris. C'est quoi exactement le problème.

  3. #3
    Membre confirmé Avatar de dlecteur
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 147
    Par défaut
    Merci pour les nouvelles précisions, au fait moi je veux obtenir un affichage de la sorte:
    etudiant1:
    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
    nom: "du texte ici"
    prenom : "du texte ici"
    adresse : "du texte ici"
    annee : "du texte ici"
    .
    .
    .
    .
    .
    etudiant2:
    nom: "du texte ici"
    prenom: "du texte ici"
    projet: "du texte ici"
    .
    .
    .
    sachant que les textes a afficher sont tirés du fichier initial (et donc faire correspondre ces textes avec les structures que tu viens de me montrer).

    Merci.

  4. #4
    Membre éclairé
    Avatar de barthelv
    Inscrit en
    Mars 2003
    Messages
    267
    Détails du profil
    Informations forums :
    Inscription : Mars 2003
    Messages : 267
    Par défaut
    Une solution, c'est au début du programme, tu créées toutes les structures pour ton "élève". Une fois ceci fait, tu initialise à chaine vide tous les attributs de ton "élève".

    Ca c'était la phase de création/initialisation.

    Ensuite, tu remplis les champs de tes structures.

    Enfin, au moment de l'affichage, tu testes si la chaine est non vide avant de faire le printf. Un truc ressemblant à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (*matieresA.math != 0)
    {
      printf("%s", matieresA.math);
    }
    C'est ce que tu veux faire ?

  5. #5
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Pour le parsing tu peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char nom[100];
    ...
    fscanf(fichier, "%99[^;];%99[^;];%99[^;];%99[^;]", nom, prenom, adresse, annee);
    %[^;] signifie qu'on lit tout jusqu'au premier point-virgule rencontré. Le 99 limite le nombre de caractères max à lire.

  6. #6
    Membre confirmé Avatar de dlecteur
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 147
    Par défaut
    Merci a tous les deux pour vos réponses, mais pour l'affichage, y a un problème, parce que je veux que selon le champ, j'affiche la valeur correspondante du champ de ma structure, car les entrées de mon fichier texte non pas les mêmes longueurs, ni les mêmes valeurs des champs.
    J'ai pensé a un pointeur générique lequel va pointer selon les circonstances sur l'une des structures, mais ca va vite devenir illisible!!! Une question: vous avez une idée d'une seule fonction qui peut parcourir au choix l'une mes structures? ca c'est peut etre une piste pour moi.

    Merci.

  7. #7
    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
    Dans ce cas, j'envisagerai peut être une organisation du type suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef enum {Etatcivil, MatA /*,....*/} Ttype; //Définition des différentes possibilités concernant la structure
    typedef struct{
      Ttype type;       // éventuellement : conserver le type peut être utile pour la suite
      int nbData;       // Nombre de chaines de données à stocker
      char const *const * listItem;  // pointe vers la liste des légendes ("nom","prenom",...) pour ce type
      char ** data;    // tableau de nbData pointeurs vers les chaines contenant les données
    } Data;
    Pour l'initialisation des structures, on peut envisager des tableaux globaux (ou static dans la fonction de création):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char const * const listItemEtatcivil[] = {"Nom", "Prenom","Numero","Adresse"};
    char const * const  listItemMatA[] = {"Mathematiques", "Physique","Informatique"};
    /*....etc....*/
    char const * const * const tabListItem[] = {listItemEtatcivil,listItemMatA /*,...*/ };
    int const nbChamps[]  = {4,3 /*,...*/};
    Les deux derniers tableaux doivent être dans l'ordre spécifié dans Ttype

    Il ne reste plus qu'à coder
    1- La création d'une structure (ici en allocation dynamique) et la destruction :
    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
    Data * CreerData(Ttype type)
    {
     int i;
     Data * p = malloc(sizeof *p);
     if(p!=NULL)
     {
        p->type = type;
        p->nbData = nbChamps[type];
        p->listItem = tabListItem[type];
        p->data = malloc(p->nbData * sizeof *p->data);
        if(p->data != NULL)
          for(i = 0 ; i< p->nbData; i++) p->data[i] = NULL; //pas de chaines de données stockées
        else free(p), p = NULL;
     }
     return p;
    }
     
    void detruireData( Data * data)
    {
    .....
    }
    2- Le remplissage d'une structure. Ca peut dépendre pas mal du reste du programme, mais par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int setData( Data * data, int item, char * valeur)
    {
       // Vérifier que data != NULL et que item est dans les limites de l'allocation
       // Libérer la mémoire allouée précédemment pour la chaine N° item  et mettre le pointeur à NULL (permet le remplacement ou la suppression d'une chaine) 
       // si valeur != NULL, allouer la mémoire pour stocker la chaine valeur donc une taille de strlen(valeur)+1 bytes et copier la chaine valeur dans cette mémoire
      // retourner un indicateur d'échec/succès
    }
    3- L'affichage est alors très simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void afficheData(Data const * data)
    {
      int i;
      if(data != NULL)
      {
        for(i=0; i<data->nbData ; i++)
         if(data->data[i] != NULL) printf("%s : %s\n", data->listItem[i],data->data[i]);
        printf("\n");
      }
    }
    4- et tester le tout, 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
      Data *p = CreerData(MatA);
      setData(p,0,"MatA 0");
      setData(p,1,"MatA 1");
      setData(p,2,"MatA 2");
      afficheData(p);
      detruireData(p);
      p = CreerData(Etatcivil);
      setData(p,0,"EC 0");
      setData(p,1,"EC 1");
      setData(p,2,"EC 2");
      setData(p,3,"EC 3");
      afficheData(p);
      detruireData(p);
    qui donnera :
    Mathematiques : MatA 0
    Physique : MatA 1
    Informatique : MatA 2

    Nom : EC 0
    Prenom : EC 1
    Numero : EC 2
    Adresse : EC 3

  8. #8
    Membre confirmé Avatar de dlecteur
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 147
    Par défaut
    Merci beaucoup beaucoup diogene pour cette réponse tout a fait complète (et avec une approche objet ), globalement elle devrait me suffire avec quelques modifications, notamment concernant nbData, qui est variable, donc un (int *), pour la fonction (ou méthode ) detruireData, elle désigne pour vous la ou je dois faire les (free) des mallocs?

    Encore une fois merci a toi et a Melem et barthelv. Je vous tiens au courant.

  9. #9
    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
    Pourquoi si la valeur de nbdata est variable, veux-tu mettre un int * ? (mais il y a peut être un aspect du problème qui m'échappe).

    pour la fonction (ou méthode ) detruireData, elle désigne pour vous la ou je dois faire les (free) des mallocs?
    Oui, il faut détruire tout ce qui a été alloué dynamiquement et qui est relié avec la structure.

  10. #10
    Membre confirmé Avatar de dlecteur
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 147
    Par défaut
    nbData en (int *) pour le passer a une fonction qui fait le parsing de chaque ligne, car les lignes n'ont pas ni les mêmes champs, ni le même nombre d'enregistrement.

  11. #11
    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
    Je n'ai pas toutes les données du problème, mais si je comprend bien ce que tu dis, ça ne donne pas un int * pour nbData mais le passage en argument de l'adresse du champ du genre f(... &data->nbData ...)

    mais je penche plutôt pour passer aux fonctions directement un pointeur vers la structure que l'adresse d'un de ses champs style f(... data ...)

Discussions similaires

  1. Réponses: 2
    Dernier message: 12/10/2006, 20h28
  2. Réponses: 4
    Dernier message: 30/09/2006, 12h27
  3. probleme d'heritage sur des chaines de caracteres
    Par pikiwiki dans le forum C++
    Réponses: 3
    Dernier message: 24/05/2006, 21h01
  4. Lire des fichiers texte (des chaines de caracteres) ifstream
    Par jamesleouf dans le forum SL & STL
    Réponses: 1
    Dernier message: 22/03/2006, 23h58
  5. [langage] Compter des chaines de caractères
    Par julfra dans le forum Langage
    Réponses: 2
    Dernier message: 26/05/2004, 17h42

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