If always returns true [duplicate] - c++

This question already has answers here:
Most efficient way to compare a variable to multiple values?
(7 answers)
Closed last year.
I'm just experimenting a bit with C++ but I can't figure out why both if-statements return true:
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
cout << "Language?" << endl;
string lang;
cin >> lang;
if(lang == "Deutsch" || "deutsch")
{
cout << "Hallo Welt!";
}
else
{
return false;
}
if(lang == "English" || "english")
{
cout << "Hello World!";
}
else
{
return false;
}
return 0;
}
I'm pretty new to C++ and stackoverflow so I'm sorry if that's an stupid or frequently asked question but I really don't know any further. Please help!

lang == "Deutsch" || "deutsch"
is wrong
lang == "Deutsch" || lang == "deutsch"
is right
"deutsch" alone returns the address of the string in memory. which is
always not equal to zero. which means true.
a == "hello" || "bob"
means
(a == "hello") || "bob"
regardless of what a == "hello" results in (true or false), false || "bob" becomes false || pointer to "bob". All non-null pointers are true, so this is false || true which is true.
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
cout << "Language?" << endl;
string lang;
cin >> lang;
if(lang == "Deutsch" || lang == "deutsch")
{
cout << "Hallo Welt!";
}
else
{
return false;
}
if(lang == "English" || lang == "english")
{
cout << "Hello World!";
}
else
{
return false;
}
return 0;
}

The expression lang == "Deutsch" || "deutsch" is actually equivalent to (lang == "Deutsch") || ("deutsch"). The second part of the expression is a const char* with a non-zero value, which means it will evaluate to true. The same applies to your second if statement.
You meant to write lang == "Deutsch" || lang == "deutsch".

The sentence:
if(lang == "Deutsch" || "deutsch")
is interpreted by the compiler as this:
"IF lang is equal to "Deutsch" OR the memory address of the string "deutsch" is not equal to 0 THEN...
Remember that in C/C++ any expression that is not zero, is considered to be TRUE. The expression "deutsch" is a string constant, which as an expression, returns its starting address, which is likely not 0.

The condition in the if statement
if(lang == "Deutsch" || "deutsch")
is equivalent to the following condition
if( ( lang == "Deutsch" ) ||( "deutsch" ) )
Independing on whether the left subexpression of the operatir || will yield true of false the right subexpression is always yields true because string literals used in expressions are converted to pointers to their first characters. And because the address of a string literal is not equal to 0 then the subexpression is converted to boolean value true.
It is obvious that you mean the following condition
if(lang == "Deutsch" || lang == "deutsch")
According to the C++ Standard (4.12 Boolean conversions)
1 A prvalue of arithmetic, unscoped enumeration, pointer, or
pointer to member type can be converted to a prvalue of type bool. A
zero value, null pointer value, or null member pointer value is
converted to false; any other value is converted to true.
And (5 Expressions)
9 Whenever a glvalue expression appears as an operand of an operator
that expects a prvalue for that operand, the lvalue-to-rvalue (4.1),
array-to- pointer (4.2), or function-to-pointer (4.3) standard
conversions are applied to convert the expression to a prvalue.
Take into account that string literals in C++ have types of constant character arrays as it is said in the quote they are converted to pointers in expressions.
Also you need to include header <string> and should exclude header "windows.h" because neither declaration from the header is used in the program.
Your program then it could be written the following way
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Language?" << endl;
string lang;
cin >> lang;
if ( lang == "Deutsch" || lang == "deutsch" )
{
cout << "Hallo Welt!" << endl;
}
else if ( lang == "English" || lang == "english" )
{
cout << "Hello World!" << endl;
}
return 0;
}

The parts on either side of the || are evaluated as separate boolean expressions. First, your program checks whether lang == "Deutsch". If that's false, it checks the next part, "deutsch". Because this is a non-zero value, it evaluates as true.
Most other variables can be evaluated as boolean in specific (sometimes weird) ways. For an int, 0 is false, and anything else is true. For a string, the null or empty string is false, and anything else is true.
Your final statement should be if(lang == "Deutsch" || lang == "deutsch").

if (lang == "Deutsch" || "deutsch") doesn't test what you expect.
it is equivalent to
if (lang == "Deutsch") {
// Do stuff
} else if ("deutsch") {
// Do same stuff
}
You wanted
if (lang == "Deutsch" || lang == "deutsch")
"deutsch" decays to a non null pointer so is always true.

This code
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
cout << "Language?" << endl;
string lang;
cin >> lang;
if(lang == "Deutsch" || "deutsch")
{
cout << "Hallo Welt!";
}
else
{
return false;
}
if(lang == "English" || "english")
{
cout << "Hello World!";
}
else
{
return false;
}
return 0;
}
is the same as
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
cout << "Language?" << endl;
string lang;
cin >> lang;
cout << "Hallo Welt!" ;
cout << "Hello World!";
return 0;
}

Related

question about this if/else code using || and &&

