C faire un strtok non destructif

Taurre a marqué ce sujet comme résolu.

Bonjour, je souhaite séparer une chaine à chaque caractere virgule ",", jusque la pas de probleme strtok marche bien, mais quand je le mets dans une boucle while, il ne me garde que la première sous chaine

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main () {
    char data[]="var1,var2";

    int i =0;

    while (i<10) {
        char * result;
        result = strtok(data,",");

        while (result != NULL) {
            printf("result : %s \n", result);
            result = strtok(NULL, ",");
        }
        i++;
    }


    return 0;
}

le résultat de sortie devrait etre : var1 var2 var1 var2

mais non j’obtiens ceci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
result : var1
result : var2
result : var1
result : var1
result : var1
result : var1
result : var1
result : var1
result : var1
result : var1
result : var1
+0 -0

Salut !

De ce que je lis sur la page de man : http://manpagesfr.free.fr/man/man3/strtok.3.html

Évitez au maximum d’utiliser cette fonction. Sinon, prenez note des informations suivantes : […] Cette fonction modifie son premier argument.

L’argument data est modifié par la fonction strtok (tu peux le deviner au type char* au lieu du type const char* qui garantit que les données ne seront pas modifié).

Il faut que tu réinitialises data avant ton premier appel à strtok.

+0 -0

Utilise une variable temporaire.

1
2
3
4
5
6
while(i<10) {
  char* result = NULL;
  char tmp[sizeof data] = {0};
  strcpy(tmp, data);
  result = strtok(tmp, ",");
//
+1 -1

Utilise une variable temporaire.

1
2
3
4
5
6
while(i<10) {
  char* result = NULL;
  char tmp[sizeof data] = {0};
  strcpy(tmp, data);
  result = strtok(tmp, ",");
//
ache

J’ai downvoté non pas poru l’utilisation d’une variable intermédiaire (qui est la bonne chose à faire) mais pour l’utilisation de sizeof data qui va dans le cas général, compiler mais ne pas faire ce qui est attendu. C’est pas vraiment le genre de code à montrer. Dans le cas le plus général,

sizeof data/ sizeof *data avec sizeof *data == 1 car sizeof(char)==1 sur tous les systèmes. Bref, j’ai économisé une division par 1.

Ce message s’adresse à ceux pour qui Davaidbrcz à mis -1.

Mais en toute bonne fois, je ne suis pas sûr de comprendre la raison pour laquelle il a mis -1.
Je pense que Davidbrcz part de ça :

  • sizeof tab donne la taille totale du tableau et pas simplement son nombre d’élements
  • Pour utiliser sizeof tab il faut que tab soit un tableau. Et pas un pointeur sur le premier élément. Les débutants peuvent confondre.

Mais j’avoue que dans les deux cas, pour un exemple en vitesse, je ne vais pas m’étendre sur le sizeof, ce n’était pas ce que je voulais montrer.

+0 -0

Le code que tu montres marche en effet bien avec des tableaux. Si jamais tu récupères une chaîne de caractère sous la forme d’un char* avec un 0 final, tu ne peux pas faire comme ca. sizeof te donnera la taille du pointeur (4 ou 8 en fonction du système). Si jamais ta chaine fait moins de 8 éléments, ca passe, sinon kaboom (au mieux), au pire tu vas labourer la mémoire de façon subtile.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  char a[]="abcd";
  printf("%ld\n",sizeof(a));

  char* b = a;
  printf("%ld\n",sizeof(b));
  return 0;
}

`
+0 -0

Du coup, c’est pas grave, mais pour printf, en C99, on peut utiliser "%zu" (ou "%zd"). C’est spécialement fait pour ça (les size_t) donc autant l’utiliser.

+0 -0

Tout est relatif, je pense que par exotique il voulait dire qu’il ne s’en servait pas tous les jours.

Ge0

Personnellement, c’est un des seuls dont je ne peux plus me passer depuis son apparition. ^^"

Un peu comme %n (le seul exemple empirique que j’ai sous la main).

Ge0

Je m’insurge, %n n’est pas exotique, mais quasi inutilisé, c’est différent. :-°

+0 -0

J’avoue pour *printf c’est pas ultra courant (même si en vrai y a pas mal de formatage qu’on pourrait faire plus simplement avec, je pense), mais pour *scanf je m’en sers vraiment tout le temps.

Lucas-84

Tu as un exemple pour illustrer une simplification de formatage avec l’indicateur n et printf() ? :)
Sinon, il est effectivement intéressant du côté de *scanf() et surtout de sscanf().

+0 -0

Tu as un exemple pour illustrer une simplification de formatage avec l’indicateur n et printf() ? :)

Taurre

En fait c’est pas aussi facile que je pensais de trouver un cas où c’est vraiment plus simple d’utiliser %n par rapport à une autre méthode, mais disons dans l’idéal ça pourrait permettre d’aligner facilement des trucs :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <stdio.h>

int main(void) {
    const char *s1 = "Lettre", *s2 = "Capitale", *s3 = "Pays";
    const char *t1 = "L", *t2 = "Londres", *t3 = "Lybie";
    int l1, l2;
    printf("%s%n | %s%n | %s\n", s1, &l1, s2, &l2, s3);
    printf("%*s | %*s | %s\n", l1, t1, l2 - l1 - 3, t2, t3);
    return 0;
}

`

(J’avoue c’est pas ouf comme exemple, mais on peut imaginer un mélange avec des affichages de flottants et autres objets étranges dont la longueur affichée n’est pas forcément immédiate à calculer.)

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte