If statement always executing even when the condition is false? - c++

when it gets to this if statement, no matter what 'option' is inputted its always setting if(option == "y" || "Y") condition to true?
bool UserInterface::readInConfimDeletion() const
{
string option = "";
cout << "Are you sure you want to delete these transactions? Y/N ";
cin >> option;
if (option == "y" || "Y")
{
return true;
}
else if (option == "n" || "N")
{
return false;
}
else{
readInConfimDeletion();
}
}

You can't compare multiple conditions like this:
if (option == "y" || "Y")
The "Y" condition will evaluate to true always if evaluated.
you need to do this:
if (option == "y" || option== "Y")
It would be simpler IMO to uppercase the string and perform a single comparision, there are a number of options to do this: Convert a String In C++ To Upper Case
So a possible solution would be:
#include <boost/algorithm/string.hpp>
string upperStr = boost::to_upper_copy(option);
then you can do:
if (upperStr == "Y")

Change it like this:
if (option == "y" || option == "Y")
and similarly
else if (option == "n" || option == "N")
You cannot compare multiple strings like the way you are doing.

You need to say option == "y" || option == "Y" etc..
FYI / if (option == "y" || "Y") is actually asking if option == "y" or... "Y" itself is true, and "Y" is a string literal that undergoes a Standard Conversion to const char* then - being used inside an if undergoes a further conversion to the bool true (because the pointer is not nullptr, it's deemed true).

Related

why wont this do while loop exit after accepting input

Pretty straight forward. i dont understand why it wont quit the loop after not accepting a y char.
ive tried different variations of == and != with regards to y char and n char
vector<int> v;
char ans;
do
{
cout << "Enter scores, enter number outside of 0-100 to stop:\n";
get_scores(v);
print_stats(v);
cout << "Do you want to try another set of scores? Y/N: \n";
cin >> ans;
} while (ans != ('n' || 'N'));
after typing any char, the loop keeps asking for more input.
NOTE: the get scores and print stats functions work as their supposed to.
Your comparison in the while condition is not correct, you probably meant to do
while (ans != 'n' && ans != 'N');
('n' || 'N') will be coerced to true (1), so you would check for a char of value 1 instead of 'n' / 'N'
} while (ans != ('n' || 'N'));
Here you are comparing char with boolean result of || operation for the 2 other chars.
Which alway evaluates as true.
So your while statement is effecitvely
} while (ans != true);
to fix this you need to compare ans to both of the n and N and exit if one of them becomes true, for example:
} while ((ans != 'n') && (ans != 'N'));
while (ans != ('n' || 'N')) is the same as writing while (ans != (true)). You probably wanted while ((ans != 'n') && (ans != 'N')).

How to use the or statement (||) correctly, in an else-if statement

