What is the effective way to replace all occurrences of a character with another character in std::string
?
-
It seems that stdlib sucks when it comes to such "advanced" feature. Better use QString or a general library when you start finding missing stuff. – Kiruahxh Mar 17 '21 at 16:14
17 Answers
std::string
doesn't contain such function but you could use stand-alone replace
function from algorithm
header.
#include <algorithm>
#include <string>
void some_func() {
std::string s = "example string";
std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}

- 97,037
- 24
- 136
- 212
-
10`std::string` is **a container** specifically designed to operate with sequences of characters. [link](http://www.cplusplus.com/reference/string/string/) – Kirill V. Lyadvinsky May 24 '10 at 11:41
-
230Unfortunately, this allows to replace only one char by another char. It cannot replace a char with more chars (that is, by a string). Is there a way to do a search-replace with more chars? – SasQ Aug 09 '12 at 09:26
-
7
-
6@KirillV.Lyadvinsky: When I use this method to replace all x's with y's, the result is a lengthy y string no matter what the original string is. I've curious what do you think would be the problem. (the code is exactly the same as you wrote) – Transcendent Oct 17 '13 at 12:08
-
2@FlowFlowOverFlow, I doubt you have "the code is exactly the same". Check it here: http://codepad.org/UIcrFX1j - it works fine. – Kirill V. Lyadvinsky Jun 20 '14 at 07:40
-
Error 2 error C2040: '==' : 'int' differs in levels of indirection from 'const char [2]' c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm 1261 f**! – hfrmobile Jul 07 '14 at 15:32
-
10@Transcendent: This is exactly what happens with `std::string::replace()` instead of `std::replace()`! 'x' (`char`) is implicitely casted to `size_t` [value 120], thus the whole string or or part of it will be filled up with 120 copies of 'y'. – IBue Feb 19 '15 at 18:41
-
1
-
1A bit late to the party, but `std::replace_if` allows you to define a lambda function that determines what characters to replace. – Urchin Jun 18 '20 at 19:44
-
@AyxanHaqverdili `std::remove` only removes the occurrences by shifting other chars to left. `string::erase()` needs to be called with the return value of `std::remove` to get rid of the remaining characters. see [https://en.cppreference.com/w/cpp/algorithm/remove](https://en.cppreference.com/w/cpp/algorithm/remove) – saeedkazemi May 17 '21 at 15:13
The question is centered on character
replacement, but, as I found this page very useful (especially Konrad's remark), I'd like to share this more generalized implementation, which allows to deal with substrings
as well:
std::string 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) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
}
return str;
}
Usage:
std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;
Outputs:
Number_Of_Beans
XXjXugtXty
hhjhugthty
EDIT:
The above can be implemented in a more suitable way, in case performance is of your concern, by returning nothing (void
) and performing the changes "in-place"; that is, by directly modifying the string argument str
, passed by reference instead of by value. This would avoid an extra costly copy of the original string by overwriting it.
Code :
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Hope this will be helpful for some others...

- 1,186
- 10
- 17

- 10,054
- 5
- 48
- 85
-
7This one has a performance issue in cases where the source string is large and there are many occurences of the string to be replaced. string::replace() would be called many times which causes lots of string copies. See my solution which addresses that problem. – Ingmar Apr 21 '15 at 06:44
-
1Nit picking ahead: **by address** => **by reference**. Whether it's an address or not is an implementation detail. – Max Truxa May 18 '15 at 16:16
-
1You should actually check if `from` string is empty, otherwise an endless loop will occur. – newbie Sep 05 '15 at 02:23
I thought I'd toss in the boost solution as well:
#include <boost/algorithm/string/replace.hpp>
// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");
// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");

- 18,272
- 7
- 49
- 77
-
Then you are missing a few `-I` flags for your compiler in order for it to find the Boost libraries on your system. Perhaps you need to even install it first. – Martin Ueding May 17 '19 at 09:56
-
1The above is more effective since it comes out with std lib.No all using boost library ;-) – hfrmobile Mar 20 '20 at 10:49
Imagine a large binary blob where all 0x00 bytes shall be replaced by "\1\x30" and all 0x01 bytes by "\1\x31" because the transport protocol allows no \0-bytes.
In cases where:
- the replacing and the to-replaced string have different lengths,
- there are many occurences of the to-replaced string within the source string and
- the source string is large,
the provided solutions cannot be applied (because they replace only single characters) or have a performance problem, because they would call string::replace several times which generates copies of the size of the blob over and over. (I do not know the boost solution, maybe it is OK from that perspective)
This one walks along all occurrences in the source string and builds the new string piece by piece once:
void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
std::string newString;
newString.reserve(source.length()); // avoids a few memory allocations
std::string::size_type lastPos = 0;
std::string::size_type findPos;
while(std::string::npos != (findPos = source.find(from, lastPos)))
{
newString.append(source, lastPos, findPos - lastPos);
newString += to;
lastPos = findPos + from.length();
}
// Care for the rest after last occurrence
newString += source.substr(lastPos);
source.swap(newString);
}

