How to remove all the occurrences of a char in c++ string
Categories:
Efficiently Removing All Occurrences of a Character from a C++ String

Learn various C++ Standard Library (STL) techniques to effectively remove all instances of a specific character from a string, optimizing for performance and readability.
Removing specific characters from a string is a common task in C++ programming. Whether you're cleaning user input, parsing data, or preparing strings for display, the C++ Standard Library offers several powerful and efficient ways to achieve this. This article explores different approaches, focusing on std::remove
, std::erase
, and std::remove_if
in conjunction with std::string::erase
, providing practical examples and performance considerations.
Understanding the Erase-Remove Idiom
The 'erase-remove idiom' is a fundamental pattern in C++ for removing elements from containers that do not automatically resize, such as std::vector
or std::string
. The std::remove
algorithm does not actually remove elements from the container; instead, it rearranges them, moving all elements not to be removed to the beginning of the range and returning an iterator to the new logical end of the range. The elements between this new logical end and the physical end of the container are left in an unspecified but valid state. To truly remove these elements and resize the container, you must then call the container's erase
method with the iterators returned by std::remove
.
flowchart TD A[Original String] --> B{std::remove(begin, end, char_to_remove)} B --> C[String with unwanted chars moved to end] C --> D{std::string::erase(new_end, old_end)} D --> E[Final String without unwanted chars] style A fill:#f9f,stroke:#333,stroke-width:2px style E fill:#bbf,stroke:#333,stroke-width:2px
The Erase-Remove Idiom Workflow
Method 1: Using std::remove
and std::string::erase
This is the most idiomatic and generally preferred way to remove elements from a std::string
or other sequence containers. It leverages the std::remove
algorithm to shift elements and then std::string::erase
to physically remove the unwanted characters and resize the string.
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string str = "Hello, World! This is a test.";
char charToRemove = 'o';
// Use std::remove to move all 'o's to the end
// and get an iterator to the new logical end.
str.erase(std::remove(str.begin(), str.end(), charToRemove), str.end());
std::cout << "String after removing '" << charToRemove << "': " << str << std::endl;
charToRemove = ' '; // Remove spaces
str.erase(std::remove(str.begin(), str.end(), charToRemove), str.end());
std::cout << "String after removing spaces: " << str << std::endl;
return 0;
}
Removing characters using std::remove
and std::string::erase
std::remove
algorithm is highly efficient as it performs a single pass over the range. The subsequent std::string::erase
operation then handles the actual memory manipulation, which is also optimized for std::string
.Method 2: Using std::remove_if
with a Lambda or Predicate
If you need to remove characters based on a more complex condition than a simple equality check, std::remove_if
is the ideal choice. It works similarly to std::remove
but takes a unary predicate (a function or lambda that returns true
for elements to be removed) as its third argument.
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype> // For ispunct, isspace, etc.
int main() {
std::string str = "Hello, World! 123 This is a test.";
// Remove all punctuation characters
str.erase(std::remove_if(str.begin(), str.end(),
[](char c) { return std::ispunct(static_cast<unsigned char>(c)); }),
str.end());
std::cout << "After removing punctuation: " << str << std::endl;
// Remove all digits
str.erase(std::remove_if(str.begin(), str.end(),
[](char c) { return std::isdigit(static_cast<unsigned char>(c)); }),
str.end());
std::cout << "After removing digits: " << str << std::endl;
return 0;
}
Removing characters using std::remove_if
with a lambda
std::ispunct
, std::isdigit
, etc., from <cctype>
, it's crucial to cast the char
argument to unsigned char
. This prevents potential undefined behavior if the char
is negative (e.g., for extended ASCII characters) and not representable as an unsigned char
.Method 3: Iterating and Erasing (Less Efficient)
While possible, iterating through a string and erasing characters one by one is generally less efficient than the erase-remove idiom, especially for large strings or frequent removals. Each std::string::erase(iterator)
operation can potentially shift all subsequent characters, leading to a quadratic time complexity in the worst case (e.g., removing every character).
#include <iostream>
#include <string>
int main() {
std::string str = "Programming is fun!";
char charToRemove = 'g';
for (auto it = str.begin(); it != str.end(); ) {
if (*it == charToRemove) {
it = str.erase(it); // erase returns an iterator to the next element
} else {
++it;
}
}
std::cout << "String after removing '" << charToRemove << "': " << str << std::endl;
return 0;
}
Removing characters by iterating and erasing (generally not recommended)
std::remove
cannot be easily adapted. However, for general character removal, prefer the erase-remove idiom.