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.
Related
one would think this is easy, but for some odd reason, my conditional statement is ignoring user input.
If I input a character 'N' or 'n' it still executes the 'Y' portion of the conditional statement, have a look:
while (i < 10) {
cout << "Would you like "<< nameOfDish[i] << "? Please enter Y or N.\n";
cin >> userResponse;
if (userResponse == 'y' || 'Y')
{
cout << "How many orders of " << nameOfDish[i] << " would you like?\n";
cin >> quantityOfDish[i];
if (quantityOfDish[i] == 0) {
cout << "I suppose you're entitled to change your mind.\n";
}
else if (quantityOfDish[i] < 0) {
cout << "Your generosity is appreciated but I must decline!\n";
quantityOfDish[i] = 0;
}
i++;
}
else if (userResponse == 'n' || 'N')
{
i++;
}
else
{
cout << "I think you mumbled NO, so I'll just go on.\n";
i++;
}
}
Is there any particular reason why despite inputting 'n' it still goes into the 'Y' if conditional block?
I have stepped through the code in the debugger, and I noticed that the userResponse variable is being read in properly. Yet, the if condition does not seem to be working properly. Thanks!
This statement (and your other if statement) is not doing what you think it does:
if (userResponse == 'n' || 'N')
Try this instead:
if (userResponse == 'n' || userResponse =='N')
You need to define each logical operation individually in a condition check. You will have to compare userResponse with n and N separately.
if (userResponse == 'y' || userResponse == 'Y')
{
cout << "How many orders of " << nameOfDish[i] << " would you like?\n";
cin >> quantityOfDish[i];
if (quantityOfDish[i] == 0) {
cout << "I suppose you're entitled to change your mind.\n";
}
else if (quantityOfDish[i] < 0) {
cout << "Your generosity is appreciated but I must decline!\n";
quantityOfDish[i] = 0;
}
i++;
}
It's been awhile since I worked in C++, but I'm fairly sure I know what's going on.
The || operator does not work on a single conditional, there must be two complete conditionals, one on each side. Try replacing your if statement with this line:
if (userResponse == 'y' || userResponse == 'Y')
Maybe you are used to SQL? You need to repeat the userResponse
if userResponse == 'n' || userResponse == 'N'
Otherwise you are actually testing
if userResponse is 'n' or the char'N' exists
The error in this code is, as others have pointed out, the if statement. However, I feel this may need some clarification. Every C++ expression returns a value. For example.
userResponse == 'y'
returns the value 1 if userResponse is 'y' and 0 if it is anything else. The operator || returns 1 if either the left or the right expression is non-zero.
Finally, the if statement checks to see whether or not the expression is zero or non-zero. So,
if (5)
cout << "X";
else
cout << "Y";
will print X and
if (0)
cout << "A";
else
cout << "B";
will print B.
Now, we can begin to understand why your code compiled successfully, but didn't do what you wanted it to.
if (userResponse == 'y' || 'Y')
In this example, the || operator will always return 1 because the expression on the right, 'Y', will always be non-zero (specifically, it will be 89, since C++ characters are just aliases for their ASCII corresponding number). And of course,
if (userResponse == 'y' || userResponse == 'Y')
work as intended. But there is a much better solution and that would be the switch statement, whose purpose is to handle situations like this. Here it is in action:
switch (userResponse) {
case 'y':
case 'Y':
//The user answered yes, handle that situation here.
break;
case 'n':
case 'N':
//The user answered no, handle that situation here.
break;
default:
// The user did not enter a valid answer,
// handle that situation here.
break;
}
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.
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).
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.
I setup a while loop where i want to choose r or h, i dont want to use forloops but i want to use a switch why is it when i enter r or h it keeps repeating a million times the cout for that case? I cant get it to just say it once..
while (chooseMove == 'r' or 'h')
{
switch (chooseMove)
{
case 'r':
cout << "you chose r";
break;
case 'h':
cout << "you chose h";
break;
}
}
I also tried it with forloops and had the same problem i cant figure it out
What you mean is while (chooseMove == 'r' or chooseMove == 'h'). What you've currently written is equivalent to ((chooseMove == 'r') or ('h')), and 'h' evaluates as true.
Maybe you were also asking for help with the input logic:
char c;
bool success = false;
while (std::in >> c)
{
switch(c) {
case 'r': /* ... */ success = true; break;
case 'h': /* ... */ success = true; break;
}
if (success) break;
}
This will also terminate if the input stream is closed, and you can use success to inspect the success of the operation.
Because that's what you programmed it to do.
If you want the loop to stop or pause (and say, wait for input), you should add that code into the loop.
while (chooseMove == 'r' or chooseMove == 'h')
{
switch (chooseMove)
{
case 'r':
cout << "you chose r";
break;
case 'h':
cout << "you chose h";
break;
}
std::cin >> chooseMove; //stop and wait for more input
}
This is a problem:
while (chooseMove == 'r' or 'h')
Try this instead:
while ((chooseMove == 'r') || (chooseMove == 'h'))
When you write (how did this even compile? or isn't C++):
chooseMove == 'r' or 'h'
It is interpreted as:
(chooseMove == 'r') or ('h')
The statement 'h' is always true, so the while loop runs forever.
What does chooseMove == 'r' or 'h' mean? According to the C++
standard, this is grouped as (chooseMove == 'r') or ('h'); the
implicit conversion of 'h' to bool then results in (chooseMove ==
'r') or ('h' != 0). The second condition will always be true.
while (chooseMove == 'r' or 'h')
which is equivalent to this:
while ( (chooseMove == 'r') or true)
//same as while ( (chooseMove == 'r') || true)
So this is infinite loop. Note that or and || are same thing.
What you want is this:
while ( (chooseMove == 'r') or (chooseMove == 'h'))
//same as while ( (chooseMove == 'r') || (chooseMove == 'h'))