- 15,379
- 3
- 47
- 71

- 2,361
- 3
- 19
- 33
-
This is by far the best solution here which is built on the STL alone. If you're going to drop in a custom function for easy use anywhere, make it this one. – Roger Sanders Jan 29 '20 at 00:41
-
1It is better to do `newString.append(source, lastPos, source.length() - lastPos);` instead of `newString += source.substr(lastPos);` to avoid creating temporary string [as `substr()` does]. (I can not edit this answer because suggested edit queue is full.) – tav Apr 26 '21 at 01:30
A simple find and replace for a single character would go something like:
s.replace(s.find("x"), 1, "y")
To do this for the whole string, the easy thing to do would be to loop until your s.find
starts returning npos
. I suppose you could also catch range_error
to exit the loop, but that's kinda ugly.

- 44,016
- 10
- 73
- 134
-
8While this is probably a suitable solution when the number of characters to replace is small compared to the length of the string, it doesn't scale well. As the proportion of characters in the original string that need to be replaced increases, this method will approach O(N^2) in time. – andand May 24 '10 at 14:37
-
7True. My general philosophy is to do the easy (to write and to read) thing until such time as the inefficiencies are causing real problems. There are some circumstances where you might have humoungous strings where O(N**2) matters, but 99% of the time my strings are 1K or less. – T.E.D. May 25 '10 at 03:40
-
4...that being said, I like Kirill's method better (and had already voted it up). – T.E.D. May 25 '10 at 03:41
-
What happens if "x" is not found? Also, why you are using double braces? – Prasath Govind Aug 25 '15 at 11:26
-
@PrasathGovind - I was just showing the calls required (hence "something like"). Important but obscuring details such as proper error handling were left as an exercise for the reader. As for "double braces", I'm not sure what those are, or what you are talking about. For me a "brace" is the `{` character. I don't know what a "double brace" is. Perhaps you have some kind of font issue? – T.E.D. Aug 25 '15 at 12:54
-
I'm all for not optimizing prematurely, but avoiding O(N^2) is not premature optimization. – Jeffrey Faust Oct 25 '19 at 22:05
For completeness, here's how to do it with std::regex
.
#include <regex>
#include <string>
int main()
{
const std::string s = "example string";
const std::string r = std::regex_replace(s, std::regex("x"), "y");
}

- 413
- 6
- 6
-
The regex_replace much slower (x10+ times slower) than if to Gauthier Boaglio solution... – David Constantine Oct 12 '22 at 08:59
If you're looking to replace more than a single character, and are dealing only with std::string
, then this snippet would work, replacing sNeedle in sHaystack with sReplace, and sNeedle and sReplace do not need to be the same size. This routine uses the while loop to replace all occurrences, rather than just the first one found from left to right.
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}

- 23,743
- 21
- 113
- 209
-
-
3
-
4This will infinite loop if kNeedle happens to be a substring of sReplace. – prideout Jan 11 '20 at 23:39
-
Plus there's a `find` call twice. Consider making that result a temp variable. – Luc Bloom Jan 20 '20 at 09:25
As Kirill suggested, either use the replace method or iterate along the string replacing each char independently.
Alternatively you can use the find
method or find_first_of
depending on what you need to do. None of these solutions will do the job in one go, but with a few extra lines of code you ought to make them work for you. :-)

- 39,751
- 32
- 78
- 114
What about Abseil StrReplaceAll? From the header file:
// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});

- 181
- 2
- 7
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
int len, loop=0;
string nword="", let;
len=word.length();
len--;
while(loop<=len){
let=word.substr(loop, 1);
if(let==target){
nword=nword+replacement;
}else{
nword=nword+let;
}
loop++;
}
return nword;
}
//Main..
int main() {
string word;
cout<<"Enter Word: ";
cin>>word;
cout<<replace(word, "x", "y")<<endl;
return 0;
}

