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 :

Découper une chaine avec un séparateur strtok


Sujet :

C

  1. #1
    Membre averti Avatar de ZeRevo
    Inscrit en
    Avril 2007
    Messages
    302
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2007
    Messages : 302
    Points : 342
    Points
    342
    Par défaut Découper une chaine avec un séparateur strtok
    Bonjour,

    J'ai besoin de découper une chaine avec un séparateur, j'ai essayé avec la commande strtok mais impossible de la faire tourner quand je n'utilise pas de tableau à taille fixe.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char *ma_string = "test";
    pch = strtok_r(ma_string, sep, saveptr1);
    Erreur de segmentation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char ma_string[] = "test";
    pch = strtok_r(ma_string, sep, saveptr1);
    Correct

    La méthode strtok est deprecated car elle modifie le premier argument, j'ai alors essayé strtok_r mais j'ai le même résultat.

    Il doit bien avoir une possibilité de passer un char * à un char[] facilement, sinon une solution que je voudrais éviter c'est d'utiliser une méthode d'une lib c++ mais je voudrais éviter.

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 076
    Points : 2 328
    Points
    2 328
    Par défaut
    Je crois que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *ma_string = "test";
    ne gere pas l' "\0".
    C'est peut etre la source de ton erreur car s'il parcours la chaine jusqu'a \0, tu va deborder en memoire.

  3. #3
    Membre éprouvé Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Points : 1 132
    Points
    1 132
    Par défaut
    Citation Envoyé par ="ZeRevo"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *ma_string = "test";
    Ton pointeur pointe sur une chaine littérale, souvent placée dans une zone mémoire en lecture seule, d'où l'erreur de segmentation, d'ailleurs une écriture plus correcte serais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    const char *ma_string = "test";
    To start press any key. (reading screen) Where's the "any" key? I see Esc, Catarl, and Pig Up. There doesn't seem to be any "any" key. Wo! All this computer hacking is making me thirsty. I think I'll order a Tab. (presses TAB key). -- HOMER --

  4. #4
    Membre éprouvé Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Points : 1 132
    Points
    1 132
    Par défaut
    Citation Envoyé par SofEvans Voir le message
    Je crois que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *ma_string = "test";
    ne gere pas l' "\0".
    C'est peut etre la source de ton erreur car s'il parcours la chaine jusqu'a \0, tu va deborder en memoire.
    Non, la chaîne littérale est stockée comme une suite de caractères suivis d'un '\0'.
    To start press any key. (reading screen) Where's the "any" key? I see Esc, Catarl, and Pig Up. There doesn't seem to be any "any" key. Wo! All this computer hacking is making me thirsty. I think I'll order a Tab. (presses TAB key). -- HOMER --

  5. #5
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 076
    Points : 2 328
    Points
    2 328
    Par défaut
    Okay, je ne savais plus.
    C'est bon a savoir ^^

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par ZeRevo Voir le message
    La méthode strtok est deprecated car elle modifie le premier argument, j'ai alors essayé strtok_r mais j'ai le même résultat.
    strtok_r() modifie aussi le premier argument. strtok() est dépréciée non pas pour cette raison, mais parce qu'elle utilise une variable statique.

    Le mieux, c'est d'utiliser malloc() pour allouer un nouveau buffer de la taille de la chaîne, et l'y recopier. Si tu es sous un système POSIX, tu as accès à la fonction strdup() qui fait ça toute seule. Dans les deux cas, n'oublie pas le free() à la fin.

    PS: Si ton compilateur est gcc, ajoutes-y l'option -Wwrite-strings. Cela te donnera un warning pour tout char *s="toto", te rappelant que les chaînes littérales sont non-modifiables. Ainsi, seul const char *s="toto" compilera sans warning.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre averti Avatar de ZeRevo
    Inscrit en
    Avril 2007
    Messages
    302
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2007
    Messages : 302
    Points : 342
    Points
    342
    Par défaut
    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
    /* strtok example */
    #include <stdio.h>
    #include <string.h>
     
    int main ()
    {
      const char *str ="- This, a sample string.";
      char * pch;
      printf ("Splitting string \"%s\" into tokens:\n",str);
      pch = strtok (str," ");
      while (pch != NULL)
      {
        printf ("%s\n",pch);
        pch = strtok (NULL, " ");
      }
     
      return 0;
    }
    main.c: In function ‘main’:
    main.c:10: attention : passing argument 1 of ‘strtok’ discards qualifiers from pointer target type
    Splitting string "- This, a sample string." into tokens:
    Erreur de segmentation (core dumped)
    J'ai ajouté le mot clé const mais maintenant la compilation ne fonctionne plus.

    Ce qu'il me faudrait c'est créer une chaine de la forme char mavariable[] mais je ne sais pas comment le faire à partir d'une chaine de type char *machaine

    Désolé mais je n'ai pas compris comment je peux utiliser strdup, est-ce que vous pouvez donner un exemple de code svp

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Code C POSIX : 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
    /* strtok & strdup example */
    #include <stdio.h>
    #include <string.h>
     
    int main(void)
    {
      const char *str = "- This, a sample string.";
      char * tmp;
     
      tmp = strdup(str);
      if (tmp == NULL)
        puts("Memory error.");
      else
      {
        char * pch;
        printf("Splitting string \"%s\" into tokens:\n", tmp);
        pch = strtok(tmp, " ");
        while (pch != NULL)
        {
          printf("%s\n",pch);
          pch = strtok(NULL, " ");
        }
        free(tmp);
      } 
      return 0;
    }
    Note: Généralement, on met un espace entre mot-clé et parenthèse ou entre fonction et parenthèse, mais jamais les deux à la fois.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre averti Avatar de ZeRevo
    Inscrit en
    Avril 2007
    Messages
    302
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2007
    Messages : 302
    Points : 342
    Points
    342
    Par défaut
    Merci bien, toutefois j'ai une erreur à la compilation sur la ligne free(tmp)
    main.c:23: attention : incompatible implicit declaration of built-in function ‘free’

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre averti Avatar de ZeRevo
    Inscrit en
    Avril 2007
    Messages
    302
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2007
    Messages : 302
    Points : 342
    Points
    342
    Par défaut
    Arf à force d'utiliser Eclipse, je fais plus attention aux imports ~~

    Le code fonctionne mais je ne le comprend pas. Je suis allé cherché le code source du strdup.c http://www.diplom.org/~njudge/doxyge...8c-source.html
    mais ça ne me fait pas plus comprendre.

    Pourquoi d'un côté quand on fait char *variable = "toto"; on ne peut pas la passer à la méthode strtok, alors que si on utilise strdup ça fonctionne ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strtok_r() modifie aussi le premier argument. strtok() est dépréciée non pas pour cette raison, mais parce qu'elle utilise une variable statique.
    Comment on sait qu'une variable est statique ? je comprend pas la différence entre allouer un espace mémoire (malloc) et faire char *variable = "toto"; ? Quand on fait char *variable = "toto";, ça fait bien appele à malloc ?

    J'ai trouvé ça :
    http://nicolasj.developpez.com/articles/libc/string/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char s1[11] = "Developpez";
    char s2[] = "Developpez";
    char *s3 = "Developpez";
    La première méthode réserve une zone de 11 bytes et la chaîne "Developpez" y est stockée. La seconde méthode laisse le compilateur calculer la taille appropriée (11 bytes dans notre cas). La dernière méthode ne réserve pas de mémoire, elle se contente de stocker l'adresse d'une chaîne de caractères qui peut se trouver dans un endroit de la mémoire non modifiable par le programme, dans ce cas toute modification de la chaîne s3 se conclura par un comportement indéterminé. il est donc conseillé d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    const char *s3 = "Developpez";
    mais je ne comprend pas bien, pourquoi toute modification de la chaine s3 se conclura par un comportement indéterminé. Comme ça se passe en mémoire quand on crée char *s3 ou const char *s3 ?

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    je comprend pas la différence entre allouer un espace mémoire (malloc) et faire char *variable = "toto"; ? Quand on fait char *variable = "toto";, ça fait bien appele à malloc ?
    Ben non, justement.
    La chaîne "toto" est stockée dans une zone mémoire en lecture seule, initialisée lors du chargement du programme.
    Donc, variable pointe sur de la mémoire en lecture seule. Si on tente d'y écrire, on a une erreur mémoire (segfault sous Linux, Access Violation sous Windows).

    Par contre, malloc() alloue dans une zone mémoire accessible en lecture & écriture. On peut donc y recopier la chaîne (ce que fait strdup) et modifier cette copie.

    Le tableau dans une fonction alloue directement sur la pile, qui est elle aussi accessible en lecture et écriture.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Code C POSIX : 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
    /* strtok & strdup example */
    #include <stdio.h>
    #include <string.h>
     
    int main(void)
    {
      const char *str = "- This, a sample string.";
      char * tmp;
     
      tmp = strdup(str);
      if (tmp == NULL)
        puts("Memory error.");
      else
      {
        char * pch;
        printf("Splitting string \"%s\" into tokens:\n", tmp);
        pch = strtok(tmp, " ");
        while (pch != NULL)
        {
          printf("%s\n",pch);
          pch = strtok(NULL, " ");
        }
        free(tmp);
      } 
      return 0;
    }
    Note: Généralement, on met un espace entre mot-clé et parenthèse ou entre fonction et parenthèse, mais jamais les deux à la fois.
    Attention le free sur tmp ne marchera pas tres bien car la fonction strtok va faire bouger le pointeur sir je me souviens bien.

    il faut conserver un pointeur sur la chaine initiale qui passe pas dans strtok si tu ne veux pas de fuite mémoire.

    enfin si je me souviens bien cela fait longtemps que je ne m'en suis pas servi.
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

  14. #14
    Membre averti Avatar de ZeRevo
    Inscrit en
    Avril 2007
    Messages
    302
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Avril 2007
    Messages : 302
    Points : 342
    Points
    342
    Par défaut
    merci bien

  15. #15
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ZeRevo Voir le message
    Quand on fait char *variable = "toto";, ça fait bien appele à malloc ?
    Non. Ca stocke 't', 'o', 't', 'o', '\0' qq part dans une zone mémoire read-only et ça met l'adresse de cette zone dans "variable".

    Citation Envoyé par ZeRevo Voir le message
    mais je ne comprend pas bien, pourquoi toute modification de la chaine s3 se conclura par un comportement indéterminé.
    Ben justement parce que tu veux modifier une zone non modifiable !!!

    Citation Envoyé par ZeRevo Voir le message
    Comme ça se passe en mémoire quand on crée char *s3 ou const char *s3 ?
    Quelle que soit ta déclaration, la zone pointée par "s3" est constante. Donc la syntaxe "const char* s3" (l'élément pointé par s3 est constant) est la plus appropriée.

    Citation Envoyé par jabbounet Voir le message
    Attention le free sur tmp ne marchera pas tres bien car la fonction strtok va faire bouger le pointeur sir je me souviens bien.
    Depuis quand une fonction qui reçoit (par recopie évidemment) une simple variable est capable de modifier ladite variable ???
    strtok() modifie la zone pointée, pas le pointeur. tmp aura la même valeur avant et après l'appel !!!
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Depuis quand une fonction qui reçoit (par recopie évidemment) une simple variable est capable de modifier ladite variable ???
    strtok() modifie la zone pointée, pas le pointeur. tmp aura la même valeur avant et après l'appel !!!
    +1
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Membre expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Points : 3 284
    Points
    3 284
    Par défaut
    comme je disais cela fait longtemps que je ne l'ai pas utilisé,

    mais il faut quand même faire gaffe au premier argument.
    bazar: http://www.improetcompagnie.com/publ...ctacles-6.html

    BÉPO la disposition de clavier francophone, ergonomique et libre: http://bepo.fr/wiki/Accueil

    Emacs Wiki: http://www.emacswiki.org/

    En attente de ce que produira: http://www.pushmid.com

Discussions similaires

  1. Bash - Découper une chaine de caractères
    Par nicolas.pissard dans le forum Shell et commandes GNU
    Réponses: 13
    Dernier message: 16/12/2014, 13h18
  2. Découper une chaine séparée par des séparateur ;
    Par d.tellier dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 23/12/2010, 18h21
  3. découper une chaine selon un spéarateur
    Par freestyler dans le forum Delphi
    Réponses: 2
    Dernier message: 16/05/2007, 15h44
  4. Extraction d'une chaine avec séparateurs
    Par kaceo dans le forum Requêtes
    Réponses: 1
    Dernier message: 05/05/2006, 10h36
  5. [Débutant][Token] découper une chaine
    Par _Eric_ dans le forum Langage
    Réponses: 14
    Dernier message: 06/07/2004, 10h36

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