17

I am currently learning C++. I am trying to code a method to remove white spaces form a string and return the string with no spaces This is my code:

string removeSpaces(string input)
{
  int length = input.length();
  for (int i = 0; i < length; i++) {
     if(input[i] == ' ')
        input.erase(i, 1);
  }
  return input
}

But this has a bug as it won't remove double or triple white spaces. I found this on the net

s.erase(remove(s.begin(),s.end(),' '),s.end());

but apparently this is returning an iterator (if I understand well) Is there any way to convert the iterator back to my string input? Most important is this the right approach?

4
  • 2
    I'm pretty sure that does in-place modification of the string s. So it doesn't matter that it returns an iterator. Just change s and return s. Commented May 2, 2013 at 2:23
  • Just an option worth mentioning... unlike say std::vector, std::string has a default (of std::string::npos which acts as a sentinel for "until the end") for the second parameter, so you can simply s.erase(remove(s.begin(),s.end(),' '));. Commented May 2, 2013 at 2:46
  • @TonyD I think your versino is even simpler/ So the last s.end() at the end of the expression s.erase(remove(s.begin(),s.end(),' '),s.end()); is just a sentinel that tells me when the string is finished right? Commented May 2, 2013 at 3:26
  • @lucaConfa: yes, that's right - it tells erase to remove the elements all the way to the end of the string, which is the default behaviour for std::string::erase anyway.... Commented May 2, 2013 at 7:18

7 Answers 7

25

std::string::erase returns an iterator, but you don't have to use it. Your original string is modified.

string removeSpaces(string input)
{
  input.erase(std::remove(input.begin(),input.end(),' '),input.end());
  return input;
}
Sign up to request clarification or add additional context in comments.

3 Comments

ok got it! the input.erase() changes my string and then i can use my modified string. just one thing, hope you can help me with, now I have the following error error: cannot convert ‘__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >’ to ‘const char*’ for argument ‘1’ to ‘int remove(const char*)’
@lucaConfa: Try it with std::remove.
ok got it, sorry, like @bill said I need to include <alogrithm>. Thanks again for the help
10

std::remove_if along with erase would be much easier (see it live):

input.erase(remove_if(input.begin(), input.end(), isspace),input.end());

using std::isspace had the advantage it will capture all types of white space.

4 Comments

but I read that remove does not delete the spaces form the string is that correct?
@mikey I also added a live example so you can see it work in action.
My compiler spat put error: no matching function for call to 'remove_if'. Here's a live link
Remove 'using namespace std;` and qualify everything see it live. You must be bringing in another isspace.
4

Let's assume your input has a double space, for example "c++[ ][ ]is[ ]fun" ([ ] represents a single space). The first space has index 3 (numeration starts from 0) and the second space, is of course index 4.

In your for loop, when you hit i == 3 you erase the first space. The next iteration of the loop takes i == 4 as the index. But is the second space at index 4 now ? No! Removing the first space changed the string into "c++[ ]is[ ]fun": the space to remove is at index 3, again!

The solution can be to remove spaces right-to-left:

for (int i = length-1; i >= 0; --i) {
   if(input[i] == ' ')
      input.erase(i, 1);
}

This solution has the benefit of being simple, but as Tony D points out, it's not efficient.

3 Comments

That makes a lot of sense! Thank you so much, it fixed my problem! Feel a bit dumb. Thank you!
This is very inefficient on large strings with lots of whitespace (e.g. if you had a couple megabytes of numbers in CSV format that you wanted to compact), as each erase has to shift all the characters beyond that point. With more care, you can do one forwards pass with two pointers - one tracking the compacted string positions and the other the next uncompacted character, then just erase the trailing characters afterwards. The erase/remove idiom Vaughn documents does that.
@TonyD I think I understand what you mean. I'll use the erase/remove idoim in my code even though the size and the number of the string I have to deal with is very small. I have to work more on pointers!
3

this should also work -- std::replace( input.begin(), input.end(), ' ', ''); You need to include <algorithm>

5 Comments

No. '' is an empty character constant.
here you are replacing a space with a empty char? which would be better? removing or replacing? Thanks for the include thing, I missed that.
i guess removing may be a better option than replacing with null...since you can not replace with '' (empty char const).
Replacing with NUL is typically not useful behaviour... when you write out the string later, or attempt to do finds, iteration, size etc. - all the NULs will still be considered - giving very different results to a string in which the whitespace has been removed. If you pass &input[0] or input.c_str() to a function expecting an ASCIIZ paramter - like ifstream's constructor, printf, fstat etc. - only the text up until the first NUL will be used....
yes, agree with everything you said about the side effects of using nulls.
0

this code should work

string removeSpaces(string input)
{
  int length = input.length();
  for (int i = 0; i < length; i++) {
     if(input[i] == ' ')
     {
        input.erase(i, 1);
         length--;
         i--;
     }
  }
  return input
}

Reason: if it gets space in the string it will reduce the length of the string, so you have to change the variable: "length" accordingly.

Comments

0

I tried to write something to. This function take a string and copy to another temporary string all the content without extra spaces.

std::string trim(std::string &str){
int i = 0;
int j = 0;
int size = str.length();
std::string newStr;
bool spaceFlag = false;

for(int i = 0;i < size; i++){
    if(str[i] == ' ' && (i+1) < size && str[i+1] == ' '){
        i++;
        spaceFlag = true;
        continue;
    }       
    if(str[i] == ' '){
        newStr += " ";
        continue;
    }
    if(str[i] == '\t' && i != 0){
        str[i] = ' ';
        newStr += " ";
    }
    else{
        newStr += str[i];
        if(spaceFlag){
            newStr += " ";
            spaceFlag = false;
        }
    }
}
str = newStr;

return str;

}

Comments

0
#include<iostream>
#include<string.h>
using namespace std;

void trimSpace(char s[])
{
    int i=0, count=0, j=0;

    while(s[i])
    {
        if(s[i]!=' ')
            s[count++]=s[i++];
        else {
            s[count++]=' ';

            while(s[i]==' ')
                i++;
        }       
    }   

    s[count]='\0';
    cout<<endl<<"  Trimmed String : ";  
    puts(s);
}

int main()
{
    char string[1000];
    cout<<"  Enter String : ";
    gets(string);
    trimSpace(string);

    return 0;
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.