Consider this code:
string GameExit;
bool GameChoiceGo = true;
while (GameChoiceGo == true)
{
system("cls");
cout << "\n Are you sure you want to exit? (Yes or No) ";
cin >> GameExit;
if (GameExit == "y" || "Y" || "yes" || "Yes" || "YES")
{
cout << "User typed Yes";
Sleep(3000);
system("cls");
break;
}
if (GameExit == "n" || "N" || "no" || "No" || "NO")
{
cout << "User typed No";
Sleep(3000);
system("cls");
GameChoiceGo = false;
}
else
{
cout << "\nI'm sorry but, " << GameExit << " is not a acceptable choice. Type: Yes or No.\n\n\n";
Sleep(3000);
system("cls");
}
}
break;
Here, only the first statement is activated. Even if the user types "No" or anything else, it will output "user typed yes".
The else-if statements work if I replace the or statements with only one statement (i.e. "y" and "n"). The only problem is, I want to have any possible version of yes and no that the user might type in the code.
Any ideas why the code is not working correctly?
I'm sorry, but you have to write GameExit == for every condition you want to check:
if (GameExit == "y" || GameExit == "Y" || GameExit == "yes" || GameExit == "Yes" || GameExit == "YES")
If you write if ("y") (which is basically what you are doing, only with more statements), the const char[] will decay to a const char*, and that pointer will be compared to 0. Now, that pointer will never be null, as there will always be memory allocated for the string literal.
A better solution is to (1) make an array with all the options, so that checking the conditions becomes a simple search or (2) convert the input to all lowercase for example, and compare that.
// 1)
std::vector<std::string> options = { "y", "Y", "yes", "Yes", "YES" };
if (std::find(options.begin(), options.end(), GameExit) != options.end());
// or
if (std::any_of(options.begin(), options.end(), [&GameExit](const auto& value) {
return GameExit == value;
});
// 2)
std::transform(GameExit.begin(), GameExit.end(), GameExit.begin(), ::tolower);
if (GameExit == "y" || GameExit == "yes");
You can look up the functions if you do not know what they do :).
Correct way using OR operator in "your" code is as below (note the explicit use of == statements between || operators):
if (GameExit == "y" || GameExit =="Y" || GameExit =="yes" || GameExit =="Yes" || GameExit =="YES")
{
cout << "User typed Yes";
Sleep(3000);
system("cls");
break;
}
if (GameExit == "n" || GameExit =="N" || GameExit =="no" || GameExit =="No" || GameExit =="NO")
{
cout << "User typed No";
Sleep(3000);
system("cls");
GameChoiceGo = false;
}
PS: The above answer is not intended to give the best programming practice in a similar situation but to give the specific answer to the OP with the minimal code change :)
// -----
EDIT: Here is a better approach using STL. Note that (unsorted) array lookup requires linear search, whereas unordered_set, which is a hash set, has (on average) constant time lookup. This will be faster especially when the yes, no etc. options are plenty.
#include <unordered_set>
...
// These sets can be as large as possible or even dynamically
// updated while the program is running. insert, remove, lookup will
// all be much faster than a simple array.
unordered_set<string> ySet{"y", "Y", "yes", "Yes", "YES"};
unordered_set<string> nSet{"n", "N", "no", "No", "NO"};
if (ySet.find(GameExit) != ySet.end())
{
cout << "User typed Yes";
Sleep(3000);
system("cls");
break;
}
if (nSet.find(GameExit) != nSet.end())
{
cout << "User typed No";
Sleep(3000);
system("cls");
GameChoiceGo = false;
}
...
You need to define a complete equality for each expression like this:
if ( gameExit == "y" || gameExit == "Y" ) {}
GameExit == "y" || "Y" || ....
is incorrect. The correct method is:
GameExit == "y" || GameExit == "Y" || ....
and so on, both for the yes or no case.

Bool function `again()` getting same result

I wrote a bool function again() to prompt the user to re-run the program, but for whatever answer the user enters the program will re-run no matter what.
bool again()
{
//Local variable
char answer;
cout<<"Would you like to re-run? (Y/N) ";
cin>>answer;
cin.ignore(100,'\n');
if(answer == 'Y' || 'y')
{
return true;
}
if(answer == 'N' || 'n')
{
return false;
}
}
...
do
{
menu(gameamount,response);
if (response == 1)
{
inputs(gameamount, game_count);
writeout(gameamount);
}
if (response == 2)
{
outputs(gameamount, game_count);
}
}while(again());
return 0;
}
I tried using else and else if and returning false after the first if-statement but that still did not work, I can't put the block of code in main to conserve space so I have to create a boolean function to ask the user to re-run the program.
There's a logic error in your code.
Try this:
if(answer == 'Y' || answer == 'y')
{
return true;
}
if(answer == 'N' || answer == 'n')
{
return false;
}
You should also possibly output a message in case the user decides to type something other than 'Y','y','N' or 'n'.
Also, I'm not 100% sure about this, but I think that your code is always returning true in the first if statement because you are checking to see if 'y' is true, which I think it always is.
if(answer == 'Y' || 'y')
{
return true;
}
Any value other than 0 would equate to true, and the character 'y' when treated as an integer is equal to it's corresponding ASCII code (121 in this case).
Try to replace the line
if(answer == 'Y' || 'y')
by
if(answer == 'Y' || answer == 'y')
The line
if (answer == 'Y' || 'y')
will enter the if block in every case, since it won't evaluate to what you intended. It evaluates answer == 'Y' which is true or false, but then ORs this value with 'y'. In this step, 'y' is converted to a boolean value in order to be ORed logically, and since all numbers unequal to 0 are converted to true the whole expression is always true.
If you correct this to
if (answer == 'Y' || answer == 'y')
you still have the following problem:
Your function only returns a value in the case where the user enters either a Y or an N in lower or upper case. But what if the user enters an invalid letter? You need to define a behavior for this situation. Currently your program doesn't have a return statement for this case, resulting in undefined behavior, which means the result of the function can be anything.
You can either return a default value (e.g. false), then you need to remove the second conditional if but keep the return false.
Another solution is to loop until the user entered a valid value.

