How to find and replace string?

C++String

C++ Problem Overview


If s is a std::string, then is there a function like the following?

s.replace("text to replace", "new text");

C++ Solutions


Solution 1 - C++

Replace first match

Use a combination of std::string::find and std::string::replace.

Find the first match:

std::string s;
std::string toReplace("text to replace");
size_t pos = s.find(toReplace);

Replace the first match:

s.replace(pos, toReplace.length(), "new text");

A simple function for your convenience:

void replace_first(
    std::string& s,
    std::string const& toReplace,
    std::string const& replaceWith
) {
    std::size_t pos = s.find(toReplace);
    if (pos == std::string::npos) return;
    s.replace(pos, toReplace.length(), replaceWith);
}

Usage:

replace_first(s, "text to replace", "new text");

Demo.


Replace all matches

Define this O(n) method using std::ostringstream as a buffer:

void replace_all(
    std::string& s,
    std::string const& toReplace,
    std::string const& replaceWith
) {
    std::ostringstream oss;
    std::size_t pos = 0;
    std::size_t prevPos = pos;

    while (true) {
        prevPos = pos;
        pos = s.find(toReplace, pos);
        if (pos == std::string::npos)
            break;
        oss << s.substr(prevPos, pos - prevPos);
        oss << replaceWith;
        pos += toReplace.size();
    }

    oss << s.substr(prevPos);
    s = oss.str();
}

Usage:

replace_all(s, "text to replace", "new text");

Demo.


Boost

Alternatively, use boost::algorithm::replace_all:

#include <boost/algorithm/string.hpp>
using boost::replace_all;

Usage:

replace_all(s, "text to replace", "new text");

Solution 2 - C++

Do we really need a Boost library for seemingly such a simple task?

To replace all occurences of a substring use this function:

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 modified: " 
          << 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

Solution 3 - C++

Yes: replace_all is one of the boost string algorithms:

Although it's not a standard library, it has a few things on the standard library:

  1. More natural notation based on ranges rather than iterator pairs. This is nice because you can nest string manipulations (e.g., replace_all nested inside a trim). That's a bit more involved for the standard library functions.
  2. Completeness. This isn't hard to be 'better' at; the standard library is fairly spartan. For example, the boost string algorithms give you explicit control over how string manipulations are performed (i.e., in place or through a copy).

Solution 4 - C++

#include <iostream>
#include <string>
using namespace std;

int main ()
{
    string str("one three two four");
    string str2("three");
    str.replace(str.find(str2),str2.length(),"five");
    cout << str << endl;
    return 0;
}

###Output one five two four

Solution 5 - C++

like some say boost::replace_all

here a dummy example:

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

    std::string path("file.gz");
    boost::replace_all(path, ".gz", ".zip");

Solution 6 - C++

Not exactly that, but std::string has many replace overloaded functions.

Go through this link to see explanation of each, with examples as to how they're used.

Also, there are several versions of string::find functions (listed below) which you can use in conjunction with string::replace.

  • find
  • rfind
  • find_first_of
  • find_last_of
  • find_first_not_of
  • find_last_not_of

Also, note that there are several versions of replace functions available from <algorithm> which you can also use (instead of string::replace):

  • replace
  • replace_if
  • replace_copy
  • replace_copy_if

Solution 7 - C++

// replaced text will be in buffer.
void Replace(char* buffer, const char* source, const char* oldStr,  const char* newStr)
{
	if(buffer==NULL || source == NULL || oldStr == NULL || newStr == NULL) return; 

	int slen = strlen(source);
	int olen = strlen(oldStr);
	int nlen = strlen(newStr);

	if(olen>slen) return;
	int ix=0;

	for(int i=0;i<slen;i++)
	{
		if(oldStr[0] == source[i])
		{
			bool found = true;
			for(int j=1;j<olen;j++)
			{
				if(source[i+j]!=oldStr[j])
				{
					found = false;
					break;
				}
			}

			if(found)
			{
				for(int j=0;j<nlen;j++)
					buffer[ix++] = newStr[j];

				i+=(olen-1);
			}
			else
			{
				buffer[ix++] = source[i];
			}
		}
		else
		{
			buffer[ix++] = source[i];
		}
	}
}

Solution 8 - C++

Here's the version I ended up writing that replaces all instances of the target string in a given string. Works on any string type.

template <typename T, typename U>
T &replace (
          T &str, 
    const U &from, 
    const U &to)
{
    size_t pos;
    size_t offset = 0;
    const size_t increment = to.size();

    while ((pos = str.find(from, offset)) != T::npos)
    {
        str.replace(pos, from.size(), to);
        offset = pos + increment;
    }

    return str;
}

Example:

auto foo = "this is a test"s;
replace(foo, "is"s, "wis"s);
cout << foo;

Output:

thwis wis a test

Note that even if the search string appears in the replacement string, this works correctly.

Solution 9 - C++

void replace(char *str, char *strFnd, char *strRep)
{
    for (int i = 0; i < strlen(str); i++)
    {
        int npos = -1, j, k;
        if (str[i] == strFnd[0])
        {
            for (j = 1, k = i+1; j < strlen(strFnd); j++)
                if (str[k++] != strFnd[j])
                    break;
            npos = i;
        }
        if (npos != -1)
            for (j = 0, k = npos; j < strlen(strRep); j++)
                str[k++] = strRep[j];
    }

}

int main()
{
    char pst1[] = "There is a wrong message";
    char pfnd[] = "wrong";
    char prep[] = "right";

    cout << "\nintial:" << pst1;
    
    replace(pst1, pfnd, prep);

    cout << "\nfinal : " << pst1;
    return 0;
}

Solution 10 - C++

void replaceAll(std::string & data, const std::string &toSearch, const std::string &replaceStr)
{
	// Get the first occurrence
	size_t pos = data.find(toSearch);
	// Repeat till end is reached
	while( pos != std::string::npos)
	{
		// Replace this occurrence of Sub String
		data.replace(pos, toSearch.size(), replaceStr);
		// Get the next occurrence from the current position
		pos =data.find(toSearch, pos + replaceStr.size());
	}
}

More CPP utilities: https://github.com/Heyshubham/CPP-Utitlities/blob/master/src/MEString.cpp#L60

Solution 11 - C++

> is there a function like the following?

One other(in addition to using boost and other methods given in different answers) possible way of doing this is using std::regex_replace as shown below:

    std::string s{"my name is my name and not my name mysometext myto"}; //this is the original line
    
    std::string replaceThis = "my";
    std::string replaceWith = "your";
    
    std::regex pattern("\\b" + replaceThis + "\\b");
    
    std::string replacedLine = std::regex_replace(s, pattern, replaceWith);

    std::cout<<replacedLine<<std::endl;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionneuromancerView Question on Stackoverflow
Solution 1 - C++Mateen UlhaqView Answer on Stackoverflow
Solution 2 - C++Czarek TomczakView Answer on Stackoverflow
Solution 3 - C++phoojiView Answer on Stackoverflow
Solution 4 - C++Mark TolonenView Answer on Stackoverflow
Solution 5 - C++Sylvain RochetteView Answer on Stackoverflow
Solution 6 - C++NawazView Answer on Stackoverflow
Solution 7 - C++Bayram AKGÜLView Answer on Stackoverflow
Solution 8 - C++anisopteraView Answer on Stackoverflow
Solution 9 - C++snbView Answer on Stackoverflow
Solution 10 - C++Shubham AgrawalView Answer on Stackoverflow
Solution 11 - C++Anoop RanaView Answer on Stackoverflow