【问题标题】:My function manipulating std::string's produces unexpected results我的函数处理 std::string 会产生意想不到的结果
【发布时间】:2015-02-12 20:12:09
【问题描述】:

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

#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 MessageBoxs 在代码运行时出现,第一个带有文本“成功运行”,然后另一个带有文本“此字符串需要修复”。我的预期是第二个MessageBox 出现“此字符串已修复”文本。

【问题讨论】:

  • 如果替换相同,这将挂起。
  • 您正在传递字符串按值
  • @Joachim Pileborg 谢谢,我不敢相信我错过了。如果您将其添加为答案,我会接受并投票。

标签: c++ string winapi stdstring


【解决方案1】:

发布的代码有两个问题:

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

第一个问题特别讨厌,因为它似乎经常起作用。但是,它仍然是未定义的行为,需要解决(通过使用 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,将第一个参数替换为对非常量的引用,并对所有出现的output(减号)使用input最后的return 声明)。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 虽然这确实解决了原始来源的一个问题,但它并没有解决所提出的问题。此外,仅代码的答案通常没有用。通常情况下,重要的不是什么,而是为什么
    • 另外,当参数包含嵌入的 NUL 字符时,您正在使用 std::string::find 重载,该重载将停止工作。没有明显的原因,因为有些重载采用 std::string (通过引用 const 和值),具有其他相同的签名。如果这还不够,您对replace 的调用会为第二个参数传递错误的参数。不知道,为什么这得到了赞成票,或者被选为接受的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-10-04
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    相关资源
    最近更新 更多