2010-03-27 88 views
3

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

它与分配字符串的区域有什么关系? (据我所知,这是一个只读区域)。

在此先感谢

例如:

//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; 

回答

6

在第一种情况下,您将字符串文字传递给strtok()。由于strtok()修改了这个字符串,并且由于字符串文字不能合法地修改,最终会导致未定义的行为。在第二种情况下,编译器将字符串复制到数组中。数组内容可以修改,所以这段代码是可以的。

+0

我明白了。没有意识到该功能的这种行为。 谢谢 – bks 2010-03-27 15:41:40

2

strtok修改它的第一个参数。

在你的情况1中,参数strtok是一个字符串literal,它不能被修改,因此strtok失败。但在情况2中,参数是可修改的char数组,其中strtok修改并分解为更小的字符串。

+0

我明白了。好吧,你和其他人非常有帮助,谢谢。 – bks 2010-03-27 15:43:37

0

这里是一个代码,所有的方面都应该是理所当然的。

  • 获得字符指针使用的strdup在strtok_r使用字符指针使用strtok_r是线程安全的
  • 自由结果的strdup时被cuz它做
  • 使用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

    你的回答里有很多不必要的故事,背包,当你开始编程等等时,你可能会尽量减少这个。你也可以拼写和大写。我知道你喜欢你正在阅读的书,但是使用它提供的头文件使得你的代码很难运行,你可能更喜欢标准包含。最后但并非最不重要的,如果你要回答一个5岁的问题,不要说你没有测试过你的代码。它等了5年,它可以等待一段时间让你测试。 – 2015-04-11 22:49:23

    +0

    thx为您的批评。删除无用的故事,测试该程序,添加所需的标题。 – had 2015-04-12 10:35:06