147

I am using following:

replace (str1.begin(), str1.end(), 'a' , '')

But this is giving compilation error.

Devesh Agrawal
  • 8,982
  • 16
  • 82
  • 131

14 Answers14

231

Basically, replace replaces a character with another and '' is not a character. What you're looking for is erase.

See this question which answers the same problem. In your case:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

Or use boost if that's an option for you, like:

#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");

All of this is well-documented on reference websites. But if you didn't know of these functions, you could easily do this kind of things by hand:

std::string output;
output.reserve(str.size()); // optional, avoids buffer reallocations in the loop
for(size_t i = 0; i < str.size(); ++i)
  if(str[i] != 'a') output += str[i];
Community
  • 1
  • 1
Antoine
  • 13,494
  • 6
  • 40
  • 52
  • 2
    Isn't the algorithm you provided ***`O(n^2)`***? – jww Apr 10 '16 at 05:07
  • 2
    @jww: I assume you're talking about the last code sample and `n` is the original string length. For each input character, I do 1 character test `O(1)`, and 0 or 1 character append. Character append is `O(1)` is enough memory is reserved, or `O(current_length)` if a new buffer is allocated. If you do `output.reserve(str.size())` before the loop this never happens and you have a global `O(n)` cost. Otherwise asymptotically, I guess the cost is `O(n . log(n) )` because of STL container reallocation strategy. – Antoine Apr 15 '16 at 10:13
  • 5
    I needed #include – S Meaden Apr 18 '17 at 17:10
  • @DmitryNichiporenko the answer with the for cannot be the most suitable. If you have a predicate or a non empty output I would rather consider: output.reserve(str.size()+output.size()); std::copy_if(str.begin(), str.end(), std::back_inserter(output), [](char c){return predicate(c);}); – jimifiki Mar 22 '19 at 08:14
  • Why are we using std::remove and std::erase? This seems a bit superfluous to me, as I am coming from python and have been learning C++ for only a month. I'd be glad if someone explained that to me, and not say 'read the reference', thanks. – Viktor Stefanov Aug 31 '21 at 13:18
  • 1
    @ViktorStefanov C++ is lower level than python, meaning you have more control over things but it's generally more verbose, and the devil is in the details. The fact that the standard library is (in my opinion) not well designed doesn't help. In this case, `remove` can't change the length of the string, so it just shuffles character. Then you have to call `earse` to basically change the length of the string. [See wiki](https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom) – Antoine Aug 31 '21 at 14:01
21

The algorithm std::replace works per element on a given sequence (so it replaces elements with different elements, and can not replace it with nothing). But there is no empty character. If you want to remove elements from a sequence, the following elements have to be moved, and std::replace doesn't work like this.

You can try to use std::remove() together with str.erase()1 to achieve this.

str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Kai Petzke
  • 2,150
  • 21
  • 29
leemes
  • 44,967
  • 21
  • 135
  • 183
19

Starting with C++20, std::erase() has been added to the standard library, which combines the call to str.erase() and std::remove() into just one function:

std::erase(str, 'a');

The std::erase() function overload acting on strings is defined directly in the <string> header file, so no separate includes are required. Similiar overloads are defined for all the other containers.

Kai Petzke
  • 2,150
  • 21
  • 29
15

Using copy_if:

#include <string>
#include <iostream>
#include <algorithm>
int main() {
    std::string s1 = "a1a2b3c4a5";
    std::string s2;
    std::copy_if(s1.begin(), s1.end(), std::back_inserter(s2),
         [](char c){ 
                std::string exclude = "a";
                return exclude.find(c) == std::string::npos;}
    );

    std::cout << s2 << '\n';
    return 0;
}
Captain Giraffe
  • 14,407
  • 6
  • 39
  • 67
perreal
  • 94,503
  • 21
  • 155
  • 181
  • -1 This code leads to buffer overruns, if `s1` is longer than the fixed size string `s2`. Furthermore, `s2` is not properly terminated, as the NUL byte at the end of `s1` is not copied. Finally, the poster asked for an in-place solution, not to generate a new string. – Kai Petzke Oct 13 '21 at 06:16
  • You are right, but seems like the NULL byte bug is introduced by @jimifiki. For the fixed length, the sample works just fine but I agree could be more generic. – perreal Oct 13 '21 at 16:57
  • I apoligize for my bad edit. Feel free to use this line s1.erase(std::copy_if(s1.begin(), s1.end(), s1.begin(), [](char c){return c!='a';})); for a safe and in-place solution – jimifiki Oct 14 '21 at 09:05
  • @KaiPetzke I edited the answer to alleviate your concerns. – Captain Giraffe Nov 02 '21 at 19:23
  • 1
    Yes, it looks clean now. – Kai Petzke Nov 04 '21 at 07:38
6
string RemoveChar(string str, char c) 
{
   string result;
   for (size_t i = 0; i < str.size(); i++) 
   {
          char currentChar = str[i];
          if (currentChar != c)
              result += currentChar;
   }
       return result;
}

This is how I did it.

Or you could do as Antoine mentioned:

See this question which answers the same problem. In your case:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
oblivion02
  • 557
  • 5
  • 14
Rafael Valle
  • 151
  • 2
  • 9
1

This code removes repetition of characters i.e, if the input is aaabbcc then the output will be abc. (the array must be sorted for this code to work)