Why does this if statement not behave as I'd expect?

I am making a program that will evaluate the value of something. I have a variable that holds the total value to be added, rcoverE. When I test "y" for the second question, it works, but when I put in "n", it adds 5 anyway. Why is this happening?
#include <iostream>
using namespace std;
int main(){
int year, yearE, rcoverE;
string rcover, func;
cout << "Enter the decade your thing was produced (eg. 20):";
cin >> year;
cout << "Does you typewriter have original thingy? (y,n):";
cin >> rcover;
rcoverE = 0;
if(rcover == "y" || "Y"){
rcoverE = rcoverE + 5;
}else{
rcoverE = rcoverE + 0;
}
cout << rcoverE;
yearE = 100 - year / 2;
}
if(rcover == "y" || "Y"){
This condition is wrong it should be:
if(rcover == "y" || rcover == "Y"){
This: if(rcover == "y" || "Y"){ is logically equivalent to if(rcover == "y" || "Y" != 0) and "Y" != 0 is always true.
if(rcover == "y" || "Y")
Does not evaluate the way you think it does. This actually evaluates as if ("rcover == 'y') or if('Y')", not "rcover == ('y' || 'Y')." In some languages the compiler would not let you do this, but in C++, simply putting in the statement "Y" returns true. You need to change the statement to:
if(rcover == "y" || rcover == "Y")

else if string compare problem

I have the following if statements, two of which don't seem to work. I don't get why it works when I try to compare it to a single character "y" or "n" but not when I try to compare it to two characters in one else if statement.
The last question I have is if there's a better cleaner way to write this or if this acceptable for a simple prompt check?
getline(cin,somestr);
if(somestr.empty()){
//do this
}
else if (somestr == "y" || "Y"){
//do something else
}
else if (somestr == "n" || "N"){
//do something else
}
else{}
You would do it like this:
else if(somestr == "y" || somestr == "Y")
if (somestr == "y" || "Y"){
Keep in mind, in C++ 0 is false and everything else is true. Since "Y" is not zero, it's true. So what you've really written is: if (something || true). Which is always true.
Unfortunately, the language doesn't give you an easy way to check a variable against a set of possibilities. You have to do each test individually or use a switch statement. So, either of the following code samples would be a valid solution for your problem:
else if (somestr == 'y' || somestr == 'Y'){
//do something else
}
else if (somestr == 'n' || somestr == 'N'){
//do something else
}
switch (somestr) {
case 'y':
case 'Y':
// do something
break;
case 'n':
case 'N':
// do something
break;
default:
break;
}
Alternatively, you can clean up your code a bit by reducing some of your logic (assuming somestr is a char):
// Convert to uppercase first and only one comparison is needed
else if (toupper(somestr) == 'Y'){
//do something else
}
else if (toupper(somestr) == 'N'){
//do something else
}
I would do something like
else if(someFunctionThatConvertsToUpper(somestr) == "Y")
Anther option, especially if you're only expecting characters - it looks like y or n for yes or no - is to read in a char, not a string, and use a switch statement.
char somechar;
cin.get(somechar);
switch(somechar){
case 'y' : case 'Y':
//do something
break;
case 'n' : case 'N':
// do something else
// break;
default:
// do something else
}
You should write two comparisons
somestr == "n" || somestr=="N"
First of all, you need to fix this:
(somestr == "y" || "Y") to (somestr == "y" || somestr == "Y")
and
(somestr == "n" || "N") to (somestr == "n" || somestr == "N")
Otherwise, these expressions always evaluate to true because any string by itself such as "y" evaluates to true along with anything else other than 0.
Secondly, you may want to ask for input again if it is not "y", "Y", "n" or "N". You could use a do-while loop to accomplish this.