Split de chaine de caracteres

lektrosonic Messages postés 145 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 21 février 2013 - 16 janv. 2007 à 02:15
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 - 16 janv. 2007 à 18:30
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

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

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

C++ (@++)<!--
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
16 janv. 2007 à 09:37
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++
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
16 janv. 2007 à 16:08
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++ (@++)<!--
0
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
16 janv. 2007 à 16:28
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++
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
lektrosonic Messages postés 145 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 21 février 2013
16 janv. 2007 à 17:28
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
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
16 janv. 2007 à 17:48
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++ (@++)<!--
0
lektrosonic Messages postés 145 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 21 février 2013
16 janv. 2007 à 17:56
Oui sa m interesse..peux tu me la montrer sil te plait ?
l3KTr0 Was HeRe
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
16 janv. 2007 à 18:07
Ç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++ (@++)<!--
0
lektrosonic Messages postés 145 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 21 février 2013
16 janv. 2007 à 18:13
Je te remercie.

l3KTr0 Was HeRe
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
16 janv. 2007 à 18:30
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++ (@++)<!--
0
Rejoignez-nous