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

8voto

tibur Points 7082

La première fois que vous l'appelez, vous fournissez la chaîne à tokeniser à strtok . Et ensuite, pour obtenir les jetons suivants, il suffit de donner NULL à cette fonction, pour autant qu'elle renvoie une valeur non NULL pointeur.

Le site strtok enregistre la chaîne de caractères que vous avez fournie en premier lieu lorsque vous l'appelez. (Ce qui est vraiment dangereux pour les applications multi-thread)

5voto

xpmatteo Points 4850

Strtok modifie sa chaîne d'entrée. Il place les caractères nuls (' \0 ) pour qu'il renvoie des éléments de la chaîne originale sous forme de jetons. En fait, strtok n'alloue pas de mémoire. Vous comprendrez peut-être mieux si vous dessinez la chaîne de caractères comme une séquence de cases.

3voto

Fehmi Noyan ISI Points 92

Pour comprendre comment strtok() fonctionne, il faut d'abord savoir ce qu'est un variable statique est. Ce lien l'explique très bien....

La clé du fonctionnement de strtok() préserve l'emplacement du dernier séparateur entre les appels seccessifs (c'est pourquoi strtok() continue à analyser la chaîne de caractères originale qui lui a été transmise lorsqu'il est invoqué avec une commande de type null pointer en appels successifs)..

Jetez un coup d'œil à mon propre strtok() appelé zStrtok() qui a une fonctionnalité légèrement différente de celle fournie par l'option strtok()

char *zStrtok(char *str, const char *delim) {
    static char *static_str=0;      /* var to store last address */
    int index=0, strlength=0;           /* integers for indexes */
    int found = 0;                  /* check if delim is found */

    /* delimiter cannot be NULL
    * if no more char left, return NULL as well
    */
    if (delim==0 || (str == 0 && static_str == 0))
        return 0;

    if (str == 0)
        str = static_str;

    /* get length of string */
    while(str[strlength])
        strlength++;

    /* find the first occurance of delim */
    for (index=0;index<strlength;index++)
        if (str[index]==delim[0]) {
            found=1;
            break;
        }

    /* if delim is not contained in str, return str */
    if (!found) {
        static_str = 0;
        return str;
    }

    /* check for consecutive delimiters
    *if first char is delim, return delim
    */
    if (str[0]==delim[0]) {
        static_str = (str + 1);
        return (char *)delim;
    }

    /* terminate the string
    * this assignmetn requires char[], so str has to
    * be char[] rather than *char
    */
    str[index] = '\0';

    /* save the rest of the string */
    if ((str + index + 1)!=0)
        static_str = (str + index + 1);
    else
        static_str = 0;

        return str;
}

Et voici un exemple d'utilisation

  Example Usage
      char str[] = "A,B,,,C";
      printf("1 %s\n",zStrtok(s,","));
      printf("2 %s\n",zStrtok(NULL,","));
      printf("3 %s\n",zStrtok(NULL,","));
      printf("4 %s\n",zStrtok(NULL,","));
      printf("5 %s\n",zStrtok(NULL,","));
      printf("6 %s\n",zStrtok(NULL,","));

  Example Output
      1 A
      2 B
      3 ,
      4 ,
      5 C
      6 (null)

Le code est tiré de une bibliothèque de traitement des chaînes de caractères que je maintiens sur Github appelé zString. Jetez un coup d'oeil au code, ou même contribuez :) https://github.com/fnoyanisi/zString

3voto

Dipak Points 373

Voici comment j'ai implémenté strtok, pas très bien mais après 2 heures de travail, j'ai finalement réussi à le faire fonctionner. Il supporte les délimiteurs multiples.

#include "stdafx.h"
#include <iostream>
using namespace std;

char* mystrtok(char str[],char filter[]) 
{
    if(filter == NULL) {
        return str;
    }
    static char *ptr = str;
    static int flag = 0;
    if(flag == 1) {
        return NULL;
    }
    char* ptrReturn = ptr;
    for(int j = 0; ptr != '\0'; j++) {
        for(int i=0 ; filter[i] != '\0' ; i++) {
            if(ptr[j] == '\0') {
                flag = 1;
                return ptrReturn;
            }
            if( ptr[j] == filter[i]) {
                ptr[j] = '\0';
                ptr+=j+1;
                return ptrReturn;
            }
        }
    }
    return NULL;
}

int _tmain(int argc, _TCHAR* argv[])
{
    char str[200] = "This,is my,string.test";
    char *ppt = mystrtok(str,", .");
    while(ppt != NULL ) {
        cout<< ppt << endl;
        ppt = mystrtok(NULL,", ."); 
    }
    return 0;
}

3voto

Pour ceux qui ont encore du mal à comprendre ceci strtok() Jetez un coup d'œil à cette fonction exemple de pythontutor il s'agit d'un excellent outil pour visualiser votre code C (ou C++, Python ...).

Au cas où le lien serait rompu, collez-le :

#include <stdio.h>
#include <string.h>

int main()
{
    char s[] = "Hello, my name is? Matthew! Hey.";
    char* p;
    for (char *p = strtok(s," ,?!."); p != NULL; p = strtok(NULL, " ,?!.")) {
      puts(p);
    }
    return 0;
}

Les crédits vont à Anders K.

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