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 */ }