Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

string erase appends elements with backward iterators

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?

like image 977
Rakete1111 Avatar asked Feb 14 '26 11:02

Rakete1111


1 Answers

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());

like image 182
Rakete1111 Avatar answered Feb 16 '26 23:02

Rakete1111



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!