I have this code:
#include <iostream>
us开发者_开发知识库ing namespace std;
int main()
{ char c='6';
if(c == '+' || '-' || '*' || '^' || '/' || '%')
{
cout<<"good";
}
else {cout<<"bad";}
return 0;
}
I want to write "good" if the char is '+' or '-' etc, and write "bad" if the char is anything else. But this code writes "good" always with any char.
Where is the problem? Thanks.
if(c == '+' || '-' || '*' || '^' || '/' || '%')
parses to
if( (c == '+') || ('-'!=0) || ('*'!=0 || ('^'!=0) || ('/'!=0) || ('%'!=0))
It will always evaluate to true because '-' is indeed not equal to zero. Of course it's a sort of flaw with the type-safety that a char "degrades" to a boolean and evaluates to true. (The proper type-safe solution would be simply not to compile your code unless you explicitly cast).
What you wanted to know was whether c is one of those values. There are many ways to do that. Apart from an indented if you could use a library feature:
C function strchr:
if( strchr( "+-*^/%", c ) != NULL )
switch statement
switch (c )
{
case '+': case '-': case '*': case '^': case '/': case '%':
// true logic
break;
default:
// false logic
};
regex
(overkill here but purists would like it).
std::bitset
This takes a lot of "setup" but if you have a fixed set of chars and lots of variable chars to see if it exists in the set, this is the quickest way to do it.
// one-time setup
std::bitset<256> myCharSet;
myCharSet.set('+');
myCharSet.set('-');
myCharSet.set('*');
myCharSet.set('^');
myCharSet.set('/');
myCharSet.set('%');
// subsequently
if( myCharSet.test( static_cast<unsigned char>(c) ) )
{
// true logic
}
else
{
// false logic
}
static array
Similar solution to bitset but you don't mind wasting a few bytes. static bool charset[256] = { false }; static bool init = false; if( !init ) { charset['+'] = true; // etc init = true; }
if( charset[ static_cast<unsigned char>(c) ] )
{
// true logic
}
else
{
// false logic
}
And you could make a class that does this that initialises from a string of the characters you want to check for (plus some logic as to whether a 0 byte is true or false, if the string you pass is null-terminated).
As with bitset this is constant-time lookup.
There are other options (eg with C++ std::string class using find and std::find) but these will do for now.
Change your if to:
if(c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%')
or better yet:
switch (c)
{
case '+': case '-': case '*' : case '^' : case '/' : case '%':
cout << "good\n"; break;
default: cout << "bad\n"; break;
}
it should be
if(c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%')
...
otherwise the expression is always evaluating to true. Any of those characters have a value different from 0, so true for c++.
Simple answer:
'-' is the ASCII (the way the computer encodes character) value of that character - which is not 0 therefore it's true (computer's logic).
Same for all the other characters. So we got:
c == '+' || true || true || true || true || true which is always true.
What you should've done:
c == '+' || c == '-' || c == '*' || c == '^' || c == '/' || c == '%'
The mistake was probably you thinking "It needs to be equal to this or that or that or that" and so on. This happened to everyone, just remember that computers don't speak English.
精彩评论