cin >> s;
ans = "";
ans += s[0];
for(int i = 1;i < s.length();++i)
if(s[i] != s[i-1])
    ans += s[i];
cout << ans << endl;
Community
  • 1
  • 1
1

In case you have a predicate and/or a non empty output to fill with the filtered string, I would consider:

output.reserve(str.size() + output.size());  
std::copy_if(str.cbegin(), 
             str.cend(), 
             std::back_inserter(output), 
             predicate});

In the original question the predicate is [](char c){return c != 'a';}

jimifiki
  • 5,377
  • 2
  • 34
  • 60
0

This is how I do it:

std::string removeAll(std::string str, char c) {
    size_t offset = 0;
    size_t size = str.size();

    size_t i = 0;
    while (i < size - offset) {
        if (str[i + offset] == c) {
            offset++;
        }

        if (offset != 0) {
            str[i] = str[i + offset];
        }

        i++;
    }

    str.resize(size - offset);
    return str;
}

Basically whenever I find a given char, I advance the offset and relocate the char to the correct index. I don't know if this is correct or efficient, I'm starting (yet again) at C++ and i'd appreciate any input on that.

Ricardo Pieper
  • 2,613
  • 3
  • 26
  • 40
0

Based on other answers, here goes one more example where I removed all special chars in a given string:

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

std::string chars(".,?!.:;_,!'\"-");

int main(int argc, char const *argv){

  std::string input("oi?");
  std::string output = eraseSpecialChars(input);   

 return 0;
}




std::string eraseSpecialChars(std::string str){

std::string newStr;
    newStr.assign(str);  

    for(int i = 0; i < str.length(); i++){
        for(int  j = 0; j < chars.length(); j++ ){
            if(str.at(i) == chars.at(j)){
                char c = str.at(i);
                newStr.erase(std::remove(newStr.begin(), newStr.end(), c), newStr.end());
            }
        }

    }      

return newStr; 
}

Input vs Output:

Input:ra,..pha
Output:rapha

Input:ovo,
Output:ovo

Input:a.vo
Output:avo

Input:oi?
Output:oi
basquiatraphaeu
  • 525
  • 7
  • 19
0

I have a string being read:

"\"internet\""

and I want to remove the quotes. I used the std::erase solution suggested above:

str.erase(std::remove(str.begin(), str.end(), '\"'), str.end());

but when I then did a compare on the result it failed:

if (str == "internet") {}

What I actually got was:

"internet "

The std::erase / std::remove solution doesn't shorten the string when it removes the end. I added this (from https://stackoverflow.com/a/21815483/264822):

str.erase(std::find_if(str.rbegin(), str.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), str.end());

to remove the trailing space(s).

parsley72
  • 8,449
  • 8
  • 65
  • 98
0
void remove_character() {
    string s; // string that you want to enterd
    cin >> s;
    // you can use string as well instead of character
    char c;
    cin >> c;
    s.erase(remove(s.begin(), s.end(), c), s.end());
    cout << s << endl;
}

you can use this method to remove characters from string.

geanakuch
  • 778
  • 7
  • 13
  • 24
-1

I guess the method std:remove works but it was giving some compatibility issue with the includes so I ended up writing this little function:

string removeCharsFromString(const string str, char* charsToRemove )
{
    char c[str.length()+1]; // + terminating char
    const char *p = str.c_str();
    unsigned int z=0, size = str.length();
    unsigned int x;
    bool rem=false;

    for(x=0; x<size; x++)
    {
        rem = false;
        for (unsigned int i = 0; charsToRemove[i] != 0; i++)
        {
            if (charsToRemove[i] == p[x])
            {
                rem = true;
                break;
            }
        }
        if (rem == false) c[z++] = p[x];
    }

    c[z] = '\0';
    return string(c);
}

Just use as

myString = removeCharsFromString(myString, "abc\r");

and it will remove all the occurrence of the given char list.

This might also be a bit more efficient as the loop returns after the first match, so we actually do less comparison.

Damien
  • 1,492
  • 10
  • 32
  • 1
    You guess right. Rather than writing your own, better find out why you can't use standard C++ headers. – xtofl Sep 13 '16 at 12:53
  • Well that's a personal opinion xtofl, It's not always good to use 3rd code you actually don't know what it does nor the performances rather than writing what you specifically need. – Damien Sep 18 '16 at 06:09
  • 1
    I understand what you mean. It's humility though that makes me choose for the version that's been reviewed, tested, optimized by professional full time library writers, rather than my own. The _standard_ library can be regarded as required knowledge: its functions as well as its runtime complexity. – xtofl Sep 18 '16 at 18:16
  • Strings aside, It's a C solution to a C++ problem. I don't think this should have been voted down. – Owl Sep 07 '18 at 11:02
-1

70% Faster Solution than the top answer

        void removeCharsFromString(std::string& str, const char* charsToRemove)
        {
            size_t charsToRemoveLen = strlen(charsToRemove);
            std::remove_if(str.begin(), str.end(), [charsToRemove, charsToRemoveLen](char ch) -> bool
                {
                    for (int i = 0; i < charsToRemoveLen; ++i) {
                        if (ch == charsToRemove[i])
                            return true;
                    }
                    return false;
                });
        }
-3
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());

Will remove capital Y and S from str, leaving "ourtring".

Note that remove is an algorithm and needs the header <algorithm> included.

Henno
  • 397
  • 1
  • 7