127 votes

Comment strtok() divise-t-il la chaîne de caractères en tokens en C ?

Veuillez m'expliquer le fonctionnement de strtok() fonction. Le manuel indique qu'elle décompose la chaîne de caractères en jetons. Je ne parviens pas à comprendre ce qu'elle fait réellement.

J'ai ajouté des montres sur str et *pch pour vérifier son fonctionnement lors de la première boucle while, le contenu du fichier str étaient seulement "ceci". Comment la sortie montrée ci-dessous s'est-elle imprimée à l'écran ?

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  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;
}

Sortie :

Splitting string "- This, a sample string." into tokens:
This
a
sample
string

246voto

Claptrap Points 21299

La fonction d'exécution strtok fonctionne comme suit

la première fois que vous appelez strtok vous fournissez une chaîne de caractères que vous voulez tokeniser

char s[] = "this is a string";

dans la chaîne ci-dessus, l'espace semble être un bon délimiteur entre les mots, alors utilisons-le :

char* p = strtok(s, " ");

ce qui se passe maintenant, c'est que 's' est recherché jusqu'à ce que le caractère espace soit trouvé, le premier jeton est retourné ('this') et p pointe vers ce jeton (chaîne de caractères).

afin d'obtenir le jeton suivant et de continuer avec la même chaîne, NULL est passé comme premier argument. puisque strtok maintient un pointeur statique à votre chaîne passée précédente :

p = strtok(NULL," ");

p pointe maintenant vers 'is'.

et ainsi de suite jusqu'à ce qu'il n'y ait plus d'espaces, puis la dernière chaîne est renvoyée comme le dernier jeton 'string'.

Plus commodément, vous pourriez l'écrire comme ceci pour imprimer tous les jetons :

for (char *p = strtok(s," "); p != NULL; p = strtok(NULL, " "))
{
  puts(p);
}

EDIT :

Si vous voulez stocker les valeurs retournées de strtok vous devez copier le jeton dans un autre tampon, par exemple. strdup(p); puisque la chaîne originale (pointée par le pointeur statique à l'intérieur de strtok ) est modifié entre les itérations afin de retourner le jeton.

44voto

Sachin Shanbhag Points 20979

strtok() divise la chaîne de caractères en jetons, c'est-à-dire qu'en partant de n'importe quel délimiteur jusqu'au suivant, on obtient un jeton. Dans votre cas, le jeton de départ sera de "-" et se terminera par l'espace suivant " ". Ensuite, le token suivant commencera à partir de " " et se terminera par " , ". Ici, vous obtenez "This" en sortie. De la même manière, le reste de la chaîne est divisé en jetons d'espace en espace et le dernier jeton se termine par ".".

33voto

John Bode Points 33046

strtok maintient une référence interne statique pointant vers le prochain token disponible dans la chaîne ; si vous lui passez un pointeur NULL, il travaillera à partir de cette référence interne.

C'est la raison pour laquelle strtok n'est pas ré-entrant ; dès que vous lui passez un nouveau pointeur, cette ancienne référence interne est détruite.

10voto

Mat Points 104488

strtok ne modifie pas le paramètre lui-même ( str ). Il stocke ce pointeur (dans une variable statique locale). Elle peut ensuite modifier ce que ce paramètre Les points suivants dans les appels suivants sans que le paramètre soit renvoyé. (Et il peut faire avancer le pointeur qu'il a conservé comme il le souhaite pour effectuer ses opérations).

De la norme POSIX strtok page :

Cette fonction utilise un stockage statique pour garder la trace de la position actuelle de la chaîne entre les appels.

Il existe une variante thread-safe ( strtok_r ) qui ne fait pas ce type de magie.

9voto

Ziffusion Points 3783

Strtok va tokeniser une chaîne de caractères, c'est-à-dire la convertir en une série de sous-chaînes.

Pour ce faire, il recherche les délimiteurs qui séparent ces éléments (ou sous-chaînes). Et vous spécifiez les délimiteurs. Dans votre cas, vous voulez que ' ' ou ',' ou '.' ou '-' soit le délimiteur.

Le modèle de programmation pour extraire ces tokens est que vous donnez à strtok votre chaîne principale et l'ensemble des délimiteurs. Vous l'appelez ensuite à plusieurs reprises, et à chaque fois, strtok renvoie le prochain token qu'il trouve. Jusqu'à ce qu'il atteigne la fin de la chaîne principale, où il renvoie un null. Une autre règle est que vous passez la chaîne de caractères seulement la première fois, et NULL pour les fois suivantes. C'est une façon de dire à strtok si vous commencez une nouvelle session de tokénisation avec une nouvelle chaîne, ou si vous récupérez des tokens d'une session de tokénisation précédente. Notez que strtok se souvient de son état pour la session de tokénisation. Pour cette raison, il n'est pas réentrant ou thread safe (vous devriez utiliser strtok_r à la place). Une autre chose à savoir est qu'il modifie réellement la chaîne originale. Il écrit ' \0 pour les délimiteurs qu'il trouve.

Une façon d'invoquer strtok, succinctement, est la suivante :

char str[] = "this, is the string - I want to parse";
char delim[] = " ,-";
char* token;

for (token = strtok(str, delim); token; token = strtok(NULL, delim))
{
    printf("token=%s\n", token);
}

Résultat :

this
is
the
string
I
want
to
parse

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X