C中的strtok函数如何工作?

我找到了这个解释strtok函数的示例程序:

 #include  #include  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; } 

但是,我不知道这是如何工作的。

怎么可能pch = strtok (NULL, " ,.-"); 返回一个新令牌。 我的意思是,我们用NULL调用strtok 。 这对我来说没有多大意义。

关于strtok两点需要了解。 如前所述,它“维持内部状态”。 此外,它会弄乱你喂它的字符串 。 本质上,它会在找到您提供的令牌时写入'\0' ,并返回指向字符串开头的指针。 在内部,它维护最后一个令牌的位置; 下次你打电话,它从那里开始。

重要的推论是你不能在const char* "hello world";上使用strtok const char* "hello world"; 字符串的类型,因为在修改const char* string的内容时将获得访问冲突。

关于strtok的“好”的事情是它实际上并不复制字符串 – 所以你不需要管理额外的内存分配等。但除非你理解上述内容,否则你将无法正确使用它。

示例 – 如果您有“this,is,a,string”,对strtok连续调用将生成如下指针( ^是返回的值)。 请注意, '\0'被添加到找到标记的位置; 这意味着修改了源字符串:

 this , is , a , string \0 this,is,a,string this \0 is , a , string \0 this ^ this \0 is \0 a , string \0 is ^ this \0 is \0 a \0 string \0 a ^ this \0 is \0 a \0 string \0 string ^ 

希望它有意义。

strtok保持内部状态。 当您使用非NULL调用它时,它会重新初始化自己以使用您提供的字符串。 当你用NULL调用它时,它使用该字符串,以及它当前获得的任何其他状态返回下一个标记。

由于strtok工作方式,如果您正在编写multithreading应用程序,则需要确保链接到C运行时的multithreading版本。 这将确保每个线程获得strtok自己的内部状态。

strtok()函数在调用之间存储数据。 当您使用NULL指针调用它时,它使用该数据。

来自http://www.cplusplus.com/reference/cstring/strtok/ :

找到最后一个令牌的点由内部保留在下一次调用时使用的函数(不需要特定的库实现来避免数据争用)。

strtok函数将数据存储在内部静态变量中,该变量在所有线程之间共享。

对于线程安全,您应该使用strtok_r

来自http://www.opensource.apple.com/source/Libc/Libc-167/string.subproj/strtok.c

看看static char *last;

 char * strtok(s, delim) register char *s; register const char *delim; { register char *spanp; register int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). */ cont: c = *s++; for (spanp = (char *)delim; (sc = *spanp++) != 0;) { if (c == sc) goto cont; } if (c == 0) { /* no non-delimiter characters */ last = NULL; return (NULL); } tok = s - 1; /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL; we stop if we see that, too. */ for (;;) { c = *s++; spanp = (char *)delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ }