Reputation: 23
Sorry if this is a noob question or formatted strangely, I'm new to programming and also new to StackOverflow. So my brother and I were trying to code a short program that utilizes a do-while loop and a switch statement within it. This is a short version of the code that illustrates the issue we were having.
#include <iostream>
int main()
{
char selection{};
do {
std::cin >> selection;
switch (selection) {
case 'P':
case 'p':
std::cout << "This doesn't work";
case 'Q':
case 'q':
std::cout << "Okay, goodbye!";
break;
}
} while ( selection != 'Q' || selection != 'q');
}
What we are confused by is when we run this program, selecting Q or q does not quit out of the loop like we had hoped. If I'm not mistaken (most likely mistaken) "!=" is basically saying "not equal to". So the last line of the while should be equivalent to "while selection is not equal to Q or selection is not equal to q" in which whenever selection does equal Q or q, the while evaluates to false, and the loop is exited.
However, the loop never evaluates to false when we run it, and just goes on forever asking us for a selection. After a good hour or so of googling we came to one of two solutions that runs the way we want it to. Either A: while (!( selection == 'Q' || selection == 'q')) of B: while (selection != 'Q' && selection != 'q'). In either case, the loop is exited successfully and the program runs the way we want it to.
This is great, but no matter what we read online, we couldn't find a good explanation for why the original code does not run the way it seems it should. My bro and I came to the conclusion that it either has something to do with precedence/associativity or the way logical operators interact with each other. If anyone can give us an educated answer on why the original code does not run the way we thought it should, we will greatly appreciate it.
Upvotes: 2
Views: 613
Reputation: 41
NOT(A) OR NOT(B) is same as NOT(A AND B)
you can draw a Venn Diagram to verify the above. Your (A AND B) reads as selection is ‘q’ and ‘Q’ simultaneously. This is always false.
And not of false is true. Hence the infinite loop.
Upvotes: 0
Reputation: 41271
Read the condition (selection != 'Q' || selection != 'q'
) very carefully, token by token:
"do... while the selection not equal to 'Q'
OR while it's not equal to 'q'
".
Since selection can't be q and Q at the same time, it's always the case that it's either not equal to q, or not equal to Q, or both.
Your intention is to say "do ... while the selection is neither 'q' nor 'Q'". It can be translated as:
!(selection == 'q' || selection == 'Q')
Applying a DeMorgan identity allows you to rewrite this as:
(selection != 'q' && selection != 'Q')
which is structurally similar, but subtly different from your original condition since it uses &&
rather than ||
. The difference is a simple and common1 misunderstanding of boolean logic/boolean algebra, rather than operator precedence or associativity.
1 From the context of tutoring digital design in an ECE department, as well as tutoring CS
Upvotes: 11
Reputation: 182753
} while ( selection != 'Q' || selection != 'q');
This will always be true. Every character is either not Q or not q. You probably wanted an &&
in there. You want to loop if the selection is both not Q and not q.
Let's look at a few cases:
selection . . . selection!='Q' . . selection!='q' . . . result of OR
X . . . . . . . . . true . . . . . . . . . . . true . . . . . . . . . . .. true
q . . . . . . . . . true . . . . . . . . . . . false . . . . . . . . . . . true
Q . . . . . . . . .false . . . . . . . . . . .true . . . . . . . . . . .. true
z . . . . . . . . . true . . . . . . . . . . . true . . . . . . . . . . .. true
See the problem? The result of the ||
is always true, so your loop never ends.
Upvotes: 6