用另一个字符串替换字符串的一部分

Tom*_*ese 171 c++ string replace substring std

在C++中是否可以用另一个字符串替换字符串的一部分?

基本上,我想这样做:

QString string("hello $name");
string.replace("$name", "Somename");
Run Code Online (Sandbox Code Playgroud)

但我想使用标准C++库.

Mic*_*zek 267

有一个函数可以在string(find)中找到一个子字符串,以及一个用另一个字符串(replace)替换字符串中特定范围的函数,所以你可以将它们组合起来得到你想要的效果:

bool replace(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = str.find(from);
    if(start_pos == std::string::npos)
        return false;
    str.replace(start_pos, from.length(), to);
    return true;
}

std::string string("hello $name");
replace(string, "$name", "Somename");
Run Code Online (Sandbox Code Playgroud)

在回应评论时,我认为replaceAll可能看起来像这样:

void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    if(from.empty())
        return;
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这仍然是2018年唯一的解决方案吗?如果是这样,并且任何C++委员会正在阅读此内容,请将其排除.这让人很难堪.split(string,string)和replace(string,string)请! (12认同)
  • @迈克尔:好的,我把我的投票变成了投票.解雇`const`是无视C++的最佳工具之一.[传递每个const参考应该是函数参数的默认模式.](http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c/21​​39254#2139254) (FTR,没有`const`,你甚至无法将字符串文字传递给你的函数,因为你不能将临时文本绑定到非`constst`引用.所以函数甚至不会写它所写的内容.) (10认同)
  • @sbi修正了,虽然你可以把它作为建议而不是攻击 - 但它根本没有发生在我身上,我很少想到使用`const`如果我写了这样的实用工具方法我只会称之为我知道更换是有效的 (9认同)
  • 如果原始字符串有更多的"$ name"实例并且我想要替换所有这些实例,我将如何修复它. (2认同)
  • 为什么不按 `const` 引用传递 `from` 和 `to`?如果`from` 不存在,你的功能是什么?'-1' 来自我。 (2认同)

Tom*_*Tom 83

使用C++ 11,您可以这样使用std::regex:

    #include <regex>
    ...
    std::string string("hello $name");
    string = std::regex_replace(string, std::regex("\\$name"), "Somename");
Run Code Online (Sandbox Code Playgroud)

转义转义字符需要双反斜杠.

  • 原始字符串允许写"R"(\ $ name)"`而不是`"\\ $ name"`. (5认同)
  • 如果不考虑 std::regex 的构建时间,这会比查找/替换慢多少? (5认同)
  • 你是对的。碰巧 QString 提供了一个接受 QRexExp 的替换方法,允许使用 Qt 自己的东西。但我认为当前的答案可以通过用“string.toStdString()”替换“string”来纠正。 (2认同)

S.C*_*sen 18

std::string有一种replace方法,就是你要找的东西?

你可以尝试:

s.replace(s.find("$name"), sizeof("$name") - 1, "Somename");
Run Code Online (Sandbox Code Playgroud)

我没有尝试过自己,只需阅读文档find()replace().

  • 第二个参数应该是"$ name"的长度(而不是"Somename"的长度),不应该吗? (4认同)
  • 如果 `s` 字符串中多次出现 `"$name"`,则此方法将不起作用。 (3认同)
  • 从我所看到的 std::string 替换方法并没有像我想要的那样使用两个字符串。 (2认同)
  • 这对我不起作用。sizeof应该替换为string(“ Somename”)。size()-1 (2认同)

Cza*_*zak 8

要返回新字符串,请使用以下命令:

std::string ReplaceString(std::string subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
    return subject;
}
Run Code Online (Sandbox Code Playgroud)

如果您需要性能,这里是一个修改输入字符串的优化函数,它不会创建字符串的副本:

void ReplaceStringInPlace(std::string& subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
}
Run Code Online (Sandbox Code Playgroud)

测试:

std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;

std::cout << "ReplaceString() return value: " 
          << ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not modified: " 
          << input << std::endl;

ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: " 
          << input << std::endl;
Run Code Online (Sandbox Code Playgroud)

输出:

Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
Run Code Online (Sandbox Code Playgroud)


小智 6

是的,你可以这样做,但是你必须找到带有字符串的find()成员的第一个字符串的位置,然后用它的replace()成员替换它.

string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
   s.replace( pos, 5, "somename" );   // 5 = length( $name )
}
Run Code Online (Sandbox Code Playgroud)

如果您打算使用标准库,那么您应该真正掌握"C++标准库 "一书副本,该书 很好地涵盖了所有这些内容.


Gal*_*lik 6

我一般用这个:

std::string& replace(std::string& s, const std::string& from, const std::string& to)
{
    if(!from.empty())
        for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
            s.replace(pos, from.size(), to);
    return s;
}
Run Code Online (Sandbox Code Playgroud)

它反复调用std::string::find()以定位搜索字符串的其他匹配项,直到std::string::find()找不到任何内容。因为std::string::find()返回匹配的位置,所以我们不存在使迭代器失效的问题。


max*_*ime 6

这听起来像是一个选择

string.replace(string.find("%s"), string("%s").size(), "Something");

您可以将其包装在一个函数中,但这种单行解决方案听起来可以接受。问题是这只会改变第一次出现,您可能想要循环它,但它也允许您使用相同的标记 ( %s)在此字符串中插入多个变量

  • 喜欢样式但发现不同的字符串令人困惑 ^^ `str.replace(str.find("%s"), string("%s").size(), "Something");` (2认同)

cam*_*mp0 5

升压解决方案怎么样:

boost::replace_all(value, "token1", "token2");
Run Code Online (Sandbox Code Playgroud)