2011-10-01 86 views
0

当我使用的strtok来标记一个C++字符串,它发生混乱的问题,请参阅下面的简单代码:C++的strtok在函数改变原始字符串值作为参数

void a(string s){ 
    strtok((char*)s.c_str(), " "); 
} 
int main(){ 
    string s; 
    s = "world hello"; 
    a(s); 
    cout<<s<<endl; 
    return 0; 
} 

程序输出“世界”。 不应该输出“世界你好”吗?因为我将字符串作为值参数传递给函数a,strtok不应该修改原始的字符... 任何人都可以解释这个技巧。 谢谢。

+1

不要这样做,你要求的内存腐败问题。 是的,strtok会改变它的输入。 http://www.cplusplus.com/reference/clibrary/cstring/strtok/ –

回答

0

问题是(char*)s.c_str(),您将强制转换并修改string内容的方式,您不应该这样做。虽然原始s不应该被修改,但我记得你可能已经被一个聪明的优化打击,希望你按规则玩。例如,一个COW实施string将恰好显示该行为。

+0

thx。顺便说一句,你知道如何安全和高效地将C++字符串转换为char *,所以我可以在strtok中使用char *而不会出现问题? – stackunderflow

+0

@zwx:如果你打算修改'char *',那么你需要复制它。 –

0

c_str()返回const指针,这是向编译器承诺所指向的内容不会被修改的承诺。然后你打电话给strtok修改它。

当你对编译器说谎时,你会受到惩罚。

+0

一个'std :: string'对空值没有问题。 –

0

这就是strtok()的工作方式。它使用第一个参数作为缓冲区。通过将其转换为char *,您允许它修改字符串。 strtok()不知道最初的std :: string。它还将字符串指针存储在一个静态变量中,这就是为什么您必须在下一次用空指针调用它才能继续解析相同的字符串。

顺便说一句,在C++中,你应该使用std :: istringstream来代替。它不使用内部静态变量,它不是线程安全的。你可以直接将参数提取到int,double等,就像我们用cin做的那样。 std :: ostringstring替换sprintf()。

+0

thx,我会试试看 – stackunderflow