#include <iostream>
#include <string>
using namespace std;
int main()
{
string vegetarian, vegan, gluten_free;
cout << "Welcome to Restaurant Selector!" << endl;
cout << "Are you a vegetarian?"<<endl;
cin >> vegetarian;
cout << "Are you a vegan?"<<endl;
cin >> vegan;
cout << "Are you gluten-free?"<<endl;
cin >> gluten_free;
if (gluten_free == "yes" && vegan == "yes" && vegetarian == "yes" )
{
cout<<"The Chef's Kitchen"<<endl;
}
else if (gluten_free == "yes" && vegan == "yes" )
{
cout<<"Vegan's lair"<<endl;
}
else if (gluten_free == "yes")
{
cout<<"Starbuck's"<<endl;
}
else if ( gluten_free == "no" || "No" && vegan == "no" || "No" && vegetarian == "no"||"No")
cout<<"Burger King"<<endl;
return 0;
}
How can I get the first if expression to use multiple variations of yes.
I want it to include: yes, Yes, and YES. however I can only use the or operator on two strings. I would also like to do this for the subsequent lines. What should I do?
How can I get the first if expression to use multiple variations of yes. I want it to include: yes, Yes, and YES.
Convert the input string to lower case before comparison.
A trivial example:
auto tolower = [](unsigned char c){
return std::tolower(c);
};
std::transform(
vegan.begin(),
vegan.end(),
vegan.begin(),
tolower
);
Note that simple string processing such as this work only with fixed width encodings and not with unicode.

Comparing chars in if statement with or

recently I encountered a problem with comparing chars.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string test1 = "test";
string test2 = "adssadad";
if (test1[0] == 'b' || 'd')
{
cout << "it equals" << "\n";
}
return 0;
}
Everytime I compare chars in if statement and or appears - if statement always returns true and code inside is executed. How do I solve this kind of problem?
The line
if (test1[0] == 'b' || 'd')
is equivalent to
if ((test1[0] == 'b') || 'd')
due to == having higher precedence than ||. This always evaluates to true since 'd' implicitly evaluates to true.
Probably what you thought this meant was
if (test1[0] == ('b' || 'd'))
but this wouldn't work either since this will evaluate to
if (test1[0] == true) // <=> if (test1[0])
Which will be true whenever test[0] != '\0'. What you need is to test each case separately
if ((test1[0] == 'b') || (test1[0] == 'd'))
If there are lots of values to check then it may be easier to store them in a container and use an algorithm.
const std::vector<char> vals {'b', 'd'};
if (std::find(vals.cbegin(), vals.cend(), test1[0]) != vals.cend())
'd' evaluates to non-zero, which is interpreted as true in C++. If even one operand of OR is true, the entire expression is true, so the cout line is executed.
You want to write test[0] == 'b' || test[0] == 'd'
Your if statement is interpreted as follows: if [(test1[0] == 'b') || ('d')] Since 'd' is not null or zero, it always evaluates to true.
Change the statement to if (test1[0] == 'b' || test1[0] = 'd')
Use switch here:
switch(test[10])
{
case b:
case d:
cout << "it equals" << "\n";
break;
}

Unknown behaviour of OR operator in C++ [duplicate]

This question already has answers here:
How to compare multiple strings inside an if statement?
(6 answers)
Closed 4 years ago.
I have this code running by chance and when i put anything as the answer it is showing me correct. I know we have to put ans before YES and yay, but this code was compiled too, as i mentioned if i put any word as the input the output is correct:
string ans;
cin >> ans;
if(ans == "yes" || "YES" || "yay") {
cout << "Correct";
}else {
cout << "Incorrect";
}
Ok here's the precedence (L->R) and associativity of logic wise operators:
(((ans == "yes") || "YES") || "yay")
Since C/C++ has no chaining unlike Python.
1st: ans == "yes" -> str to str comparison
2nd: bool result of 1st || "YES" -> bool and str comparison = always true for "YES" is not null
3rd: true || "YES" = always true
Thus, the condition will always be true for "YES" and "yay" are not null.
You have the precedence wrong.
if (var == A || B || C) means "if (var is equal to A) OR (B is not zero) OR (C is not zero)"
You want to do if (var == A || var == B || var == C). That means "if (var is equal to A) OR (var is equal to B) or (var is equal to C)"
You should compare ans with each value. Every comparison with value is not "0" or "fail" value is assumed as "true". So if you input the if a condition like if("yes") it always returns a true.
int main()
{
std::string ans;
std::cin >> ans;
if("yes" == ans || "YES" == ans || "yay" == ans)
{
std::cout << "Correct\n";
}
else
{
std::cout << "Incorrect";
}
}

My else if statement using a string is not working [duplicate]

