Or operator not working - c++

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.

Related

If always returns true [duplicate]

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;
}

Endless loop, can't find error

I'm making a small program for myself and any of my friends at school to use. I have a function (C++), called getChoice(), that returns a choice that the user made:
std::string getChoice(const std::string& s)
{
std::string choice;
if (s == "sp")
{
do
{
std::cout << "Do you want to search for a video or play it? (s/p): ";
std::cin >> choice;
if (choice[0] == 'S' || choice[0] == 'P')
choice[0] = tolower(choice[0]);
} while (choice.compare("s") != 0 || choice.compare("p") != 0);
}
else if (s == "vidtype")
{
do
{
std::cout << "Do you want to use vine or yt? (vine/yt): ";
std::cin >> choice;
} while (choice.compare("vine") != 0 || choice.compare("yt") != 0);
}
else
{
std::cout << "Uh, this function only supports \"sp\" and \"vidtype\"\n\n";
exit(EXIT_FAILURE);
}
return choice;
}
My issue is that the program gets stuck in an infinite loop at
"Do you want to search for a video or play it? (s/p): ";
I've rewritten the entire program, and that didn't fix it. I've looked up on using !=; it seems that I should use std::string.compare().
And I also tried outputting choice after using std::cin. It looks just fine in console output, showing s and p, but the tests in the do-while both fail somehow. Is there something I'm missing here?
while (choice.compare("s") != 0 || choice.compare("p") != 0);
If not S or not P:
If you input S, not P will evaluate to true, this continuing the loops
If you input P, not S will evaluate to true, this continuing the loops
If you input anything other than S or P, both will be true, this continuing the loop.
You probably meant to do:
while (choice.compare("s") != 0 && choice.compare("p") != 0);
If not S and not P (aka some other character besides S and P).
This incorrect logic is also present in your second loop (thank you dwcanillas)
while (choice.compare("vine") != 0 || choice.compare("yt") != 0);
Change the condition in the while loop the following way
do
{
std::cout << "Do you want to search for a video or play it? (s/p): ";
std::cin >> choice;
if (choice[0] == 'S' || choice[0] == 'P')
choice[0] = tolower(choice[0]);
} while (choice.compare("s") != 0 && choice.compare("p") != 0);
It is easier to consider the negation of the condition when the loop has to be terminated. For example
!(choice.compare("s") != 0 && choice.compare("p") != 0)
or more visually
not (choice.compare("s") != 0 && choice.compare("p") != 0)
is equivalent to
choice.compare("s") == 0 || choice.compare("p") == 0
So when the user entered either "s" or "p" then exit the loop.
The problem is the line
while (choice.compare("s") != 0 || choice.compare("p") != 0);
If you change the logic to
while (choice.compare("s") == 0 || choice.compare("p") == 0);
it will be good.

how to only allow 3 values in a "if" and "while" statement to allow the loop to exit

I'm just stuck on some logic statements.
specifically the ones that are in the function char GetInteger() so how would I only allow 3 values to cause the loop to exit.
char GetInteger( /* out */ char& usrinput)
{
do
{
cin >> usrinput;
cin.ignore(200,'\n');
if (usrinput != 0 || usrinput != 1 || usrinput != 2)
{
cout << "Invalid Input." << userinput << " Try Again\n";
}
} while(usrinput != 0 || usrinput != 1 || usrinput != 2);
return userInput;
}
Two issues with this code:
First userinput has a type of char. So when you read from a stream you read a single character (after dropping white space). So when a user types 1<enter> you get the character '1' in the variable userinput. Note the character '1' is not the same as the number 1.
Thus your test should be:
userinput != '1';
Secondly your boolean logic is wrong. When first learning it is sometimes easier to state the problem as a list of values that you would like to be acceptable (not the unacceptable ones).
You want the conditions to be false if the userInput has one of your accepted values (any good value will fail the test and thus not invoke the bad code). The first step to this is to get a true if any of your values are valid.
// If any value is good then true.
userinput == '1' || userinput == '2' || userinput == '3'
To invert this just add a not to the expression.
if (! (userinput == '1' || userinput == '2' || userinput == '3') )
Note: in boolean logic
!(A || B) => (!A && !B)
So you could re-write the above as:
if (userinput != '1' && userinput != '2' && userinput != '3')
I think this was your main mistake you converted the == into != but did not convert the || into &&.
I would also suggest that you could simplify this (as you may get more valid result) byconverting this into a range based test.
if (userinput < '1' || userinput > '3')
{
// Test Failed.
}
Additionally. Since you have the test in two places. You should yank it outinto its own function. Then you can call the function to do the test.
bool isUserInputValid(char userInput)
{
return userInput >= '1' && userInput <= '3';
}
Now we can re-write your original function as:
char GetInteger( /* out */ char& usrinput)
{
do
{
cin >> usrinput;
cin.ignore(200,'\n');
if (!isUserInputValid(userinput))
{
cout << "Invalid Input." << userinput << " Try Again\n";
}
} while(!isUserInputValid(userinput));
return userInput;
}
First of all, you should use int instead of string as you are reading integer.
You can use while(1) instead of putting condition in while. Inside while loop, if your selection is 0 or 1 or 2, you can simply break the loop.

