Logical OR operator

Started by
19 comments, last by Boooke 12 years, 1 month ago
Hello. I'm currently reading the Primer Plus 5th Edition. I'm currently stuck at the listing 6.4. It goes something like this,


#include <iostream>
int main()
{
using namespace std;
cout << "This program may reformat your hard disk\n"
"and destroy all your data.\n"
"Do you wish to continue? <y/n> ";
char ch;
cin >> ch;
if (ch == 'y' || 'Y')
cout << "You were warned!\a\a\n";
else if (ch == 'n' || 'N')
cout << "A wise choice ... bye\n";
else
cout << "That wasn't a y or n, so I guess I'll "
"trash your disk anyway.\a\a\a\n";
return 0;
}


The problem is, no matter what the input will be, the program will always execute the first if-loop. So an input of 'n' or 'a' will result in the output "You were warned!". I have encountered this problem with the or operator in my own programs (On two different computers actually), and often thought I was just misusing it, but somehow I wonder if it's not me, and maybe some kind of bug? I suspect the OR operator since, if I remove it in all of the loops and leave only one char for each loop ('y' and 'N' for instance), the problem will disappear.

I am using Code::Blocks 10.05 (rev 6283) with the GNU GCC version 0.99 compiler (Which came with the Code::Blocks bundle). Hope someone can explain what is happening here.

Best regards,
Boooke
Advertisement
It should be:
(ch == 'y' || ch == 'Y')

@Down: a few secs. smile.png
(( I am learning English. ))
Change it to:

if (ch == 'y' || ch == 'Y')

/EDIT: Too slow, too slow.
C++ sucks.

'Y' is a simple ascii character, value of 89. Since that's not zero, C++ allows implicit conversion of 89 into 'true'. So no matter what ch == 'y' is, the other side of the operator is true, thus the conditional is always true.
[color=#000000]ch [color=#666600]==[color=#000000] [color=#008800]'y'

[color=#000000]In C++, this is an example of an "expression". This one evaluates to TRUE.

[color=#008800][size=2]

'Y'


Even a literal value can be considered an expression. This one evaluates to the character 'Y', which has the value TRUE if converted to a boolean (which is the case for anything non-zero converted to a boolean).

The || operator expects an expression on either side: a || b , where a and b are both expressions which are to be evaluated. The values of a and b are considered as booleans. If either are TRUE then the value of a || b is also TRUE. C++ will check a first and not actually go to the trouble of working out the value of b if a is TRUE.

a || b is also an expression - they are like Russian dolls stacked inside each other.



[color=#000000]ch [color=#666600]==[color=#000000] [color=#008800]'y'[color=#000000] [color=#666600]||[color=#000000] [color=#008800]'Y'

This expression from inside your 'if' is therefore equivalent to (ch == 'y') || ('Y'), or (expression which may be TRUE) || (TRUE).
Ah, I understand now. Seems logical enough, though. Thank you for all the replies. It really helped clear a lot of trouble :-) Could you say something like ch == ('y' || 'Y') in such a loop? Gonna try it out when I get near an IDE.

Edit: Nope you can not :-(
Like ||, the == operator expects an expression on either side. a == b evaluates both expressions first, compares the values and returns TRUE if they are equal.

You cannot use || to chain together values into a list of possible options like this. (a || b) does not mean of "a value which is either a or b", instead think of (a || b) as a true/false question which has to be answered before moving on: if (a is equal to TRUE) or (b is equal to TRUE) then the answer is TRUE else it's FALSE.

Generally the computer has to work out the values of things one by one - the various sub-expressions which make up a larger expression have to be evaluated (literally given a value and stored somewhere) in a particular order, just like a person would when working through a maths problem with lots of brackets etc.
While what has been said above is true and useful, if you want to have an option be activated by both lowercase and uppercase letters, you can use the toupper function to avoid having to compare against both lowercase and uppercase letters. This is useful if you have a lot of options, as it eliminates the possibility of you (or someone else working on a program you wrote) forgetting to put in a test for either the lowercase or uppercase.
An interesting newbie-friendly heuristic could be applied: there is no way to add parentheses in a way that makes any sense, so the expression must also be wrong without them.
ch == 'y' || 'Y'
Deceptively symmetrical.
ch == ('y' || 'Y')
Logical OR of two char constants? Whatever it does, it's not something I want to compare ch with; "at best" it is 'y' or 'Y', and I'm making only one of the two comparisons.
(ch == 'y' )|| 'Y'
Logical OR of operator == and a char constant? No, I want operator == on both sides.

Omae Wa Mou Shindeiru

Things are similar with the bit-wise OR. Because of
'y' in ASCII / UTF-8 is 79[sub]hex[/sub]
'Y' in ASCII / UTF-8 is 59[sub]hex[/sub]
the difference is just 20[sub]hex[/sub], what is typical for all latin letters. Hence
( ch | 0x20 ) == 'y'
can be used to check for both 'y' and 'Y'. However, also here the parentheses are required, or else the == would be evaluated before the |.


EDIT: Well, I'm aware of the above being not a direct answer to the OP, also IMHO previous posts have given ample answers already. The above stuff came to my mind during reading RulerOfNothing's post about using toupper, because the above code is a kind of tolower-operator (although working for latin letters in said encodings only). So feel free to ignore it.

This topic is closed to new replies.

Advertisement