我的函数操作std :: string' s会产生意外的结果

时间:2014-12-14 17:39:17

标签: c++ string winapi stdstring

我正在尝试创建一个函数来查找子字符串的所有实例,并用新字符串替换它,但它似乎不起作用。这是代码:

#include <string>
#include <windows.h>
void ReplaceSubstr(std::string mainstring, std::string substring1, std::string substring2)
{
    while (1)
    {
    int pos1 = mainstring.find (substring1);
    if (pos1 == -1)
        {
        return;
        }
    mainstring.erase(pos1, substring1.size());
    mainstring.insert(pos1, substring2);
    MessageBox (NULL, "successfully ran", NULL, NULL);
    }
}

int main()
{
    std::string target = "this string needs fixing";
    std::string bereplaced = "needs fixing";
    std::string replacement = "is fixed";
    ReplaceSubstr (target, bereplaced, replacement);
    MessageBox (NULL, target.c_str(), NULL, NULL);
    return 0;
}
运行代码时出现

2 MessageBox,第一个文本“成功运行”,然后另一个文本“此字符串需要修复”。我期望第二个MessageBox出现的文字是“此字符串已修复”。

2 个答案:

答案 0 :(得分:1)

发布的代码有两个问题:

  • 调用std::string::erase使所有迭代器无效,即成员函数返回后不再使用pos1(参见this answer)。
  • 您通过 value 传递参数,因此任何修改都只反映在本地临时副本中。

第一个问题特别令人讨厌,因为它似乎经常起作用。但是,它仍然是未定义的行为,需要解决(通过使用std::string::erase重载,返回有效的迭代器,或者通过调用std::string::replace)。

第二个问题也可以通过两种方式解决,或者通过引用传递第一个参数,或者通过返回一个新的字符串对象。

解决方案可能如下所示:

std::string ReplaceSubstr( const std::string& input, const std::string& pattern,
                                                     const std::string& replacement ) {
    std::string output{ input };
    auto pos = output.find( pattern );
    while ( pos != std::string::npos ) {
        output.replace( pos, pattern.size(), replacement );
        pos = output.find( pattern );
    }
    return output;
}

如果要在原地执行替换,只需将返回类型更改为void,将第一个参数替换为对非const的引用,并对所有出现的{input使用output {1}}(减去最后的return语句)。

答案 1 :(得分:0)

你可以通过以下方式轻松完成: -

 index = target.find(bereplaced.c_str(), index);
 if (index == string::npos) 
     //return or do something else

 target.replace(index, replacement.size(), replacement);