String and Bool (Int Condition to be false) C++

Im new to C++ and I tried searching but I have no idea on what to search. Sorry. My problem is:
When I set the bool condition false, it still requires me to input 2 x to terminate the compiler. Why is that so? (I tried using cin.fail () but it didnt work)
When I print the list of courses, it lists the one that should terminate the program (ie when you press x). How do I correct this?
Thank you for your help.
int main(void)
{
// Gather list of courses and their codes from user,
// storing data as a vector of strings
const string DegreeCode("PHYS");
string CourseTitle;
int CourseCode(0);
vector <string> CourseList;
vector <string> :: iterator iter;
bool not_finished(true);
do
{
if (CourseTitle == "x" && "X")
{
not_finished=false;
}
else
{
cout<<"Please enter a course code and a course title (or x to finish): "<<endl;
cin>>CourseCode;
cin.sync();
cin.clear();
getline(cin , CourseTitle);
ostringstream oss;
string outputCourseList (oss.str ());
oss << DegreeCode << " " << CourseCode << " "<< CourseTitle;
CourseList.push_back (oss.str ());
cout <<outputCourseList <<endl;
oss.str(""); //clear oss content
}
} while(not_finished);
// Print out full list of courses
cout<<"List of courses:\n"<<endl;
for (iter = CourseList.begin(); iter != CourseList.end(); iter++)
cout<<(*iter)<<endl;
return 0;
}
Your problem is your comparison in the if statement:
if (CourseTitle == "x" && "X")
The proper syntax is: (variable operator variable) && (variable operator variable)
The syntax corrected:
if ((CourseTitle == "x") && (CourseTitle == "X"))
There is a logic issue because a variable can't equal two values at the same time.
Maybe you want:
if ((CourseTitle == "x") || (CourseTitle == "X"))
which means one OR the expressions is true.
You could eliminate the two compares by transforming the string into all uppercase or all lowercase. Search the web for "C++ string transform tolower toupper".
if (CourseTitle == "x" && "X")
{
not_finished=false;
}
to
if (strcmp(CourseTitle.c_str(), "x") == 0 || strcmp(CourseTitle.c_str(), "X") == 0)
{
not_finished=false;
}
== is a pointer comparison, almost never true... "x" == "x" will even be false unless you're good with compiler flags
Make sure to
#include <string.h> //<----.h is needed!

Char validator will not only accept lower and upper case M/F

Hey im trying to validate a char to limit it to accpeting an m or f for male or female. But it doesnt pass the while condition even when m or f is pressed and keeps looping the question.
Can anybody help me with this.
Thanks in advance.
Here is my code:
char Validator :: getChar(string q)
{
char input;
do
{
cout << q.c_str() << endl;
cin >> input;
}
while(!isalpha(input) && "M"||"F"||"m"||"f");
return input;
}
The "M"||"F"||"m"||"f" part of your code doesn't do what you think it does. What it does is check the ADDRESSES of those string constants. Since they are all non-NULL, this expression simply returns true, so your condition, essentially becomes: while(!isalpha(input) && true) which is the same as while(!isalpha(input)).
Try this instead:
char Validator::getChar(const string &q)
{
char input = 0;
do
{
cout << q << endl;
cin >> input;
}
while((input != 'M') && (input != 'F') && (input != 'm') && (input != 'f'));
return input;
}
The expression in the while doesn't mean what you think it does. First, the ! does not apply to the entire expression, and second, "equality" is not an implicit test. You need to write out everything you mean.
To test for equality, use the == or != operators. You have to use the operators on every value you want to test; the operator doesn't "distribute" over a list of values like it would in ordinary English. Write your condition like this:
while (input != 'M' && input != 'F' && input != 'm' && input != 'f');
You can see that the isalpha call isn't necessary; if input isn't equal to any of the listed values, then it doesn't really matter whether it's an alphabetical character.
Another way to write it is this:
while (!(input == 'M' || input == 'F' || input == 'm' || input == 'f'));
Notice that I've another set of parentheses around the internal terms so that the ! operator applies to the entire expression instead of just the first term.
Just for an alternative approach to the terminating condition:
char Validator::getChar(const string &q)
{
const std::set<char> valid_chars { 'M', 'm', 'F', 'f' };
char input = 0;
do
{
cout << q << endl;
cin >> input;
}
while (!valid_chars.count(q));
return input;
}