How do I replace all instances of a string with another string?

The bug is in str.replace(start_pos, end_pos, to);

From the std::string doc at http://www.cplusplus.com/reference/string/string/replace/

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

You are using an end-position, while the function expects a length.

So change to:

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

Note: untested.


This is going to go in my list of 'just use a Boost library' answers, but here it goes anyway:

Have you considered Boost.String? It has more features than the standard library, and where features overlap, Boost.String has a more much more natural syntax, in my opinion.


A complete code:

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 a more 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 changed: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def

C++11 now includes the header <regex> which has regular expression functionality. From the 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;
}

Of course, now you have two problems.

Tags:

C++

String