Skip to content
C++ Better Explained
Go back
How to Replace a Substring in a C++ String

How to Replace a Substring in a C++ String

Short answer: find the position with find(), then call replace(pos, length, newText). There is no built-in replace-all, so replacing every occurrence needs a small loop — both versions are below.


Replace the First Occurrence

#include <iostream>
#include <string>

int main() {
    std::string s = "I like cats and cats like me";
    std::string target = "cats";
    std::string replacement = "dogs";

    size_t pos = s.find(target);
    if (pos != std::string::npos) {
        s.replace(pos, target.length(), replacement);
    }

    std::cout << s;   // I like dogs and cats like me
}

Three arguments to replace: where to start, how many characters to remove, and what to put there instead.

Always check for npos. If find does not locate the text it returns std::string::npos, and passing that to replace throws std::out_of_range.

Replace All Occurrences

This is the function most people are actually looking for:

#include <iostream>
#include <string>

void replaceAll(std::string& s,
                const std::string& target,
                const std::string& replacement) {
    if (target.empty()) return;

    size_t pos = 0;
    while ((pos = s.find(target, pos)) != std::string::npos) {
        s.replace(pos, target.length(), replacement);
        pos += replacement.length();
    }
}

int main() {
    std::string s = "I like cats and cats like me";
    replaceAll(s, "cats", "dogs");
    std::cout << s;   // I like dogs and dogs like me
}

Two details make this correct rather than subtly broken:

Want the full picture? The C++ Better Explained Ebook explains strings, vectors and the STL in plain English — 87 pages, just $19.

The Infinite Loop Trap

Skip that pos += step and watch what happens when the replacement contains the target:

// BROKEN — hangs forever
while ((pos = s.find("cat")) != std::string::npos) {
    s.replace(pos, 3, "cats");   // "cats" contains "cat"
}

Every replacement creates a fresh match at the same place, so the loop never ends and the string grows until memory runs out. Advancing the position is not an optimisation — it is what makes the loop terminate.

Replacing by Position, Without Searching

If you already know where the text sits, skip find entirely:

std::string date = "2026-09-11";
date.replace(4, 1, "/");   // one char at index 4
date.replace(7, 1, "/");
std::cout << date;         // 2026/09/11

The replacement does not have to be the same length as what it removes — the string resizes itself:

std::string s = "hello world";
s.replace(0, 5, "goodbye");
std::cout << s;   // goodbye world

Replacing Single Characters

For one character at a time, std::replace from <algorithm> is simpler and faster:

#include <algorithm>

std::string path = "C:\\Users\\Sahil";
std::replace(path.begin(), path.end(), '\\', '/');
std::cout << path;   // C:/Users/Sahil

Note the different design: this takes characters, not strings, and it edits in place across the whole range. It cannot change the string’s length, which is exactly why it can’t replace substrings.

Removing a Substring

Removing is just replacing with nothing:

std::string s = "hello, cruel world";
size_t pos = s.find(", cruel");
if (pos != std::string::npos) {
    s.erase(pos, 7);        // or s.replace(pos, 7, "");
}
std::cout << s;             // hello world

Case-Insensitive Replace

find is case-sensitive. To ignore case, search a lowercased copy while editing the original:

#include <algorithm>
#include <cctype>

std::string lower(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(),
                   [](unsigned char c){ return std::tolower(c); });
    return s;
}

void replaceAllInsensitive(std::string& s,
                           const std::string& target,
                           const std::string& replacement) {
    std::string hay = lower(s);
    std::string needle = lower(target);
    size_t pos = 0;
    while ((pos = hay.find(needle, pos)) != std::string::npos) {
        s.replace(pos, target.length(), replacement);
        hay = lower(s);
        pos += replacement.length();
    }
}

Rebuilding the lowercase copy each pass keeps the two strings aligned when the replacement changes the length.

Quick Reference

GoalCode
Replace first matchs.replace(s.find(t), t.size(), r)
Replace all matchesreplaceAll(s, t, r) from above
Replace at known positions.replace(pos, len, r)
Replace one character everywherestd::replace(s.begin(), s.end(), 'a', 'b')
Delete a substrings.erase(pos, len)

Take Your C++ Further

If you would rather understand strings and the STL than look up one function at a time, the C++ Better Explained Ebook walks through the fundamentals in plain English. Just $19.

👉 Get the C++ Better Explained Ebook — $19


📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Share this post on:

Written by

Sahil Bora

Software Engineer. Author and creator of C++ Better Explained.


Previous Post
How to Read a File Line by Line in C++
Next Post
How to Reverse a Vector in C++ (std::reverse and More)

Keep Learning