0

This is the code that I've written to remove spaces in the given string. It normally works.

   string a = "hello  there world";
   int n = a.size();
   for(int i =0 ;i<n;++i){
       if(a[i] == ' '){
           a.erase(a.begin()+i);
       }
   }
   cout<<a;

But for the given input above ( note that there are two spaces between "hello" and "there" ), my output is:

 hello thereworld

"hello" and "world" still have a single space between them.

Is this behaviour normal? Is it something to do with erase ?

  • After removing the space at index `5`, the spacing originally at index `6` is moved to the left, so it is left as-is after `++i`. – L. F. Sep 05 '20 at 10:54
  • 1
    *This is the code that I've written to remove spaces in the given string* -- You know you could have simply done: `a.erase(std::remove(a.begin(), a.end(), ' '), a.end());` – PaulMcKenzie Sep 05 '20 at 10:57
  • No, I didn't. Thanks for the one liner. So remove() essentially removes the specified character and returns an iterator pointing to the beginning of the string? – user 123fer Sep 05 '20 at 11:01
  • The `std::remove` actually moves the characters to the end of the container and returns an iterator to where the removed characters start. In general, if you are writing code to do something you know has been done thousands, if not millions of times before, there usually is an STL algorithm function or set of functions that do the job. Erasing certain characters from a sequence is just one of those things. – PaulMcKenzie Sep 05 '20 at 11:02
  • Does remove_if have any significant advantage over remove? – user 123fer Sep 05 '20 at 11:11
  • 1
    @PaulMcKenzie `std::remove` doesn't move elements to the end of the container. The only data movement is good elements move to the left, overwriting "removed" values. Elements after the new logical end have unspecified values. It's not a partition algorithm. – Blastfurnace Sep 05 '20 at 11:42
  • @user123fer `std::remove` takes a value and `std::remove_if` takes a predicate (a callable thing that returns a `bool`). It's not that one has an advantage, they do different things. – Blastfurnace Sep 05 '20 at 11:55
  • Consider changing your algorithm to remove the right-most spaces first. – 2785528 Sep 05 '20 at 12:32
  • @Blastfurnace -- Yes, you're right. Got my algorithm specifics mixed-up. The `remove` does leave unspecified elements. – PaulMcKenzie Sep 05 '20 at 17:34

2 Answers2

0

No but your problem is that you loop forwards and ignore the fact that the string that you are looping over changes while you loop.

After you erased a space, the rest of the string shifts one position backwards, but you consider the current character as already checked, even though you just changed it.

So you essentially never check any character that immediately follows a space, hence why the second space in a row is not removed.

If you would loop backwards through the string (or manually decrement i after you erased a space), it would work.

Also note that for the same reason it is wrong that you save a.size() in a variable n beforehand, since it changes every time you remove a space. You should either decrement n after you erase a space or check i < a.size() instead of i < n in the loop condition. (If you would loop backwards, it would be fine though.)

So bottom line is that the easiest way to fix both issues is to loop backwards instead of forwards:

for (int i = n - 1; i >= 0; i--) 
CherryDT
  • 25,571
  • 5
  • 49
  • 74
0

You are overstepping the second space after erasing the first one, because you immediately increment the index i.

It will work correctly if, for example, you modify the loop so that in the case of finding a space, you don't increment i but decrement n instead, as the next character after the one you remove has then the same index, and the string is shorter by one.