用另一个子字符串 C++ 替换子字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4643512/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:01:50  来源:igfitidea点击:

Replace substring with another substring C++

c++stringreplacesubstring

提问by Steveng

How could I replace a substring in a string with another substring in C++, what functions could I use?

如何用 C++ 中的另一个子字符串替换字符串中的子字符串,我可以使用哪些函数?

eg: string test = "abc def abc def";
test.replace("abc", "hij").replace("def", "klm"); //replace occurrence of abc and def with other substring

回答by templatetypedef

There is no one built-in function in C++ to do this. If you'd like to replace all instances of one substring with another, you can do so by intermixing calls to string::findand string::replace. For example:

C++ 中没有一个内置函数可以做到这一点。如果您想用另一个替换一个子字符串的所有实例,您可以通过混合调用string::find和 来实现string::replace。例如:

size_t index = 0;
while (true) {
     /* Locate the substring to replace. */
     index = str.find("abc", index);
     if (index == std::string::npos) break;

     /* Make the replacement. */
     str.replace(index, 3, "def");

     /* Advance index forward so the next iteration doesn't pick it up as well. */
     index += 3;
}

In the last line of this code, I've incremented indexby the length of the string that's been inserted into the string. In this particular example - replacing "abc"with "def"- this is not actually necessary. However, in a more general setting, it is important to skip over the string that's just been replaced. For example, if you want to replace "abc"with "abcabc", without skipping over the newly-replaced string segment, this code would continuously replace parts of the newly-replaced strings until memory was exhausted. Independently, it might be slightly faster to skip past those new characters anyway, since doing so saves some time and effort by the string::findfunction.

在这段代码的最后一行中,我增加index了插入字符串的字符串长度。在这个特定的例子中 - 替换"abc""def"- 这实际上不是必需的。但是,在更一般的设置中,跳过刚刚被替换的字符串很重要。例如,如果要替换"abc""abcabc",而不跳过新替换的字符串段,则此代码将不断替换新替换的字符串的一部分,直到内存耗尽。独立地,无论如何跳过这些新字符可能会稍微快一点,因为这样做可以节省string::find函数的一些时间和精力。

Hope this helps!

希望这可以帮助!

回答by Oleg Svechkarenko

Boost String Algorithms Libraryway:

Boost字符串算法库方式:

#include <boost/algorithm/string/replace.hpp>

{ // 1. 
  string test = "abc def abc def";
  boost::replace_all(test, "abc", "hij");
  boost::replace_all(test, "def", "klm");
}


{ // 2.
  string test = boost::replace_all_copy
  (  boost::replace_all_copy<string>("abc def abc def", "abc", "hij")
  ,  "def"
  ,  "klm"
  );
}

回答by Jingguo Yao

In c++11, you can use std::regex_replace:

c++11 中,您可以使用std::regex_replace

#include <string>
#include <regex>

std::string test = "abc def abc def";
test = std::regex_replace(test, std::regex("def"), "klm");

回答by rotmax

I think all solutions will fail if the length of the replacing string is different from the length of the string to be replaced. (search for "abc" and replace by "xxxxxx") A general approach might be:

如果替换字符串的长度与要替换的字符串长度不同,我认为所有解决方案都会失败。(搜索“abc”并替换为“xxxxxx”)一般方法可能是:

void replaceAll( string &s, const string &search, const string &replace ) {
    for( size_t pos = 0; ; pos += replace.length() ) {
        // Locate the substring to replace
        pos = s.find( search, pos );
        if( pos == string::npos ) break;
        // Replace by erasing and inserting
        s.erase( pos, search.length() );
        s.insert( pos, replace );
    }
}

回答by Jeff Zacher

str.replace(str.find(str2),str2.length(),str3);

Where

在哪里

  • stris the base string
  • str2is the sub string to find
  • str3is the replacement substring
  • str是基本字符串
  • str2是要查找的子字符串
  • str3是替换子串

回答by Czarek Tomczak

Replacing substrings should not be that hard.

替换子字符串不应该那么难。

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

If you need performance, here is an optimized function that modifies the input string, it does not create a copy of the string:

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

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

Tests:

测试:

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;

Output:

输出:

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

回答by Michael Burr

using std::string;

string string_replace( string src, string const& target, string const& repl)
{
    // handle error situations/trivial cases

    if (target.length() == 0) {
        // searching for a match to the empty string will result in 
        //  an infinite loop
        //  it might make sense to throw an exception for this case
        return src;
    }

    if (src.length() == 0) {
        return src;  // nothing to match against
    }

    size_t idx = 0;

    for (;;) {
        idx = src.find( target, idx);
        if (idx == string::npos)  break;

        src.replace( idx, target.length(), repl);
        idx += repl.length();
    }

    return src;
}

