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

Posted

技术标签:

【中文标题】如何用另一个字符串替换一个字符串的所有实例?【英文标题】:How do I replace all instances of a string with another string? 【发布时间】:2011-03-17 17:58:56 【问题描述】:

我在另一个堆栈问题上找到了这个:

//http://***.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'
    

和我的方法:

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;

对于这个输入:

cout << convert_FANN_array_to_binary("1 1 -1 -1 1 1 ");

现在,输出应该是“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()

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

【问题讨论】:

在这个特定的例子中,似乎另一种解决方案更合适——即根本不使用字符串操作,使用整数/布尔数组。 它必须是字符串,因为我们是从一个 ascii 文件中读取的。 如果您遵循@Konrad 的建议,您可以使用std::replace 替换值。您从 ascii 文件中读取的事实没有理由不将您的数字表示为整数。 然后转换它们。程序的流程总是一样的:1.读取输入,2.转换为适当的格式,3.应用计算,4.转换为输出格式,5.输出。你正试图跳过第 (2) 步,让你的生活变得不必要地艰难。字符串很少适合文本以外的任何内容。 同意。我们需要在我们的库中重新编写一个方法,然后才能读取序列化文件。我们会到达那里。 【参考方案1】:

完整代码:

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;

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

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();
    

测试:

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;

输出:

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

【讨论】:

替换字符串(字符串(“abc\dir\dir1”),字符串(“\\”),字符串(“\\\\”));没用 你应该实际检查search字符串是否为空,否则会出现死循环。【参考方案2】:

错误在str.replace(start_pos, end_pos, to);

来自http://www.cplusplus.com/reference/string/string/replace/的 std::string 文档

string& replace ( size_t pos1, size_t n1,   const string& str );

您使用的是结束位置,而函数需要一个长度。

所以改成:

while((start_pos = str.find(from, start_pos)) != std::string::npos) 
         str.replace(start_pos, from.length(), to);
         start_pos += to.length(); // ...

注意:未经测试。

【讨论】:

顺便说一句,我不赞成代码和样式,但这不是这里的问题。 有没有更好的方法来进行字符串替换?我真的很惊讶这不是 string.h 内置的东西......就像......说真的......高级语言都有它。 @NullVoxPopuli 我发现了你的问题:C++ 不是高级语言 @Sjoerd 如果您不同意代码和样式,您会建议什么替代方案? 在 C++11 中有一种方法 std::regex_replace(str, std::regex(from), to) @NullVoxPopuli【参考方案3】:

这将出现在我的“仅使用 Boost 库”答案列表中,但无论如何都会出现:

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

【讨论】:

The function 他正在寻找。【参考方案4】:

C++11 现在包含具有正则表达式功能的标头 &lt;regex&gt;。来自docs:

// 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;

当然,now you have two problems。

【讨论】:

【参考方案5】:

我发现之前的答案中给出的替换函数都在内部使用就地 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;

格雷格

【讨论】:

你可以通过在最后做str.swap(wsRet)而不是赋值来提高效率。这可以廉价地交换字符串的内容,而不是执行可能昂贵的复制。 @Blastfurnace,确实,谢谢你的提示!我测试过,效果很好。也会用它更新上面的示例代码。 我有一个与此非常相似的功能,您对性能的看法是正确的。当fromto 大小不同时,这可能会非常快。如果它们的大小相同,则通用的就地版本效果很好。 确实,例如,我使用一个专门的函数来替换单个字符。我想当长度不相等时,每次替换时围绕字符串的其余部分移动是导致延迟的原因。谢谢! 为什么没有 C++11 语法?对新手来说非常困惑,所有错误都会出现。【参考方案6】:

试试这个:

#include <string>

string replace_str(string & str, const string & from, const string & to)

  while(str.find(from) != string::npos)
    str.replace(str.find(from), from.length(), to);
  return str;

【讨论】:

如果to 包含from,此外观将永远不会终止。

以上是关于如何用另一个字符串替换一个字符串的所有实例?的主要内容,如果未能解决你的问题,请参考以下文章

Android - 如何用另一个字符串替换部分字符串?

如何用熊猫列中的另一个字符串替换子字符串[关闭]

如何用从一个数据帧到另一个数据帧的值替换字符串

如何用空格匹配、计数和替换字符串,但它们不是另一个字母字符串的子字符串?

如何用另一个数组值替换javascript中的数组值?

如何用包含空格的字符串替换列表中的项目?