Skip to content
C++ Better Explained
Go back
How to Remove a Character from a String in C++

How to Remove a Character from a String in C++

Short answer: by position use s.erase(index, 1). To remove every occurrence, use the erase-remove idiom:

s.erase(std::remove(s.begin(), s.end(), 'a'), s.end());

Remove by Position

#include <iostream>
#include <string>

int main() {
    std::string s = "hello";

    s.erase(1, 1);        // remove 1 char at index 1
    std::cout << s;       // hllo
}

erase(pos, count) removes count characters starting at pos. Leave off the count and it removes everything from that position onward:

std::string s = "hello world";
s.erase(5);               // hello

Passing an index beyond the end throws std::out_of_range, so validate first if the index comes from user input or a search.

Remove the First or Last Character

std::string s = "hello";

s.pop_back();             // hell     (C++11)
s.erase(0, 1);            // ell

pop_back() on an empty string is undefined behaviour — no exception, just silent corruption. Always guard it:

if (!s.empty()) s.pop_back();

Remove Every Occurrence: The Erase-Remove Idiom

This is the one people search for:

#include <algorithm>
#include <iostream>
#include <string>

int main() {
    std::string s = "banana";

    s.erase(std::remove(s.begin(), s.end(), 'a'), s.end());

    std::cout << s;       // bnn
}

It looks strange until you see what each half does.

Want the STL explained properly? The C++ Better Explained Ebook covers strings, algorithms and containers in plain English — 87 pages, just $19.

Why std::remove Does Not Remove

std::remove works through iterators, and iterators cannot resize a container. So it does the only thing it can: it shuffles the characters you want to keep towards the front, and returns an iterator marking the new logical end.

std::string s = "banana";
auto newEnd = std::remove(s.begin(), s.end(), 'a');

// s is now "bnn" + 3 leftover characters
// s.size() is still 6

The leftover tail is unspecified junk. erase(newEnd, s.end()) chops it off and fixes the size. That is why the two calls are always written together — using remove alone is a classic bug that leaves a string looking right when printed but reporting the wrong length.

Remove Characters Matching a Rule

remove_if takes a predicate instead of a value:

#include <algorithm>
#include <cctype>

// remove all whitespace, not just spaces
s.erase(std::remove_if(s.begin(), s.end(),
        [](unsigned char c){ return std::isspace(c); }), s.end());

// keep only letters and digits
s.erase(std::remove_if(s.begin(), s.end(),
        [](unsigned char c){ return !std::isalnum(c); }), s.end());

// remove all digits
s.erase(std::remove_if(s.begin(), s.end(),
        [](unsigned char c){ return std::isdigit(c); }), s.end());

The unsigned char cast is not optional pedantry. Passing a negative char to isspace is undefined behaviour, and it genuinely crashes on some inputs with accented characters.

Remove the First Occurrence Only

std::string s = "banana";
size_t pos = s.find('a');
if (pos != std::string::npos) {
    s.erase(pos, 1);
}
std::cout << s;          // bnana

Always check for npos — passing it to erase throws.

C++20: std::erase and std::erase_if

C++20 finally added the obvious spelling:

#include <string>

std::string s = "banana";
std::erase(s, 'a');                                  // bnn

std::erase_if(s, [](char c){ return c == 'n'; });    // b

Same behaviour, no iterator pair, no chance of forgetting the erase half. Use it if your compiler supports C++20.

Removing from a Vector Works the Same Way

The idiom is not string-specific:

std::vector<int> v = {1, 2, 3, 2, 4};
v.erase(std::remove(v.begin(), v.end(), 2), v.end());
// 1 3 4

See removing elements from a vector for the container version and its iterator traps.

Quick Reference

GoalCode
Remove at indexs.erase(i, 1)
Remove last chars.pop_back()
Remove first chars.erase(0, 1)
Remove first matchs.erase(s.find(c), 1)
Remove all matchess.erase(std::remove(s.begin(), s.end(), c), s.end())
Remove by rulestd::remove_if(...) + erase
C++20 shorthandstd::erase(s, c)

Take Your C++ Further

If you want strings and the STL explained properly instead of assembled from snippets, the C++ Better Explained Ebook covers 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
cin vs getline in C++: Why getline Gets Skipped
Next Post
How to Check if a String Is a Number in C++

Keep Learning