在字符串中的定界符之间删除字符

Deleting chars between a delimiter in a string

本文关键字:之间 删除 字符 定界符 字符串      更新时间:2023-10-16

我想删除字符串中两个相同字符之间的所有字符。我的函数在其参数中采用字符串(通过引用)和一个字符。

假设我使用这样的 std::string变量: "hah haaah hah hello!"作为第一个参数,而char '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的第二次出现。最后,我运行了一段段循环,该循环首先要擦除特定范围内的字符,如果itr_to有效。当我的迭代器不等于line.end()时,我一遍又一遍地重复。

但是由于某种原因,此代码无法正常工作。有时它会删除空格,甚至不会触摸我要删除的字符。

感谢您的帮助。

std::string迭代器均被所有修改字符串长度的操作无效,因此在呼叫line.erase之后,使用itr_fromitr_to是不确定的行为。

您需要使用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;
}

要避免不确定的行为,您应该在调用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);
    }
}

在这里实时示例。