简体   繁体   中英

How to correctly shorten an if-statement in C++?

Okay, I have an if sentence in which I compare a specific value multiple times. I bet there is a shorter way to do this:

if(letter == "%" || letter == "+" || letter == "-" || letter == "!")

I tried writing it as:

if(letter == "%" || "+" || "-" || "!")

But it works incorrectly.

Something like this might work:

string s("%+-!");
if (s.find(letter) != string::npos) { ... } 

That's as short as it can. You could rewrite it though, with some help from Boost it could be

if( boost::is_any_of( "%+-!" )( letter ) )

Try a switch statement in-stead of an if. It's not less typing, but it does allow you to write "letter" only once. Some programmers like the visual layout of a switch statement. Note of caution, switch only works on scalar types like char (not std::string).

switch (letter)
{
  case '%':
  case '+':
  case '-':
  case '!':
     // if letter is %,+,-,!
     // code goes here for matching letter 
     break;
  default:
     // else do something different
     // code goes here for letter that doesn't match
}

See bottom of page at http://www.cplusplus.com/doc/tutorial/control/ for a similar example.

char op[4] = { '%', '+', '-', '!' };
char * opEnd(op + 4);
if (opEnd != find(op, opEnd, letter))

Alternatively:

if (string("%+-!").find(letter) != string::npos)

The problem is that either side of the || operator has no knowledge of each other. They're two completely independent expressions. Consequently "+" etc. always evaluate as true (think of what would happen if you just wrote if ("+") - it decays to a pointer which is non- NULL )

Sometimes I find it is cleaner to express this kind of problem using std::find and pair of iterators:

#include <iostream>
#include <algorithm>

void test(const char letter) {
  static const char c[] = {'%', '+', '-', '!'};
  static const char *begin=c, *end=&c[sizeof(c)/sizeof(*c)];
  if (std::find(begin, end, letter) != end) {
    std::cout << "Matched " << letter << std::endl;
  }
}

int main() {
  test('a');
  test('%');
  test('!');
}

I guess the end result is to type as little as possible and attempt to keep your code quick to comprehend by using something familiar like English.

Your code reads something like,'is my letter equal to this and this and this and this'. It may be a bit long winded but it is quite quick to comprehend.

Unfortunately c++ compilers don't really do 'is my letter equal to these'. Which may be English to most of us but not to poor compilers :)

As a programmer you have the power to hide the compiler literacy shortfalls, keep your code comprehendable and also type less.

 if( letterIsOneOfThese( letter, "%+-!") )
 {
    // do something

 }


bool letterIsOneOfThese( const char letter, const char* letterList ) 
{
    int len = strlen( letterList );
    while( len-- )
    {
        if( letterList[len] == letter )
        {
            return true;
        }
    }

    return false;

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM