在C语言中,strtok和strtok_r有什么区别?

25

strtokstrtok_r在C语言中有何不同,我们应该在何时使用它们?


1
一个是可重入的,另一个不是。我记得手册上是这样说的。 - RedX
2
不是标准的C语言,而是Posix。Strtok()函数是一个错误工厂,它在CRT内部使用全局变量来跟踪字符串位置。因此,您不能同时在多个字符串上使用它。在线程中也存在风险,但大多数CRT都已解决了这个问题。 - Hans Passant
为了让你更加困惑,C11添加了strtok_s - Per Johansson
4个回答

28

strtok 的等效实现(通常是这样定义的):

char *strtok(char *str, const char *delim) {
    static char *save;
    return strtok_r(str, delim, &save);
}

通常情况下,您应该直接使用strtok_r而不是strtok,除非您需要使您的代码可移植到仅支持strtok的pre-POSIX-2001系统。


21
_r 版本的函数是可重入的:可以同时从多个线程调用它们,或在嵌套循环中调用,等等。可重入版本通常需要一个额外的参数,这个参数用于在调用之间存储状态,而不是使用全局变量。
非可重入版本通常使用全局状态,因此如果您从多个线程调用它们,则可能会引发未定义的行为。你的程序可能会崩溃,或者更糟。
根据 man pages (man 3 strtok):

strtok_r() 函数是 strtok() 的可重入版本。在每次调用时必须提供上下文指针 last。只要使用单独的上下文指针,strtok_r() 函数也可以用于将两个解析循环嵌套在一起。


有没有这样的_r函数列表,与我可能在不知情的情况下使用的原始函数相比?由于_r不是标准C,我不能只在*.h中使用grep查找它们。 - dargaud
@dargaud:它们确实在*.h文件中。这些函数不是“标准C”,但它们是POSIX标准的一部分。我能想到的另一个是strerror_r - Dietrich Epp

5

strtok 函数会保存一个静态指针以便在下一次调用时重复使用,当你将第一个参数设置为 NULL 时,无法同时解析两个字符串。

strtok_r 函数需要传递一个作为输出参数的指针(指向指针的指针),因此该函数没有静态指针。这意味着你可以在多个字符串之间自由移动。


0
根据文档,strtok_r()函数是strtok()的可重入版本。
char *strtok_r(char *s1, const char *s2, char **s3);

它从字符串s1中获取下一个标记,其中标记是由s2中的字符分隔的字符串。要从s1中获取第一个标记,需要使用strtok_r(),并将s1作为其第一个参数调用。通过使用空指针作为第一个参数调用strtok_r(),可以获得来自s1的剩余标记。分隔符字符串s2在每次调用时都可能不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接