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 :

Tokeniser Pb, char *, vector


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Tokeniser Pb, char *, vector
    Bonjour a tous,

    voila je code un petit Tokenizer en c++ pour m'entrainer sur les char* et les pointeurs.
    je n'utilise volontairement pas les string.

    -j'ai à l'heure actuel deux problèmes je ne sais pas écrire la fonction pour vider mon vector<char *>
    si vous pouvez me fournir de l'aide?

    -lorsque j'exécute mon code tout vas bien mais lorsque je le lance avec gdb un signal sigtrap apparait.
    mais je ne trouve pas l'erreur.je suis presque sure que c un pb de pointeur mais où

    voici le code de la fonction
    toutes les autres fonctions permet de reconnaitre une catégorie de token ex:is_DblOper(Ptr) renvoie 1 si ">=" "<="

    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
    int TK_LoadEval::Str_GetToken(char *ChaineStr,std::vector <char *> &ListeToken)
    {//parcours la chaine et la transforme en token
        if (ChaineStr)
        {   //Init
            char *Ptr=ChaineStr;
            int SizeStr=strlen(ChaineStr);
            if (SizeStr)
            {//si pas chaine vide
                //Str_DelToken(&ListeToken);
                ListeToken.clear();
                ListeToken.reserve(SizeStr/2);   //nettoie le vecteur et reserve la motie de la taille de la chaine
                char *BufferCpy=(char *)calloc(SizeStr,sizeof(char));
                char *ptrBuf=BufferCpy;
                if (BufferCpy)
                {//allocation reussie
                    while (*Ptr!=0)
                    {//pour tous les caracteres
                        if (!isspace(*Ptr))
                        {//c'est pas un blanc
                            if (!is_ProgSepar(*Ptr))    {*ptrBuf=*Ptr;ptrBuf++;}    //pas un separateur
                            else                                                    //c'est un separateur
                            {   //on copie le buffer si present
                                if ((*BufferCpy)!=0)
                                {//le buffer n'est pas vide
                                    *ptrBuf=0;
                                    char *Chaine=(char *)calloc(strlen(BufferCpy)+1,sizeof(char));
                                    memcpy(Chaine,BufferCpy,strlen(BufferCpy));
                                    ListeToken.push_back(Chaine);
                                    memset(BufferCpy,0,strlen(BufferCpy));ptrBuf=BufferCpy;
                                }
                                //on copie l'opérande
                                if (is_DblOper(Ptr))
                                {
                                    char *Chaine=(char *)calloc(3,sizeof(char));
                                    memcpy(Chaine,Ptr,2);Chaine[2]=0;
                                    ListeToken.push_back(Chaine);
                                }
                                else
                                {
                                    char *Chaine=(char *)calloc(2,sizeof(char));
                                    memcpy(Chaine,Ptr,1);Chaine[1]=0;
                                    ListeToken.push_back(Chaine);
                                }
                            }
                        }
                        else
                        {//c'est un blanc
                            if ((*BufferCpy)!=0)
                            {//le buffer n'est pas vide
                                *ptrBuf=0;
                                char *Chaine=(char *)calloc(strlen(BufferCpy)+1,sizeof(char));
                                memcpy(Chaine,BufferCpy,strlen(BufferCpy));
                                ListeToken.push_back(Chaine);
                                memset(BufferCpy,0,strlen(BufferCpy));ptrBuf=BufferCpy;
                            }
                        }
                        Ptr++;
                    }
                    //dernier item
                    if ((*BufferCpy)!=0)
                    {//le buffer n'est pas vide
                        *ptrBuf=0;
                        char *Chaine=(char *)calloc(strlen(BufferCpy)+1,sizeof(char));
                        memcpy(Chaine,BufferCpy,strlen(BufferCpy));
                        ListeToken.push_back(Chaine);
                        memset(BufferCpy,0,strlen(BufferCpy));
                    }
                    free(BufferCpy);
                    int tt=0;
                    fprintf(stdout,"Ligne: ' %s '\n\t< %s >" , ChaineStr,ListeToken[0] );
                    for (tt=1;tt<ListeToken.size();tt++) {fprintf(stdout,",< %s >",ListeToken[tt]);}
                    fprintf(stdout,"\n");
                    return 1;
                }
            }
        }
        return 0;
    }

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Suite
    N'ayant pas de réponse je rajoute quelques informations

    le deuxième message est problématique pour moi car il n'y a pas de points d'arrêt dans le programme, donc je pense qu'il y a une faille dans mon code c'est pour cela que je l'ai posté en espérant que vous puissiez y voir quelque chose que j'aurais loupé.

    pour la première question: est ce que ceci est correct. (j'ai crée le char* avec calloc donc je dois utilisé free()? )

    Code C/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
     
      void EffacerTblItem (std::vector <char *> *ListeToken)
      {//efface les allocations de la liste
          if (ListeToken)
          {
             if (ListeToken.size())
             {
                 int i=0;char *Temp=NULL;
                 for (i=0;i<ListeToken.size;i++)
                 {
                     temp=ListeToken->back():
                     ListeToken->pop_back();
                     if (temp) free(temp);     //ou peut être delete
                 }
             }
          }
      }

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 116
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 116
    Points : 32 968
    Points
    32 968
    Billets dans le blog
    4
    Par défaut
    Plusieurs choses

    - en C++ on utilise new et delete
    - en C++ on favorise std::string
    -- l'utilisation de std::string n'empêche en rien de travailler avec son const char*

    ton code est brouillon, et à moitié faux
    - strlen retourne le nombre de cartactères de la chaîne
    -- strlen n'inclut pas le 0 final
    - beaucoup trop de copies de pointeurs inutile
    -- pourquoi créer Ptr pour recevoir ChaineStr
    -- pourquoi créer ptrBuff pour recevoir BufferCpy
    - BufferCpy n'est jamais initialisé
    - la copie de chaîne c'est strcpy

    Concernant ton nouveau code
    - size() et non size
    - tes variables ont des portées inutilement trop grandes
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour PADYVEN.

    Déjà ca va être difficile de trouver un développeur C++ qui corrige ton problème. Le code est à 80% du C, et il n'est pas compilable tel que présenté ici.

    Le C++ et le std::string, c'est justement pour éviter cette gestion laborieuse des chaînes de charactères.

    Néanmoins, si tu souhaites vraiment réaliser ce bout de code de cette façon, je te conseilles de poster dans le forum C. Il faudra alors le présenter avec des tableaux, et non pas des std::vector, parce qu'ils vont râler...

    Sinon postes un code qui compile en mode console, avec un main et les en-têtes.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Questions/reponses
    Bonsoir et merci de vos réponses.

    j'aimerais apporter quelques éclaircissements.
    Mais avant toutes chose j'aimerais préciser que mes réponses ne sont en rien agressives mais traduisent mon interrogation face à certaines réponses.

    Fonctionnement attendu de mon code:
    en entree --> chaine de caractere de type " Jmp 1,1;/0"
    attendu en sortie "Jmp" , "1" , "," , "1" , ";"
    fonctionnement Ptr pointe sur ChaineStr, si conforme aux conditions
    recopie dans Buffercopy par l'intermediaire de PtrCpy.

    - strlen retourne le nombre de caractères de la chaîne
    -- strlen n'inclut pas le 0 final

    Oui merci j'ai lu la doc, mais c'est bien ainsi que je l'utilise.

    La chaine qui arrive dans ce bout de code à déjà été nettoyé auparavant et j'ai donc la certitude du zéro final.

    - en C++ on favorise std::string
    -- l'utilisation de std::string n'empêche en rien de travailler avec son const char*
    --> Pourquoi? pourquoi est on OBLIGER d'utiliser un string alors que cela vas me couter un constructeur et un destructeur(appelé en interne.) je présume que si le C++ reconnais toujours le char et le char * c'est pour l'utiliser. je cherchais de la rapidité (oui je sais il faut faire gaffe à la micro optimisation.)

    ton code est brouillon et à moitié faux
    Bien merci d'accord c'est peut être pour cela que je le poste. Pourquoi est il brouillon?, que proposes tu....a tu des pistes de code semblable, ou un lien pouvant servir de référence pour savoir comment BIEN faire.
    A moitié faux encore une fois, je suis d'accord mais où?pourquoi? Je voudrais quand même signaler que le seul problème que j'avais à l'exécution du code en débogueur était le signal SIGTRAP, le code s'exécute à l'heure actuelle rapidement et fonctionne exactement comme je le désirais.
    je n'ai pas posté l'ensemble du code pour ne pas surcharger ma question, j'étais sure de l'emplacement du bug mais je ne le comprenais pas.

    - beaucoup trop de copies de pointeurs inutile
    Là tu m' intéresse... Quelles pistes peut tu me proposer?

    -- pourquoi créer Ptr pour recevoir ChaineStr
    Ptr ne reçoit pas chainestr, il pointe dessus pour pouvoir la parcourir.

    -- pourquoi créer ptrBuff pour recevoir BufferCpy
    - BufferCpy n'est jamais initialisé

    --> char *ptrBuf=BufferCpy;
    -->...
    -->if (!is_ProgSepar(*Ptr)) {*ptrBuf=*Ptr;ptrBuf++;}

    - la copie de chaîne c'est strcpy
    Encore une fois merci j'ai lu la doc, mais que reproches tu a memcpy?
    je sais que mes 0 finaux sont présents donc je gagne du temps en faisant une copie binaire.

    Concernant ton nouveau code
    - tes variables ont des portées inutilement trop grandes

    Je ne comprend pas ta dernière remarque
    la portée de mes variables est limité à void EffacerTblItem?

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Citation Envoyé par PADYVEN Voir le message
    Mais avant toutes chose j'aimerais préciser que mes réponses ne sont en rien agressives mais traduisent mon interrogation face à certaines réponses.
    Effectivement tes réponses ne sont pas agressives. Je laisserai Bousk te répondre, mais je ne pense pas non plus que sa réponse est agressive.

    La majorité des développeurs C++ vont t'orienter vers des solutions C++, du moins qui respectent la philosophie (cin/cout, new/delete, std::string).

    Si ton problème c'est l'optimisation, en effet du C pur est une bonne idée. Mais c'est contradictoire avec le fait d'utiliser des std::vector, et de ne pas compiler avec le compilateur C.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    - Le coût d'un constructeur et d'un destructeur de std::string est probablement négligeable par rapport aux nombreux calloc/free. Et a l'avantage de ne pas générer de fuite mémoire ou d'adressage erronée.

    - Il est intéressant de regarder les algorithmes proposés par la STL car ça nous permet souvent d'économiser le code et de se concentrer sur ce qu'on veut vraiment faire :
    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
    #include <string>
    #include <algorithm>
    #include <vector>
     
    void tokenize(std::string const input, std::string const separator, std::vector<std::string>& tokens)
    {
       std::string::const_iterator it_start = input.begin();
       std::string::const_iterator const it_end = input.end();
     
       for(std::string::const_iterator it = it_start; it_start!=it_end; it = std::find_first_of(it_start,it_end,separator.begin(),separator.end()))
       {
          if(it_start!=it)
          {
             tokens.push_back(std::string(it_start,it));
          }
          it_start = (it==it_end)?it_end:(it+1);
       }
    }
     
    #include <iostream>
    #include <iterator>
    int main()
    {
       std::string const input = " Jmp 1,1;/0";
       std::string const separator = " \t,;/";
       std::vector<std::string> tokens;
       tokenize(input,separator,tokens);
       std::copy(tokens.begin(),tokens.end(),std::ostream_iterator<std::string>(std::cout,"-"));
       std::cout<<"\n";
     
       return 0;
    }
    - Cela reste vrai en C (cf strtok par exemple)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. bien utiliser vector<char>
    Par Korhyana dans le forum Débuter
    Réponses: 7
    Dernier message: 25/02/2009, 14h42
  2. vector<vector<char> > Matrice;
    Par fatjoe dans le forum SL & STL
    Réponses: 66
    Dernier message: 08/05/2008, 17h26
  3. Problème avec vector<char>
    Par Fahmi06 dans le forum C++
    Réponses: 6
    Dernier message: 13/08/2007, 17h10
  4. vector<unsigned char> et unsigned char* : conversion ?
    Par zax-tfh dans le forum SL & STL
    Réponses: 5
    Dernier message: 15/01/2006, 10h43
  5. char[50] et std::vector<>
    Par tut dans le forum SL & STL
    Réponses: 9
    Dernier message: 12/10/2004, 13h26

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