2011-01-14 70 views
4

考虑使用的strtok分割字符串madddy下面的代码片段。试图了解的strtok

char* str = (char*) malloc(sizeof("Madddy")); 
strcpy(str,"Madddy"); 

char* tmp = strtok(str,"d"); 
std::cout<<tmp; 

do 
{ 
    std::cout<<tmp; 
    tmp=strtok(NULL, "dddy"); 
}while(tmp!=NULL); 

它工作正常,输出是马。但通过修改strtok到以下,

tmp=strtok(NULL, "ay"); 

输出变成Madd。那么,strtok究竟是如何工作的?我有这个问题,因为我预料的strtok把每一个那就是在分隔符字符串被视为一个分隔符。但在某些情况下,它正在这样做,但在少数情况下,它会带来意想不到的结果。有谁能帮我理解这一点吗?

+6

老实说,我认为这样做的正确方法是完全停止使用`strtok`。这是一个难以使用,难以调试的功能,根本没有线程安全保证。你最好使用`string :: find`和`string :: substr`的​​组合来完成解析。 – templatetypedef 2011-01-14 02:31:54

+0

或`boost :: token_iterator` – 2011-01-14 02:42:30

+0

我愿意重复这个重要性和重点,尤其是因为您使用的是C++而不是C。另外,您可能需要查看boost :: tokenize。 – 2011-01-14 02:42:57

回答

1

看来你忘了,你必须通过分隔符“d”调用strtok的第一次(退出循环)。

的strtok的是工作的罚款。你应该有一个参考here

对于第二个示例(strtok("ay")):

首先,您拨打的strtok(STR, “d”)。它会寻找第一个“d”,并分开你的字符串。具体来说,它设置tmp =“Ma”,并且str =“ddy”(删除第一个“d”)。

然后,你调用strtok(str,“ay”)。它会在str中查找“a”,但由于您的字符串现在只是“ddy”,因此不会发生匹配。然后它会寻找一个“y”。所以str =“dd”和tmp =“”。

如您所见,它会打印出“Madd”。

10

“试图了解strtok的” 祝你好运!

不管怎么说,我们在2011年Tokenise正确:

std::string str("abc:def"); 
char split_char = ':'; 
std::istringstream split(str); 
std::vector<std::string> token; 

for (std::string each; std::getline(split, each, split_char); token.push_back(each)); 

:d

3

摩登原始人可能使用strtok()。它早于多线程环境并打败(修改)源字符串。

NULL要求第一个参数,它继续分析最后一个字符串。这个功能很方便,但即使在一天中也有点不同寻常。

2

其实你的代码是错误的,难怪你会得到意想不到的结果:

char* str = (char*) malloc(sizeof("Madddy")); 

应该

char* str = (char*) malloc(strlen("Madddy") + 1); 
0

,我向另一个问题有关functions causing security problems/bad practise functions and the c standard library启发的问题。

引述从那里给我的答案是:

strtok() 功能一个常见的错误是假设解析 串保持不变,而它 实际上取代了分隔 字符与'\0'

另外,使用strtok()可以使 后续调用它,直到整个字符串被标记为 。有些 库实现存储在 全局变量 strtok()的内部状态,这可能导致一些 讨厌suprises,如果strtok()是 在 同时从多个线程调用。

正如您所标记的问题C++,用别的东西!如果你想使用C,我建议实现自己的标记生成器,在一个安全的方式工作。

0

由于您将标记更改为C而不是C++,因此我重写了使用printf的函数,以便您可以看到发生了什么。 Hoang是对的。你看到正确的输出,但我认为你在同一行上打印所有东西,所以你对输出感到困惑。看看Hoang的答案,他解释了正确的事情。另外,正如其他人所指出的,strtok破坏了输入字符串,所以你必须小心 - 而且它不是线程安全的。但是如果你需要一个快速的脏标记器,它可以工作。另外,我更改了代码以正确使用strlen,而不是Anders正确指出的sizeof。

这里是你的代码修改为多个C类:

char* str = (char*) malloc(strlen("Madddy") + 1); 
strcpy(str,"Madddy"); 

char* tmp = strtok(str,"d"); 
printf ("first token: %s\n", tmp); 

do 
{ 
    tmp=strtok(NULL, "ay"); 
    if (tmp != NULL) { 
     printf ("next token: %s\n", tmp); 
    } 
} while(tmp != NULL);