如何用另一个字符串替换字符串的所有实例?

Nul*_*uli 42 c++ string

我发现这是另一个堆栈问题:

//http://stackoverflow.com/questions/3418231/c-replace-part-of-a-string-with-another-string
//
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        size_t end_pos = start_pos + from.length();
        str.replace(start_pos, end_pos, to);
        start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
}
Run Code Online (Sandbox Code Playgroud)

和我的方法:

string convert_FANN_array_to_binary(string fann_array)
{
    string result = fann_array;
    cout << result << "\n";
    replaceAll(result, "-1 ", "0");
    cout << result << "\n";
    replaceAll(result, "1 ", "1");
    return result;
}
Run Code Online (Sandbox Code Playgroud)

其中,对于此输入:

cout << convert_FANN_array_to_binary("1 1 -1 -1 1 1 ");
Run Code Online (Sandbox Code Playgroud)

现在,输出应为"110011"

这是方法的输出:

1 1 -1 -1 1 1  // original
1 1 0 1  // replacing -1's with 0's
11 1  // result, as it was returned from convert_FANN_array_to_binary()
Run Code Online (Sandbox Code Playgroud)

我一直在查看replaceAll代码,而且,我真的不确定它为什么用一个0替换连续的-1,然后在最终结果中不返回任何0(和一些1).= \

Cza*_*zak 54

完整的代码:

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 changed: " 
          << 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 changed: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
Run Code Online (Sandbox Code Playgroud)

  • 你应该检查`search`字符串是否为空,否则会出现无限循环. (6认同)

Sjo*_*erd 19

这个bug就在 str.replace(start_pos, end_pos, to);

来自http://www.cplusplus.com/reference/string/string/replace/上的std :: string doc

string& replace ( size_t pos1, size_t n1,   const string& str );
Run Code Online (Sandbox Code Playgroud)

您正在使用结束位置,而该函数需要一个长度.

所以改为:

while((start_pos = str.find(from, start_pos)) != std::string::npos) {
         str.replace(start_pos, from.length(), to);
         start_pos += to.length(); // ...
}
Run Code Online (Sandbox Code Playgroud)

注意:未经测试.

  • 是否有更好的方法来进行字符串替换?我真的很惊讶这不是内置在string.h中的东西....比如...认真......更高级别的语言都有它. (54认同)
  • @NullVoxPopuli我发现了你的问题:C++不是更高级的语言 (4认同)
  • 在C ++ 11中,有一种方法std :: regex_replace(str,std :: regex(from),to)@NullVoxPopuli (2认同)

pho*_*oji 11

这将在我的"仅使用Boost库"答案列表中进行,但无论如何它仍然存在:

你考虑过Boost.String吗?它具有比标准库更多的功能,并且在功能重叠的地方,Boost.String在我看来具有更自然的语法.

  • [功能](http://www.boost.org/doc/libs/1_46_1/doc/html/boost/algorithm/replace_all.html)他正在寻找. (8认同)

Jhe*_*ico 8

C++ 11现在包含<regex>具有正则表达式功能的标头.来自文档:

// regex_replace example
#include <iostream>
#include <string>
#include <regex>
#include <iterator>

int main ()
{
  std::string s ("there is a subsequence in the string\n");
  std::regex e ("\\b(sub)([^ ]*)");   // matches words beginning by "sub"
  // using string/c-string (3) version:
  std::cout << std::regex_replace (s,e,"sub-$2");
  std::cout << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当然,现在你有两个问题.


gre*_*gko 6

我在前面的答案中找到了替换函数,所有函数都在内部使用就地调用str.replace(),当使用大约2 MB长度的字符串时非常慢.具体来说,我调用了像ReplaceAll(str,"\ r","")这样的东西,并且在我的特定设备上,文本文件包含很多换行符,大约需要27秒.然后,我将其替换为仅在新副本中连接子字符串的函数,并且仅用了大约1秒钟.这是我的ReplaceAll()版本:

void replaceAll(string& str, const string& from, const string& to) {
    if(from.empty())
        return;
    string wsRet;
    wsRet.reserve(str.length());
    size_t start_pos = 0, pos;
    while((pos = str.find(from, start_pos)) != string::npos) {
        wsRet += str.substr(start_pos, pos - start_pos);
        wsRet += to;
        pos += from.length();
        start_pos = pos;
    }
    wsRet += str.substr(start_pos);
    str.swap(wsRet); // faster than str = wsRet;
}
Run Code Online (Sandbox Code Playgroud)

格雷格

  • 你可以通过在末尾执行`str.swap(wsRet)`而不是赋值来提高效率.这可以便宜地交换字符串的内容,而不是执行可能昂贵的副本. (4认同)