In my introductory computer science class, a prompt asked us:
"Given a char variable c that has already been declared , write some code that repeatedly reads a value from standard input into c until at last a 'Y' or 'y' or 'N' or 'n' has been entered."
The code I entered causes an infinite loop, but the logic makes sense to me. Can somebody please explain why the following Boolean expression is faulty?
while (c != ('n' || 'N' || 'y' || 'Y'))
cin >> c;
Because that expression does not do what you think it does. The correct is
while (c !='n' && c != 'N' && c!= 'y' && c != 'Y')
But what happens with the one you present above?
('n' || 'N' || 'y' || 'Y')
This is a series of 4 boolean ORs. The first one is 'n' || 'N', where the chars 'n' and 'N' are converted to booleans (both true), therefore the whole expression is true.
So you are left with
while (c != true)
which is the same as c != 1, and goes into a loop until you input the character with ASCII value 1. Since that is not a printable character, no input from the keyboard is going to get you out of the loop.
This:
while (c != ('n' || 'N' || 'y' || 'Y'))
is equivalent to:
while (c != true )
because any group of values ORd together is going to evaluate to true when one or more of them is non-zero. What you're probably looking for is:
while ( c != 'n' && c != 'N' && c != 'y' && c != 'Y' )
The condition in your loop is incorrect.
The correct condition is:
while ( c != 'n' && c != 'N' && c != 'y' && c != 'Y' )
{
// ...
}
When you write:
while (c != ('n' || 'N' || 'y' || 'Y'))
You ask if c is different from ('n' || 'N' || 'y' || 'Y'). But this expression itself will be evaluated as true because non-zero values ORd together are always evaluated as true. So your condition is equivalent to:
while( c != true )
Wich will lead to an infinite loop...
Try
while (c !='n' && c!='N' && c!= 'y' && c!='Y')
cin >> c;
You are "OR"ing 'n','N','y','Y' which always equals to true ( non zero). This is reason The loop is not terminating.
Related
This question already has answers here:
Most efficient way to compare a variable to multiple values?
(7 answers)
Why is if statement not working [duplicate]
(2 answers)
Closed 11 months ago.
I'm 100% sure from testing that for loop does iterate through characters how is it suposed to, but the other part of the program isn't working correctly.
Im trying with if statement to print only uppercase characters.
Here are some input/output samples to get a better pitcure what this program is about:
Input: Tim-Berners-Lee Output: TBL
Input: Albert-Einstein Output: AE
Here is the code:
#include <iostream>
#include <string>
using namespace std;
int main(){
string name;
cin >> name;
int N = name.length();
for (int i = 0; i < N; i++)
{
if (name[i] == 'A' || 'B' || 'C' || 'D' || 'E' || 'F' || 'G' || 'H' || 'I' || 'J' || 'K' || 'L' || 'M' || 'N' || 'O' || 'P' || 'Q' || 'R' || 'S' || 'T' || 'U' || 'V' || 'W' || 'X' || 'Y' || 'Z'){
cout << name[i];
}
}
}
Your code will calculate compare name[i] == 'A' first and then take
the result to do OR operation with 'B', 'C', and so on..., which absolutely won't work.
You should do name[i] == 'A' || name[i] == 'B' || ... or just use std::isupper().
Why is this an infinite loop using || logical operator
char c;
std::cin >> c;
while( c != 'y' || c != 'Y' || c != 'N' || c != 'n')
but this is not
while( c != 'y' && c != 'Y' && c != 'N' && c != 'n')
I don't understand why && operator work here because logically thinking || operator is better fit.
Lets just look at the very smallest part:
c != 'Y' || c != 'N'
If c is 'Y' then it is not 'N', if it is 'N' then it is not 'Y'. Aka:
c | c != 'Y' || c != 'N'
Y | 1 || 0 = 1
N | 0 || 1 = 1
? | 1 || 1 = 1
If your logic always returns 1 no matter what, the loop will run forever. I assume you are looking to wait until you get c as one of these values, so write it logically.
I want to wait until c is one of ['y', 'Y', ...]
And you might be able to write some nicer code:
std::array<char> options = {{'y', 'Y', 'n', 'N'}};
while (std::none_of(std::begin(options), std::end(options),
[&c](char check) { return check == c; };)) {
std::cout << "Hey write the correct character!\n";
}
Untested!
You are checking the condition which is always true by using || operator,
( c != 'y' || c != 'Y' || c != 'N' || c != 'n')
This is always true ,because it would always satisfy at-least 3 conditions in your conditional statement .
if your char is n then it would satisfy remaining conditions
c!='y' , c!='Y' , c!='N' and similarly for any other character
here's a simple logic error I can't quite wrap my head around:
Why does the following statement always equate to true?
if ( (grid[i][0] && grid[i][1] && grid[i][2]) == ('X' || 'x') ) return true;
It works flawlessly for
if ( (grid[i][0] && grid[i][1] && grid[i][2]) == ('X') return true;
Do it like this:
create a function to check a character of being x:
bool isX(char c)
{
return c == 'X' || c == 'x';
}
and the you can write:
if ( isX(grid[i][0]) && isX(grid[i][1]) && isX(grid[i][2]))
return true;
That's because the expressions
'X' || 'x'
and
grid[i][0] && grid[i][1] && grid[i][2]
use the || and && operators between non-zero integer-typed values (because char is an integer type) and so they both evaluate to true.
To translate into C++ (or almost any other somewhat similar language, for that matter) that you want characters x, y and z to be equal to either of the characters c and C, you must compute
(x == c || x == C) && (y == c || y == C) && (z == c || z == C)
so apply that to your problem.
More importantly though, learn about boolean operators and programming in general before you try to tackle C++.
In the first case, it returns true because none of the grid elements has the value of zero. The && operator produces 0 or 1, depending on the values that you pass.
In the second case, it does not work as expected either: you wouldn't get an 'X' by &&-ing values together.
The proper way of checking if three items are equal to 'X' or not would be as follows:
if (toupper(grid[i][0]) == 'X'
&& toupper(grid[i][1]) == 'X'
&& toupper(grid[i][2]) == 'X') {
return true;
}
To generalize the concept of "win" in TiCTacToe, write a function that returns true when a sequence of three items with a specific step in each direction holds a sequence of a given character, like this:
bool isWin(int r, int c, int dr, int dc, char ch) {
return toupper(grid[r+0*dr][c+0*dc] == ch
&& toupper(grid[r+1*dr][c+1*dc] == ch
&& toupper(grid[r+2*dr][c+2*dc] == ch;
}
bool isWin(char ch) {
return isWin(0,0,0,1,ch)
|| isWin(0,0,1,0,ch)
|| isWin(1,0,0,1,ch)
|| isWin(0,1,1,0,ch)
|| isWin(2,0,0,1,ch)
|| isWin(0,2,1,0,ch)
|| isWin(0,0,1,1,ch)
|| isWin(2,0,-1,1,ch);
}
int main (void)
{
char n;
label0:
cout<<"Please enter a character value(C/S)\n";
cin>>n;
n = toupper(n);
if ( n!= 'C' || n!= 'S' )
{
cout<<"Please enter proper value\n";
cin.clear();
cin.ignore();
goto label0;
}
else
{
cout<<"You entered"<<n<<"\n";
}
return 0;
}
In this code, even when I enter c C s S , it gives the same output as Please enter the proper value. Why is it not comparing?
if ( n!= 'C' || n!= 'S' )
This is true for every n in the world. You probably meant to use &&.
Think about it:
if n == 'C', then the condition is satisfied since n != 'S',
if n == 'S', then the condition is satisfied since n != 'C',
if n == 'X', then the condition is satisfied since n != 'C',
...
Read more about short circuit evaluation.
In general, you are having trouble by understanding the way in that logical operators are used.
The condition n != 'C' is equivalent to !(n == 'C').
Thus, the if() condition in your code can be rewritten in this way:
if ( !(n == 'C') || !(n == 'S') )
However, the condition you need in your code is another one:
if ( ! (n == 'C' || n == 'S') )
I suggest to do the job in reverse order:
if ( n== 'C' || n== 'S' )
{
cout<<"You entered"<<n<<"\n";
}
else
{
cout<<"Please enter proper value\n";
cin.clear();
cin.ignore();
goto label0;
}
In this way, if the entered character is c C s S, then the character is correct, and in any other case, a new character must be entered.
On the other hand, the goto statements must be used only in excepcional cases, when the flow of the program becomes very intrincated, and one really need "to jump out of the mess".
However, your program is very simple, and can be achieved with normal loop control sentences, such as do {} while():
int main (void)
{
char n;
do {
cout<<"Please enter a (proper) character value(C/S)\n";
cin>>n;
n = toupper(n);
cin.clear();
cin.ignore();
} while ( ! (n == 'C' || n == 'S') );
cout<<"You entered"<<n<<"\n";
return 0;
}
Now, the user is enforced to enter one of the desired characters: c C s S, until the entered character is correct.
The result prints out 'c' 3 times, anyone know why it always meets the first condition?
#include <iostream>
using namespace std;
char x(char y)
{
if (y == 'a' || 'b')
{
return 'c';
}
else if (y == 'c' || 'd')
{
return 'e';
}
else
{
return 'g';
}
}
int main()
{
cout << x('a') << endl;
cout << x('c') << endl;
cout << x('p') << endl;
return 0;
}
You need something of the form
if (y == 'a' || y == 'b')
This is because in this expression
(y == 'a' || 'b')
you are evaluating an OR of y == 'a' and 'b', and since 'b' evaluates to true by virtue of being non-zero, the whole expression evaluates to true.
(y == 'a' || true)
This line:
if (y == 'a' || 'b')
is equivalent to:
if ((y == 'a') || ('b'))
That's because the == operator has higher precedence than the || operator.
Since 'b' is non-zero, it always evaluates as true, and so (y == 'a' || 'b') always evaluates as true.
You need to write this:
if (y == 'a' || y == 'b')
Of course, even if the precedence was the other way around,
if (y == ('a' || 'b'))
would not have been what you intended either!
Please check the operator precedence (priority) here: http://en.cppreference.com/w/cpp/language/operator_precedence
In your case the condition expression is:
(y == 'a' || 'b')
So the “y == 'a'” part is evaluated first which may be true/false depending on the value of "y". Let's call the value of "y=='a'" as "t". And then the expression is evaluated as " t || 'b'" in this case 'b' is actually the ASCII code value of character 'b' (98) which is surely larger than 0, so the result of the boolean expression is always true.
To dismiss any ambiguity caused by operator precedence, I think it's a good habit to use brackets to explicitly express your priority in the evaluation. In your case, as suggested by earlier post, it should be:
if ((y=='a') || (y=='b'))