Reputation: 23
I've string s="12300" and now I am trying to erase the tail's 0s. So I am trying:
s.erase(s.rbegin(), std::remove_if(s.rbegin(), res.rend(),
[](unsigned char x){
static bool isPrevSymbol0 = true;
if(!isPrevSymbol0)
{
return false;
}
isPrevSymbol0 = (x=='0');
return isPrevSymbol0;
}));
And I am getting this error:
no matching function for call to `std::basic_string::erase(std::basic_string::reverse_iterator, std::reverse_iterator<__gnu_cxx::__normal_iterator > >)`
How to solve the problem?
Upvotes: 2
Views: 460
Reputation: 137315
basic_string
's 150+ member functions are often ridiculed, but since they are there, let's put them to good use:
s.erase(s.find_last_not_of('0') + 1);
Upvotes: 2
Reputation: 48615
It seems the reverse iterators move the bad characters to the beginning of the string (rather than the end) and return the position after which we need to keep the characters.
So you need to erase from the beginning of the string to the value returned by remove_if
.
std::string s = "12300";
s.erase(s.begin(), std::remove_if(s.rbegin(), s.rend(), [](char x){
static bool isPrevSymbol0 = true;
if(!isPrevSymbol0)
return false;
isPrevSymbol0 = (x=='0');
return isPrevSymbol0;
}).base());
std::cout << s << '\n';
Also note we need to convert the returned reverse iterator to its corresponding normal iterator using base()
.
Upvotes: 0
Reputation: 277
A reverse_iterator is not a normal iterator. You have to use the base()
function to use the erase()
function of the std::string
.
An you have to reorder your arguments. You do it the wrong way round.
std::string s="12300";
s.erase(std::remove_if(s.rbegin(), s.rend(),
[](unsigned char x){
static bool isPrevSymbol0 = true;
if(!isPrevSymbol0)
{
return false;
}
isPrevSymbol0 = (x=='0');
return isPrevSymbol0;
}).base(), s.end());
std::cout << s;
EDIT: I think your code is not correct at all. std::remove_if
doesn't break at the first returned false
. I think it is the wrong algorithm for this task.
std::string s="0012300";
s.erase(std::find_if_not(s.rbegin(), s.rend(), [](char c){ return c == '0'; }).base(), s.end());
std::cout << s;
Upvotes: -2
Reputation: 303097
This is simply because std::string::erase
takes a const_iterator
, it doesn't take a reverse iterator. There's just no valid overload.
You need to explicitly convert the iterator from a reverse iterator to a forward iterator, via base()
. And we can do this much more straightforwardly by finding the first non-0
character from the end, and erasing from there:
auto last_non_zero = std::find_if(s.rbegin(), s.rend(), [](char c){ return c != '0'; });
s.erase(last_non_zero.base(), s.end());
// ^^^^^^^
Upvotes: 3