How do I replace all occurrences of a substring with another string, for std::strings?
std::string s ("One hello, two hellos.");
s = s.replace("hello", "world"); // something like this
How do I replace all occurrences of a substring with another string, for std::strings?
std::string s ("One hello, two hellos.");
s = s.replace("hello", "world"); // something like this
Many other answers repeatedly call std::string::replace, which requires the string to be overwritten repeatedly, which results in poor performance. In contrast, this uses a std::string buffer so that each character of the string is only traversed once:
void replace_all(
std::string& s,
std::string const& toReplace,
std::string const& replaceWith
) {
std::string buf;
std::size_t pos = 0;
std::size_t prevPos;
// Reserves rough estimate of final size of string.
buf.reserve(s.size());
while (true) {
prevPos = pos;
pos = s.find(toReplace, pos);
if (pos == std::string::npos)
break;
buf.append(s, prevPos, pos - prevPos);
buf += replaceWith;
pos += toReplace.size();
}
buf.append(s, prevPos, s.size() - prevPos);
s.swap(buf);
}
Usage:
replace_all(s, "text to replace", "new text");
#include <iostream>
#include <sstream>
void replace_all(
std::string& s,
std::string const& toReplace,
std::string const& replaceWith
) {
std::string buf;
std::size_t pos = 0;
std::size_t prevPos;
// Reserves rough estimate of final size of string.
buf.reserve(s.size());
while (true) {
prevPos = pos;
pos = s.find(toReplace, pos);
if (pos == std::string::npos)
break;
buf.append(s, prevPos, pos - prevPos);
buf += replaceWith;
pos += toReplace.size();
}
buf.append(s, prevPos, s.size() - prevPos);
s.swap(buf);
}
int main() {
std::string s("hello hello, mademoiselle!");
replace_all(s, "hello", "bye");
std::cout << s << std::endl;
}
Output:
bye bye, mademoiselle!
Note: Previous versions of this answer used std::ostringstream, which has some overhead. The latest version uses std::string::append instead, as recommended by @LouisGo.
// Replace all occurrences of searchStr in str with replacer
// Each match is replaced only once to prevent an infinite loop
// The algorithm iterates once over the input and only concatenates
// to the output, so it should be reasonably efficient
std::string replace(const std::string& str, const std::string& searchStr,
const std::string& replacer)
{
// Prevent an infinite loop if the input is empty
if (searchStr == "") {
return str;
}
std::string result = "";
size_t pos = 0;
size_t pos2 = str.find(searchStr, pos);
while (pos2 != std::string::npos) {
result += str.substr(pos, pos2-pos) + replacer;
pos = pos2 + searchStr.length();
pos2 = str.find(searchStr, pos);
}
result += str.substr(pos, str.length()-pos);
return result;
}