Split de chaine de caracteres

Signaler
Messages postés
145
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
21 février 2013
-
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
-
Existe-il une fonction predefinie qui transforme char[ ]="ceci|est|une|chaine|separee/0"  en char1[]="ceci", char2[]="est" .... ?

l3KTr0 Was HeRe

10 réponses

Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
strtok
Exemple:
char buffer[] = "salut a tous";
char *ptr[3];

ptr[0] = strtok(buffer," ");
ptr[1] = strtok(0, " ");
ptr[2] = strtok(0, "\0");

C++ (@++)<!--
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
strtok est une vieille daube qu'il convient d'oublier cause que pas safe thread.
On fait la même chose en balladant 2 pointeurs et pas de bugs en multi thread.

ciao...
BruNews, MVP VC++
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
Je m'en doute. Je ne m'en sers jamais. J'utilise plutôt mes propres routines mais si je n'avais pas donné d'exemple avec strtok mais avec mes routines, quelqu'un d'autre aurais ramené cette fonction sur le planché.
Tu dois probablement être mieu placé que moi pour le savoir mais on s'écoeure à la longue de se faire dire que sa méthode de travail n'est pas bonne et qu'une fonction désuette ou boulet (sprintf) est meilleur malgré le fait que ce n'est pas vrai du tout. Ou encore, que l'on m'ignore quand je dit, par exemple, que lire un fichier tout d'un coup et traiter le buffer avec des pointeurs après est beaucoup plus rapide que de lire que par petite section à la fois. Très frustrant tout ça.
Fini de chialer... Voici donc la routine en question. À optimiser probablement (j'ai jamais eu à traiter ce genre de context). Elle stock le tout dans un tableau de pointeur:

char test[] = "salut a tous";
char *ptr[3], *c = &test[0], *d = c;
int i = 0;

while(1)
{    if(*c ' ' || *c '\n')
    {
        *c = 0;
         ptr[i++] = d; d = c+1;
    }
    else if(!*c) { ptr[i] = d; break; }
    c++;
}

printf("%s %s %s\n", ptr[0], ptr[1], ptr[2]);
C++ (@++)<!--
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
27
Un concert de pleureuses ne doit pas nous empêcher de coder.
Il ne faut pas craindre de se répéter, seulement d'être incompris.

ciao...
BruNews, MVP VC++
Messages postés
145
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
21 février 2013

hmm SAKingnom...peut tu expliquer en 2 mots comment tu reussit a spliter ?
j ai pas compris pourquoi tu utilise une boucle infini...

l3KTr0 Was HeRe
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
La boucle n'est pas infinie. J'ai pas beaucoup de talent dans les explications mais:

...
char *ptr[3], *c = &test[0]
char *d = c; // <- Sers à pointer sur le "début" du mot
...

while(1)
{    if(*c ' ' || *c '\n') // <- On roule jusqu'à trouver un espace ou un saut de ligne
    {
        *c = 0; // <- On remplace l'occurance par un 0 de fin de chaine
         ptr[i++] = d; // <- On fait pointer un des pointeurs du tableau sur le mot
        d = c+1; // <- On fais pointer d sur la position du second mot (+1 pour sauter l'occurance)
    }
    else if(!*c) { ptr[i] = d; break; } // Si on rencontre un 0, on pointe sur le dernier mot et on quitte
    c++;
}

En gros, cette routine roule jusqu'à trouver une occurance. Elle remplace celle-ci par un 0 pour créé une chaine, fais pointer un des pointeurs du tableau sur la "nouvelle" chaine puis sauvegarde la première position après l'occurance (qui devrais être la première lettre d'une autre chaine) et ainsi de suite jusqu'à la rencontre du 0 de fin de chaine de la vrai chaine. Elle ne fais donc là que pointer le mot et elle quitte directement la boucle.

Attention, il ne s'agit que de pointeur. Il reste donc dépendant de la chaine principal (qui ce retrouve donc modifié). Si tu écrase la chaine principal, les pointeurs risque de ne plus pointer sur la bonne location.

Si tu veux garder la chaine principal intacte ou si tu veux la réutiliser pour autre chose, j'ai un autre code qui sauvegarde les chaines dans un tableau à 2 dimensions tout en laissant la principal inchangé. Si ça t'interesse...

C++ (@++)<!--
Messages postés
145
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
21 février 2013

Oui sa m interesse..peux tu me la montrer sil te plait ?
l3KTr0 Was HeRe
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
Ça fait un moment que je l'est fais celle-là elle n'est donc pas très optimisé (n'utilise pas de pointeur entre autre) mais fais tout de même l'affaire. À toi de l'optimiser et/ou modifier à tes besoins:

char buffer[] = "salut a tous";
char tab[3][10]; // <- 3 mots de chacun 9 char + 0 de fin de chaine int i 0, j 0;

while(1)
{
     int k = 0;
    while(buffer[i] != ' ' && buffer[i] != '\n' && buffer[i])
    {
        tab[j][k] = buffer[i];
        i++; k++;
    }
    tab[j][k] = 0;
    if(!buffer[i]) break;
    i++; j++;
}

tab[0] contien "Salut" tab[1] contien "a" et tab[2] contien "tous"

C++ (@++)<!--
Messages postés
145
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
21 février 2013

Je te remercie.

l3KTr0 Was HeRe
Messages postés
3212
Date d'inscription
lundi 7 novembre 2005
Statut
Membre
Dernière intervention
16 février 2009
15
Déjà, on peut avoir un code beaucoup plus compact en modifient quelques petites choses:

...
do
{
    int k = 0;
    while(buffer[i] != ' ' && buffer[i] != '\n' && buffer[i]) tab[j][k++] = buffer[i++];
    tab[j++][k] = 0;
} while(buffer[i++]);

C++ (@++)<!--