- 31
- 2
-
If `word` is long, there may be a lot of overhead while calling the function. You can optimise this by passing `word`, `target`, and `replacement` as const-references. – TrebledJ Feb 21 '19 at 08:49
Old School :-)
std::string str = "H:/recursos/audio/youtube/libre/falta/";
for (int i = 0; i < str.size(); i++) {
if (str[i] == '/') {
str[i] = '\\';
}
}
std::cout << str;
Result:
H:\recursos\audio\youtube\libre\falta\

- 603
- 7
- 10

- 447
- 4
- 10
For simple situations this works pretty well without using any other library then std::string (which is already in use).
Replace all occurences of character a with character b in some_string:
for (size_t i = 0; i < some_string.size(); ++i) {
if (some_string[i] == 'a') {
some_string.replace(i, 1, "b");
}
}
If the string is large or multiple calls to replace is an issue, you can apply the technique mentioned in this answer: https://stackoverflow.com/a/29752943/3622300

- 300
- 3
- 7
here's a solution i rolled, in a maximal DRI spirit. it will search sNeedle in sHaystack and replace it by sReplace, nTimes if non 0, else all the sNeedle occurences. it will not search again in the replaced text.
std::string str_replace(
std::string sHaystack, std::string sNeedle, std::string sReplace,
size_t nTimes=0)
{
size_t found = 0, pos = 0, c = 0;
size_t len = sNeedle.size();
size_t replen = sReplace.size();
std::string input(sHaystack);
do {
found = input.find(sNeedle, pos);
if (found == std::string::npos) {
break;
}
input.replace(found, len, sReplace);
pos = found + replen;
++c;
} while(!nTimes || c < nTimes);
return input;
}

- 651
- 1
- 9
- 11
I think I'd use std::replace_if()
A simple character-replacer (requested by OP) can be written by using standard library functions.
For an in-place version:
#include <string>
#include <algorithm>
void replace_char(std::string& in,
std::string::value_type srch,
std::string::value_type repl)
{
std::replace_if(std::begin(in), std::end(in),
[&srch](std::string::value_type v) { return v==srch; },
repl);
return;
}
and an overload that returns a copy if the input is a const
string:
std::string replace_char(std::string const& in,
std::string::value_type srch,
std::string::value_type repl)
{
std::string result{ in };
replace_char(result, srch, repl);
return result;
}

- 4,371
- 23
- 23
This works! I used something similar to this for a bookstore app, where the inventory was stored in a CSV (like a .dat file). But in the case of a single char, meaning the replacer is only a single char, e.g.'|', it must be in double quotes "|" in order not to throw an invalid conversion const char.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count = 0; // for the number of occurences.
// final hold variable of corrected word up to the npos=j
string holdWord = "";
// a temp var in order to replace 0 to new npos
string holdTemp = "";
// a csv for a an entry in a book store
string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";
// j = npos
for (int j = 0; j < holdLetter.length(); j++) {
if (holdLetter[j] == ',') {
if ( count == 0 )
{
holdWord = holdLetter.replace(j, 1, " | ");
}
else {
string holdTemp1 = holdLetter.replace(j, 1, " | ");
// since replacement is three positions in length,
// must replace new replacement's 0 to npos-3, with
// the 0 to npos - 3 of the old replacement
holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3);
holdWord = "";
holdWord = holdTemp;
}
holdTemp = "";
count++;
}
}
cout << holdWord << endl;
return 0;
}
// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85
Uncustomarily I am using CentOS currently, so my compiler version is below . The C++ version (g++), C++98 default:
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

- 193
- 1
- 11
This is not the only method missing from the standard library, it was intended be low level. This use case and many other are covered by general libraries such as:
QtCore & QString has my preference: it supports UTF8 and uses less templates, which means understandable errors and faster compilation. It uses the "q" prefix which makes namespaces unnecessary and simplifies headers.
Boost often generates hideous error messages and slow compile time.
POCO seems to be a reasonable compromise.

- 1,276
- 13
- 30
How about replace any character string with any character string using only good-old C string functions?
char original[256]="First Line\nNext Line\n", dest[256]="";
char* replace_this = "\n"; // this is now a single character but could be any string
char* with_this = "\r\n"; // this is 2 characters but could be of any length
/* get the first token */
char* token = strtok(original, replace_this);
/* walk through other tokens */
while (token != NULL) {
strcat(dest, token);
strcat(dest, with_this);
token = strtok(NULL, replace_this);
}
dest
should now have what we are looking for.

- 73
- 5