strtok() 在 C99 中返回不正确的值?

strtok() returning incorrect value in C99?

我运行正在使用 std c99 的 32 位 linux 系统上。所以我有这个代码

char* tokPtr = strtok(expr, " ");
    while(tokPtr != NULL) {
            tokPtr = strtok(NULL, " ");
            puts(tokPtr);
            push(tokens, tokPtr);
    }

expr 是作为参数传入的 C 字符串,类似于“1 2 +”。我只是将 put 用于测试目的。但是,当我 运行 带有 --leak-check=full 标志的 valgrind 时,它为我在 puts 中为 strlen 提供了大小为 1 的无效读取,并以段错误结束。当我让 tokPtr = "1";并注释掉 strtok() 的东西,我 运行 valgrind 完全没有错误。我不知道为什么会这样,我真的需要一些帮助。谢谢

这里:

while(tokPtr != NULL) {
    tokPtr = strtok(NULL, " ");
    puts(tokPtr);

你应该检查是否 tokPtr == NULL 在你调用 之后,而不是之前。当 strtok() 最终执行 return NULL 时,您将始终使用此代码将 NULL 传递给 puts(),这就是您的问题。

您可以重新排序,然后更改为:

char* tokPtr = strtok(expr, " ");
while(tokPtr != NULL) {
    puts(tokPtr);
    push(tokens, tokPtr);
    tokPtr = strtok(NULL, " ");
}

还要记住,strtok() 修改了它使用的字符串和 return 指向该字符串的内部指针。你没有显示你的 push() 函数,但除非代码非常简单,并且你的 expr 数组总是比你的堆栈更持久,否则你可能 运行 会遇到将这些指针推入的问题它。为每个令牌 malloc() 一些内存并将 strtok() return 复制到其中,然后推送这些可能会更好。

我知道这已经得到解答,但正是出于这个原因,我建议在 for() 而不是 while() 中使用 strtok,因为它自然具​​有初始化程序、测试条件和迭代器。例如:

for( char* tokPtr = strtok(expr, " ");
     tokPtr != NULL;
     tokPtr = strtok(NULL, " ") )
{
    puts(tokPtr);
    push(tokens, tokPtr);
}