3

I am trying to remove every '0' in a std::string, starting from the back. According to this, there are multiple ways to .erase backward iterators.

The weird thing is that they all append numbers to the std::string, instead of erasing them!

Here is a little sample

//'str' will be "5.090000"
std::string str = std::to_string(5.09);

auto it = std::remove_if(str.rbegin(), str.rend(), [](char value) {
    return value == '0';
});

1) Pre-C++11 way:

str.erase(--(it.base()));

2) C++11 way (1)

str.erase(std::next(it).base());

3) C++11 way (2)

std::advance(it, 1);
str.erase(it.base());

In all cases, str == "5.095.9". Why? Because as I see it, str should be 5.9, but it isn't...

My best guess is that I am doing something wrong with the backwards iterators, because if you split the string: 5.09 | 5.9, the first value has still the in-between '0', but not the last ones. The second value is actually the std::string I expected.

What I am doing wrong?

Community
  • 1
  • 1
Rakete1111
  • 47,013
  • 16
  • 123
  • 162

1 Answers1

1

I made 2 errors in my approach:

  • erase called with only 1 iterator removes the element the iterator is pointing at, not from the iterator to the end (as I falsely assumed)

So str.erase(std::next(it).base(), str.end()); - this is still wrong, continue reading ;)

  • As @KerrekSB pointed out, I didn't read the docs carefully enough: Because I am using std::reverse_iterator, the elements get pushed back to the front! So, as it points to the new end iterator (which is BTW before the not-removed elements), I have to delete the range from the beginning (str.begin()) to it.base().


TL;DR

The new working version is: str.erase(str.begin(), it.base());

Rakete1111
  • 47,013
  • 16
  • 123
  • 162