strtok不接受:char *str

5

当使用char *str作为第一个参数(而不是分隔符字符串)时,strtok将无法正确工作。

这是否与在该表示法中分配字符串的区域有关?(据我所知,这是一个只读区域)。

提前感谢您的回答。

示例:

//char* str ="- This, a sample string.";   // <---doesn't work
char str[] ="- This, a sample string.";   // <---works
char delims[] = " ";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,delims);
while (pch != NULL)
{
  printf ("%s\n",pch);
  pch = strtok (NULL, delims);
}
return 0;
3个回答

7
在第一种情况下,您向strtok()传递一个字符串字面量。由于strtok()会修改此字符串,而字符串字面量不能合法地被修改,因此您最终会得到未定义的行为。在第二种情况下,编译器将字符串复制到数组中。数组内容可以被修改,因此这段代码是正确的。

我知道了。我不知道函数还有这个行为。 谢谢。 - bks

2

strtok 修改了它的第一个参数。

在你的第一种情况中,strtok 的参数是一个字符串 literal,它不能被修改,因此 strtok 失败了。但在第二种情况下,参数是一个可修改的 char 数组,strtok 会修改它并将其分解成较小的字符串。


我明白了。嗯,你和另一个人都非常有帮助,谢谢。 - bks

0

这里有一段代码,所有方面都应该被关注。

  • 获取字符指针
  • 使用strdup来在strtok_r中使用字符指针
  • 使用strtok_r使其线程安全
  • 完成后释放结果strdup,因为它内部使用了malloc

如果我忘记了什么,请给我提示。

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

#define WHITE " \t\n" // white space, tab and newline for tokenizing arguments
#define MAXARGC 50 // max number of arguments in buf 

void handlecommand(int argc, char *argv[])
{
    // do some handle code, in this example, just print the arguments
    for(int i = 0; i < argc; i++)
        printf("argv[%d]='%s'\n", i, argv[i]);
}

void parsecommand(char * cmdstr)
{
    char *cmdstrdup = strdup(cmdstr);
    if(cmdstrdup == NULL)
      //insuficient memory, do some errorhandling. 
      return; 
    char *saveptr;
    char *ptr;
    char *argv[MAXARGC]; 
    int argc;

    if((ptr = strtok_r(cmdstrdup, WHITE, &saveptr)) == NULL)
    {
        printf("%s\n", "no args given");
        return;
    } 

    argv[argc = 0] = cmdstrdup;
    while(ptr != NULL) {
        ptr = strtok_r(NULL, WHITE, &saveptr);
        if(++argc >= MAXARGC-1) // -1 for room for NULL at the end
            break;
        argv[argc] = ptr;
    }

    // handle command before free
    handlecommand(argc, argv);

    // free cmdstrdup, cuz strdup does malloc inside
    free(cmdstrdup);
}

int main(int argc, char const *argv[])
{
    parsecommand("command arg1 arg2 arg3\targ4\narg5 arg6  arg7");
    return 0;
}

结果

argv[0]='command'
argv[1]='arg1'
argv[2]='arg2'
argv[3]='arg3'
argv[4]='arg4'
argv[5]='arg5'
argv[6]='arg6'
argv[7]='arg7'

2
你的回答里有很多不必要的故事,比如背包、你开始编程的时候等等,你可以尽量减少这些。你还可以注意一下拼写和大小写。我知道你喜欢你正在阅读的书,但是使用它提供的头文件会使你的代码示例难以直接运行,你可能更喜欢标准的包含文件。最后,如果你要回答一个五岁孩子的问题,不要说你没有测试过你的代码。它已经等了五年,它可以再等一段时间让你测试。 - Retired Ninja
谢谢您的批评。已删除无用的故事,测试了程序,并添加了所需的头文件。 - had

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