Need help how to make a remove_if function to "remove_if_not"

Dec 16, 2015 at 3:41pm
So after trying to solve a problem for several hours i am very close. I need to remove all characters that is not alphabetical but currently i am removing all alphabetical characters and keeping everything else.

This is the piece of code that currently removes all alphabetical characters instead of removing all other characters except the alphabetical. Please help me make this a "remove_if_not" function. I have no idea where to start after experimenting a lot.

 
tempbook.erase(remove_if(tempbook.begin(), tempbook.end(), ::isalnum), tempbook.end());
Last edited on Dec 16, 2015 at 3:41pm
Dec 16, 2015 at 3:54pm
Create another function that does the 'not' with isalnum(...) and pass that function.
Dec 16, 2015 at 3:56pm
Yeah i have no idea how to do that. I am new to c++ and need explaining as if i am 3 years old.

Thanks.
Last edited on Dec 16, 2015 at 3:57pm
Dec 16, 2015 at 4:00pm
1
2
3
func notisalnum (para)
return !isalnum(para);
end func
Last edited on Dec 16, 2015 at 4:00pm
Dec 16, 2015 at 4:06pm
I am sorry but i have been sitting with this for so long time and i have no idea what do.


I have been working with c++ for only a couple of days so EVERYTHING is a question-mark for me.

Something like this?
1
2
3
4
5
6
void NotAlphaNum ()
{
  return !::isalnum;
}

tempbook.erase(remove_if(tempbook.begin(), tempbook.end(), NotAlphaNum()), tempbook.end());


I did not get this to work. I am at a loss here. been sitting with code for 12hours so i cant really think anymore heh.
Dec 16, 2015 at 4:08pm
isalnum takes in a parameter. notalphanum should do the same.
Dec 16, 2015 at 4:09pm
NotAlphaNum should have the same return type and parameter has isalnum.
When passing to remove_if, you're passing the function itself, so you don't need the brackets.
Dec 16, 2015 at 4:10pm
Hmm i am not really sure what that parameter should be. Maybe i need to take a break from this and do i again in a few hours. My brain has stopped working. :D
Dec 16, 2015 at 4:11pm
Dec 16, 2015 at 4:12pm
1
2
3
4
5
6
bool NotAlphaNum (char ch)
{
  return (::isalnum(ch) == 0);
}

tempbook.erase(remove_if(tempbook.begin(), tempbook.end(), NotAlphaNum()), tempbook.end());
Dec 16, 2015 at 4:15pm
You say don't what type of container tempbook is, but based on your other posts, I'm assuming it is a string. It doesn't really matter a whole lot as long as the container supports a forward iterator.

You're trying to combine two functions in a way that won't work.
- string.erase() removes a character pointed to by an iterator.
- remove_if() removes those elements that match the predicate.

The code you have is going to result in undefined behavior. tempbook.erase() expects an iterator pointing to the element to be removed from the container. remove_if() returns a new "past end" iterator as its return value, which is what is passed to tempbook.erase() and that is what tempbook.erase is going to try and remove. So tempbook.erase() is going to try and remove an element past the end of the container (string).

To answer your question, simply supply your own predicate to remove_if that returns true if the character is not alphanumeric.

1
2
3
4
5
bool not_alnum (int c)
{  return ! alnum(c);
}

  remove_if (tempbook.begin(), tempbook.end(), not_alnum);

Last edited on Dec 16, 2015 at 6:54pm
Dec 16, 2015 at 5:06pm
You're trying to combine two functions in a way that won't work.
- string.erase() removes a character pointed to by an iterator.
- remove_if() removes those elements that match the predicate.

One version of string.erase() removes a character pointed to by an iterator. Not the version used here. And, perhaps somewhat surprisingly, remove_if doesn't remove anything.

http://en.cppreference.com/w/cpp/string/basic_string/erase
(We're using #3.)


The code you have is going to result in undefined behavior.

Nope!

remove_if() returns a new "past end" iterator as its return value,

What remove_if returns is a valid iterator that, if remove_if actually removed anything, would be the iterator returned by tempbook.end(). But, since it doesn't actually remove anything, we need to erase those elements from that iterator to the end of the string in order to finish the job.

https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
Last edited on Dec 16, 2015 at 5:06pm
Dec 16, 2015 at 6:50pm
Thanks cire
Last edited on Dec 16, 2015 at 6:51pm
Dec 16, 2015 at 8:51pm
Thanks for the help everyone. I needed a few hours rest in order to understand most of the reply:s. Guess i was a bit tired hehe.

I ended up using cire code that he posted in another forum topic and it worked perfect.

1
2
auto not_alnum = [](char ch) { return !std::isalnum(ch); };
tempbook.erase(remove_if(tempbook.begin(), tempbook.end(), not_alnum), tempbook.end());
Topic archived. No new replies allowed.