This question already has answers here:
if statement not working right?
(5 answers)
Closed 7 years ago.
after a good amount of time trying to get my else if statement to work, it just doesn't. This program keeps returning the first one, no matter what I input. Please help.
#include <iostream>
#include <string>
using namespace std;
string arehap;
int main()
{
cout << "Are you happy?" << endl;
cin >> arehap;
if (arehap == "Yes" || "Y")
{
cout << "Good." << endl;
}
else if (arehap == "No" || "N")
{
cout << "Bad." << endl;
}
return 0;
}
You should use this:
if (arehap == "Yes" || arehap == "Y")
{
cout << "Good." << endl;
}
else if (arehap == "No" || arehap == "N")
{
cout << "Bad." << endl;
}
When you're using the || operator, you have to compare two boolean values. If arehap is equal to "Y", the following statement will be True: arehap == "Y". In that case your computer will "understand" this as if (True || False) { /* do smth */} and this will evaluate to True and the code you want to execute will be run.
Your problem lies in this line:
if (arehap == "Yes" || "Y")
C++ understands this as
if ((arehap == "Yes") || ("Y"))
and while the first check (arehap == "Yes") might be false, the second check -- which is just "Yes" is always true.
This happens, because the "Yes" gets understood as a char const* -- and this pointer must obviously not be NULL, but point to the character 'Y'!

Or operator not working

When I enter start then the program outputs the else function even though I fulfilled the criteria, I have tried with && as well and it still didn't work. Any answers would be appreciated.
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
int main ()
{
float timer;
bool end;
std::string input;
end = false;
cout << "Enter start then a number to count down from" << ".\n";
while (end == false){
cin >> input;
if (input.find("end" || "End") != std::string::npos)
end = true;
else if (input.find("start" || "restart" || "Start" || "Restart") != std::string::npos)
{
cin >> timer;
while (timer>0){
timer -= 0.1;
Sleep(100);
cout << timer << ".\n";
}
cout << "Finished! Enter restart then another number to perform another countdown, or enter end to close the program" << ".\n";
}
else
cout << "Enter start" << ".\n";
}
return 0;
}
Replace
if (input.find("end" || "End") != std::string::npos)
with:
if (input.find("end") != std::string::npos || input.find("End") != std::string::npos)
Similarly for your other if.
It seems obvious what your expression means, but when you break it down it really doesn't make sense. find expects a string, and "end" || "End" is not a string.
the Logical or operator, || only works in boolean expressions.
For instance, if you had
bool A = true
bool B = false
bool C = A||B;
than you will have set bool C to be True. IT just takes 2 booleans, and returns true if either of those booleans is true. That's all logical or does.
You might want to try something like
if (input.find("end") != std::string::npos || input.find("End") != std::string::npos)
The || works only in logical boolean expression.
From the standard (emphasis is mine):
5.15 Logical OR operator [expr.log.or]
The || operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). It returns true if either of its operands is true, and false otherwise.
So in input.find("end" || "End"), it tries to convert "end" and "End" to bool. And the operator || will return a bool also.
Here to solve your problem you need to replace:
if (input.find("end" || "End") != std::string::npos)
by
if ( input.find("End") != std::string::npos ||
input.find("End") != std::string::npos )
And do the same in the second find.
C++ simply doesn't work that way. When you write
input.find("end" || "End") != std::string::npos
the compiler sees the logical or on two non-null const char pointers, which results in the boolean value true. This is then interpreted as a char with the value 1 ('\1') which is then searched in the string - certainly not what you intended. If you want to know if you string is in a set of strings, you could use:
static std::set<std::string> s = { "end", "End" };
s.find( input ) != s.end();
While maybe not the most efficient code in the world, but with a C++11 compiler you can also condense it into a single line like this:
if( std::set<std::string>{ "end", "End" }.count( input ) ) {
// found...
}
if (input.find("end" || "End") != std::string::npos)
// ^^^^^^^^^^^^^^
The || operator is not being used correctly here. The righthand expression will return true because it is non-zero, then it will be returned. So the statement resolves to input.find("end"). You need to use two separate conditional statements there:
if (input.find("end") != std::string::npos ||
input.find("End") != std::string::npos)
I'd recommend using regex instead for things like that:
regex
The argument of the function call
input.find("end" || "End")
has type bool and means that addess of string literal "end" or/and address of string literal "End" is not equal to zero. It is obvious that the both string literals have addresses that are not equal to zero. So the call is equivalent to
input.find(true)
The compiler finds an overloaded function find that is the most suitable for this argument. This function is
find( charT, c, size_tipe pos = 0 );
Value true is implicitly converted to value charT( 1 ) and the function tries to find char with value 1 in your string.
here is a fix:
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
int main()
{
float timer;
bool end;
std::string input;
end = false;
cout << "Enter start then a number to count down from" << ".\n";
while (end == false) {
cin >> input;
if (input.find("end") != std::string::npos | input.find("End") != std::string::npos)
end = true;
else if (input.find("start") != std::string::npos | input.find("Start") != std::string::npos | input.find("restart") != std::string::npos | input.find("Restart") != std::string::npos)
{
cin >> timer;
while (timer > 0) {
timer -= 0.1;
Sleep(100);
cout << timer << ".\n";
}
cout << "Finished! Enter restart then another number to perform another countdown, or enter end to close the program" << ".\n";
}
else
cout << "Enter start" << ".\n";
}
return 0;
}
it should be like this if (input.find("end") != std::string::npos | input.find("End")!= std::string::npos or this if (input.find("end") != std::string::npos || input.find("End")!= std::string::nposinstead of if (input.find("end" || "End") != std::string::npos)you can use logical or or bitewise or.