Since it's not a member of the stringclass, it doesn't allow quite as nice a syntax as in your example, but the following will do the equivalent:

由于它不是string类的成员,因此它不允许使用像您的示例中那样好的语法,但以下将执行等效操作:

test = string_replace( string_replace( test, "abc", "hij"), "def", "klm")

回答by ch0kee

If you are sure that the required substring is present in the string, then this will replace the first occurence of "abc"to "hij"

如果您确定字符串中存在所需的子字符串,则这将替换第一次出现的"abc"to"hij"

test.replace( test.find("abc"), 3, "hij");

It will crash if you dont have "abc" in test, so use it with care.

如果您在测试中没有“abc”,它会崩溃,因此请谨慎使用。

回答by Neoh

Generalizing on rotmax's answer, here is a full solution to search & replace all instances in a string. If both substrings are of different size, the substring is replaced using string::erase and string::insert., otherwise the faster string::replace is used.

概括 rotmax 的答案,这里有一个完整的解决方案来搜索和替换字符串中的所有实例。如果两个子串的大小不同,则使用 string::erase 和 string::insert. 替换子串,否则使用更快的 string::replace。

void FindReplace(string& line, string& oldString, string& newString) {
  const size_t oldSize = oldString.length();

  // do nothing if line is shorter than the string to find
  if( oldSize > line.length() ) return;

  const size_t newSize = newString.length();
  for( size_t pos = 0; ; pos += newSize ) {
    // Locate the substring to replace
    pos = line.find( oldString, pos );
    if( pos == string::npos ) return;
    if( oldSize == newSize ) {
      // if they're same size, use std::string::replace
      line.replace( pos, oldSize, newString );
    } else {
      // if not same size, replace by erasing and inserting
      line.erase( pos, oldSize );
      line.insert( pos, newString );
    }
  }
}

回答by Den-Jason

Here is a solution I wrote using the builder tactic:

这是我使用构建器策略编写的解决方案:

#include <string>
#include <sstream>

using std::string;
using std::stringstream;

string stringReplace (const string& source,
                      const string& toReplace,
                      const string& replaceWith)
{
  size_t pos = 0;
  size_t cursor = 0;
  int repLen = toReplace.length();
  stringstream builder;

  do
  {
    pos = source.find(toReplace, cursor);

    if (string::npos != pos)
    {
        //copy up to the match, then append the replacement
        builder << source.substr(cursor, pos - cursor);
        builder << replaceWith;

        // skip past the match 
        cursor = pos + repLen;
    }
  } 
  while (string::npos != pos);

  //copy the remainder
  builder << source.substr(cursor);

  return (builder.str());
}

Tests:

测试:

void addTestResult (const string&& testId, bool pass)
{
  ...
}

void testStringReplace()
{
    string source = "123456789012345678901234567890";
    string toReplace = "567";
    string replaceWith = "abcd";
    string result = stringReplace (source, toReplace, replaceWith);
    string expected = "1234abcd8901234abcd8901234abcd890";

    bool pass = (0 == result.compare(expected));
    addTestResult("567", pass);


    source = "123456789012345678901234567890";
    toReplace = "123";
    replaceWith = "-";
    result = stringReplace(source, toReplace, replaceWith);
    expected = "-4567890-4567890-4567890";

    pass = (0 == result.compare(expected));
    addTestResult("start", pass);


    source = "123456789012345678901234567890";
    toReplace = "0";
    replaceWith = "";
    result = stringReplace(source, toReplace, replaceWith);
    expected = "123456789123456789123456789"; 

    pass = (0 == result.compare(expected));
    addTestResult("end", pass);


    source = "123123456789012345678901234567890";
    toReplace = "123";
    replaceWith = "-";
    result = stringReplace(source, toReplace, replaceWith);
    expected = "--4567890-4567890-4567890";

    pass = (0 == result.compare(expected));
    addTestResult("concat", pass);


    source = "1232323323123456789012345678901234567890";
    toReplace = "323";
    replaceWith = "-";
    result = stringReplace(source, toReplace, replaceWith);
    expected = "12-23-123456789012345678901234567890";

    pass = (0 == result.compare(expected));
    addTestResult("interleaved", pass);



    source = "1232323323123456789012345678901234567890";
    toReplace = "===";
    replaceWith = "-";
    result = utils_stringReplace(source, toReplace, replaceWith);
    expected = source;

    pass = (0 == result.compare(expected));
    addTestResult("no match", pass);

}