我想删除字符串中两个相同字符之间的所有字符。我的函数接受一个字符串(通过引用)和参数中的char。
假设我使用std::string
这样的变量:"hah haaah hah hello!"
作为第一个参数而char [{1}}作为第二个参数,这样的事情应该发生:'h'
。如您所见,两个"hah haaah hah hello!" ===> "hh hh hh hello"
个字符之间的每个字符都已被删除。我如何实现这样的目标?
我试过使用迭代器并最终得到了这个:
h
首先,我搜索第一次出现void delete_chars_between(std::string& line, char del)
{
std::string::iterator itr_from = std::find(line.begin(), line.end(), del);
std::string::iterator itr_to = std::find(itr_from + 1, line.end(), del);
while (true) {
if(itr_to != line.end())
line.erase(itr_from + 1, itr_to);
itr_from = std::find(itr_to, line.end(), del);
if (itr_from == line.end())
break;
itr_to = std::find(itr_from + 1, line.end(), del);
if (itr_to == line.end())
break;
}
}
,我将迭代器存储到del
中的位置。之后,我搜索第二次itr_from
。最后,如果del
有效,我会运行一个while循环,首先擦除某个范围内的字符。我一遍又一遍地重复这一点,而我的迭代器不等于itr_to
。
但由于某些原因,此代码无法正常运行。它有时会删除空格,甚至不会触及我打算删除的字符。
感谢您的帮助。
答案 0 :(得分:3)
std::string
迭代器失效,因此在调用itr_from
之后使用itr_to
和line.erase
是未定义的行为。
您需要使用erase
的返回值:
while (true) {
if(itr_to != line.end())
itr_to = line.erase(itr_from + 1, itr_to);
itr_from = std::find(itr_to, line.end(), del);
if (itr_from == line.end())
break;
itr_to = std::find(itr_from + 1, line.end(), del);
if (itr_to == line.end())
break;
}
答案 1 :(得分:0)
为避免未定义的行为,您应在调用erase
之前重置两个迭代器。
查看预期输出,似乎不应使用结束分隔符来启动另一个间隔:
"hh hh hh hello" not "hhhhhhhello"
^ ^ ^
所以,这是我的建议:
void delete_chars_between(std::string& line, char del)
{
std::string::iterator itr_from = std::find(line.begin(), line.end(), del);
// I don't want to pass an iterator to two past the last element
if ( itr_from == line.end() )
return;
std::string::iterator itr_to = std::find(itr_from + 1, line.end(), del);
// ^^^^
while ( itr_to != line.end() )
{
itr_to = line.erase(itr_from + 1, itr_to);
itr_from = std::find(itr_to + 1, line.end(), del);
// to start another couple ^^^^
if (itr_from == line.end())
break;
itr_to = std::find(itr_from + 1, line.end(), del);
}
}
直播示例HERE。