C++ c++;标记化标准字符串

C++ c++;标记化标准字符串,c++,tokenize,strtok,C++,Tokenize,Strtok,可能重复: 您好,我想知道如何使用strtok标记std字符串 string line = "hello, world, bye"; char * pch = strtok(line.c_str(),","); 我得到以下错误 error: invalid conversion from ‘const char*’ to ‘char*’ error: initializing argument 1 of ‘char* strtok(char*, const char*)’ 我正在寻

可能重复:

您好,我想知道如何使用strtok标记std字符串

string line = "hello, world, bye";    
char * pch = strtok(line.c_str(),",");
我得到以下错误

error: invalid conversion from ‘const char*’ to ‘char*’
error: initializing argument 1 of ‘char* strtok(char*, const char*)’
我正在寻找一种快速简便的方法,因为我认为这不需要太多时间

std::string::size_type pos = line.find_first_of(',');
std::string token = line.substr(0, pos);

要查找下一个令牌,请重复
find_first_of
,但从
pos+1
开始。您可以通过执行
&*line.begin()
来使用
strtok
,以获取指向
char
缓冲区的非常量指针。我通常喜欢在C++中使用.

<代码> Strutok> /Cord>是一个相当怪异的、邪恶的函数,修改它的参数。这意味着您不能直接在
std::string
的内容上使用它,因为无法从该类获取指向可变的、以零结尾的字符数组的指针

您可以处理字符串数据的副本:

std::vector<char> buffer(line.c_str(), line.c_str()+line.size()+1);
char * pch = strtok(&buffer[0], ",");
或者更直接地查找逗号:

std::string token(line, 0, line.find(','));

我总是使用
getline
来完成这些任务

istringstream is(line);
string part;
while (getline(is, part, ','))
  cout << part << endl;
istringstream为(行);
弦部;
while(getline(is,part,,))

我是否认为通过丢弃字符串内部指针上的常量,您可以允许strtok修改字符串的内部指针-非常脏。这是一个糟糕的想法。它将把
std::string
置于未定义状态。您不应该使用C字符串函数修改
std::string
。@japreis它怎么可能出错?通过迭代器修改字符串中的字符并没有错,并且C++字符串是,并且保证在C++ 11中是连续的,空的终止。@ ScCeNCW:不能保证字符串的内部表示为零终止;它可能使用写时复制语义,在这种情况下,subversing
const
可能会更改字符串的其他副本。可以(也可以不可以)证明您所做的工作对于任何一致性实现都是定义良好的,但即使可以,我也不想测试这样的一致性边缘情况。@MikeSeymour内部缓冲区在C++11()中保证以null结尾。不过,你提出了一个有趣的观点,那就是“一写即用”。我猜在这样的实现中,取消对迭代器的引用会触发副本,或者当
strtok
写入缓冲区时,某种内存保护会触发副本。有没有真正实现CoW的实现?我以前见过这种问题。可能重复。有了这个,就必须有另一个变量来跟踪pos1和pos2。否则,您将使用从0到新pos的子字符串,而不是从pos1到pos2。
istringstream is(line);
string part;
while (getline(is, part, ','))
  cout << part << endl;