9

I'm trying to do an if statement inside a loop with an iterator over a string, but can't figure out how to get the current character for the if statement:

for (std::string::iterator i=buffer.end()-1; i>=buffer.begin(); --i) {
    if (!isalpha(*i) && !isdigit(*i)) {
        if(i != "-") { // obviously this is wrong
            buffer.erase(i);
        }
    }
}

Can someone help me get the current character so I can do some additional if statements?

1
  • you don't really need the isalpha and isdigit check if you are going to check for a specific character right afterward Commented Mar 24, 2011 at 17:17

5 Answers 5

20

I can't figure out how to get the current character

You do it twice here:

if (!isalpha(*i) && !isdigit(*i))

When you dereference an iterator (*i), you get the element to which it points.

"-"

This is a string literal, not a character. Character constants use single quotes, e.g., '-'.

for (std::string::iterator i=buffer.end()-1; i>=buffer.begin(); --i)

This would be much simpler with reverse iterators:

for (std::string::reverse_iterator i = buffer.rbegin(); i != buffer.rend(); ++i)
Sign up to request clarification or add additional context in comments.

6 Comments

if((*i) != '-')) in case you need more clarification
@P.R.: Good catch on the "-".
@James Thank you :) I used to be a lab instructor for a C++ course and I guess now the first things my eyes go to are the '' and ==
Using a reverse_iterator will be simpler for the iteration, but it will be less simple to erase elements.
@David Rodríguez While using a forward iterator makes erase simpler, it also makes the loop illegal because it will decrement the iterator to before begin.
|
4
if(i != "-")

should be

if(*i != '-')

Comments

2

To get the character just say *i, but this isn't enough. Your loop isn't legal because it's not allowed to decrement before begin. You should use reverse iterators or the remove_if algorithm.

Comments

2

Other answers have solved the particular issue that you have, but you should be aware that there are different approaches to solve your actual problem: erase elements that fullfill a condition. That can be easily solved with the remove/erase idiom:

// C++0x enabled compiler
str.erase( 
    std::remove_if( str.begin(), str.end(), 
                  [](char ch) { return !isalpha(ch) && !isdigit(ch) && ch != '-' } ),
    str.end() );

While this might look cumbersome at first, once you have seen it a couple of times it will no longer be surprising, and it is an effective way of deleting elements from a vector or string.

If your compiler does not have lambda support, then you can create a functor and pass it as the third argument to remove_if:

// at namespace level, sadly c++03 does not allow you to use local classes in templates
struct mycondition {
   bool operator()( char ch ) const {
      return !isalpha(ch) && !isdigit(ch) && ch != '-';
   }
};
// call:
str.erase( 
    std::remove_if( str.begin(), str.end(), mycondition() ),
    str.end() );

Comments

1

You have it right above in the previous if statement: i is an iterator, so *i gives the character referred to by the iterator.

Note that if you're going to iterate through a collection backwards, it's generally easier to use a reverse_iterator with rbegin and rend. I'd probably use a pre-packaged algorithm instead though.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.