In C++, I have run into a problem when I am doing loops. I just know there is an obvious solution I am just overlooking in my work. Here is an example for reference:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
string loop();
int main()
{
string answer;
do
{
cout << "Do you wish to be asked this question again?: ";
cin >> answer;
if (answer == "no" || answer == "No" || answer == "NO")
cout << "As you wish";
else if (answer == "yes" || answer == "Yes" || answer == "YES")
cout << "";
else
{
cout << "You didn't answer yes or no\n";
loop();
}
}while (answer == "yes" || answer == "Yes" || answer == "YES");
return 0;
}
string loop()
{
string answer;
cout << "Do you wish to be asked this question again?: ";
cin >> answer;
if (answer == "no" || answer == "No" || answer == "NO")
cout << "As you wish";
else if (answer == "yes" || answer == "Yes" || answer == "YES")
cout << "";
else
{
cout << "You didn't answer yes or no\n";
loop();
}
return answer;
}
When I am doing an If-else in a loop, I run into a problem when it comes to the else section. I cant seem to figure out how to display something that tells the user there is an error, and then re-run the same sequence. For example, in the program I included, when the user enters something other than yes or no, I am not sure how to show an error statement and then loop it back to the top so it asks the question again.
You should use a while loop.
string answer;
while ( (answer != "yes") && (answer != "no") ) {
cout << "Do you wish to be asked this question again?: ";
cin >> answer;
if (answer == "no" || answer == "No" || answer == "NO") {
cout << "As you wish";
break;
}
if (answer == "yes" || answer == "Yes" || answer == "YES") {
cout << "";
break;
}
}
The problem isn't the loop; the problem is you've got your logic all tangled up. The solution isn't a way to fix the loop, the solution is a way to straighten up your logic.
A simple trick which is a lot more useful than it appears is to completely separate the loop from the thing you do in the loop:
// This function does something, then returns a boolean value
// to indicate whether or not you should continue looping.
bool do_something();
int main()
{
bool continue_looping = true;
while (continue_looping) {
continue_looping = do_something();
}
}
Now, you implement do_something() in a way that doesn't have to worry about actually doing the looping; it's only responsibility in that regard is to return a value that indicates whether looping should continue.
All you need is a single do-while loop...
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string ans{""};
transform(ans.begin(), ans.end(), ans.begin(), ::tolower); // convert string to lower case
do {
cout << "Do you wish to be asked this question again? ";
cin >> ans;
if (ans == "no") {
cout << "As you wish.";
} else
if (ans == "yes") {
cout << "";
}
else {
cout << "You didn't answer yes or no." << endl;
}
} while (ans != "yes" && ans != "no");
return 0;
}
Note, the transform algorithm converts the string into lower case to avoid variations in the spelling of yes and no.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 9 months ago.
The community reviewed whether to reopen this question 9 months ago and left it closed:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
Improve this question
My loop is skipping the nested 3rd else if. What should I do so it does not skip it?
#include <iostream>
int main()
{
int loop, i;
loop = 0;
char choice, selection;
std::cout << "Welcome" << std::endl;
while (loop == 0)
{
std::cout << "Please a choice" << std::endl;
std::cout << "a. Run" << std::endl;
std::cin >> selection;
if (selection == 'a')
{
for (i = 1; i < 5; i++)
{
std::cout << "run" << std::endl;
std::cout << "do you want to continue running? (y/n)";
std::cin >> choice;
if (i < 5 && choice == 'y')
{
continue;
}
else if (i < 5 && choice == 'n')
{
break;
}
else if ( i > 5 && choice == 'y')
{
std::cout << "Limit Reached";
}
}
}
I want it to print "limit reached" when i > 5, but somehow the loop skips it. What am I doing wrong?
Previous StackOverflow questions did not help much. I tried their solutions, but they did not solve my issue.
Edit:
For example: Nesting if statements inside a While loop? I have looked if I have initialized any of my int which might be messing my loop.
Looks like my else if didn't work because the condition I gave it would never be true. I feel stupid. But thanks everyone for your time. I really appreciate it.
Your loop runs only while i is in the range 1..4 inclusive, so i < 5 will always be true and i > 5 will never be true.
You should check the value of i after the loop exits. You should also check the user's input to make sure it matches your expectations.
Try something more like this:
#include <iostream>
#include <cctype>
bool shouldContinue(const char *prompt)
{
char choice;
do
{
std::cout << prompt << " (y/n)";
if (!(std::cin >> choice)) throw ...;
if (choice == 'y' || choice == 'Y' || choice == 'n' || choice == 'N') break;
std::cout << "Invalid choice" << endl;
}
while (true);
return (choice == 'y' || choice == 'Y');
}
int main()
{
bool loop = true;
int i;
char selection;
std::cout << "Welcome" << std::endl;
while (loop)
{
std::cout << "Please a choice" << std::endl;
std::cout << "a. Run" << std::endl;
std::cin >> selection;
if (selection == 'a')
{
for (i = 1; i < 5; ++i)
{
std::cout << "run" << std::endl;
if (!shouldContinue("do you want to continue running?"))
break;
}
if (i == 5)
std::cout << "Limit Reached";
}
...
}
return 0;
}
I am working on a project right now and when I try to run what I have below it gives me an error that says "uninitialized local variable 'userOption' used" on line 22, while (isValidOption(userOption) == true) {.
How do I fix that error? Thank you.
#include<iostream>
#include <string>
using namespace std;
char toupper(char ch) {
if (ch >= 'A'&&ch <= 'Z')
return(ch);
else
return(ch - 32);
}
bool isValidOption(char ch) {
if (ch == 'I' || ch == 'O' || ch == 'L' || ch == 'X')
return(true);
else
return(false);
}
char getMainOption() {
string UserInput;
char userOption;
while (isValidOption(userOption) == true) {
cout << "Choose One of the following options\n";
cout << "I--List Our Inventory\n";
cout << "O--Make an Order\n";
cout << "L--List all Orders made\n";
cout << "X--Exit\n";
cout << "Enter an option: ";
getline(cin, UserInput);
userOption = toupper(UserInput[0]);
if (!isValidOption(userOption)) {
cout << "Invalid String\n";
cout << "Enter an option: ";
getline(cin, UserInput);
userOption = toupper(UserInput[0]);
}
if (userOption == 'I')
cout << "Listing Our Inventory\n";
else if (userOption == 'O')
cout << "Make an order\n";
else if (userOption == 'L')
cout << "Listing all orders\n";
}
return userOption;
}
int main() {
char choice;
choice = getMainOption();
system("pause");
return 0;
}
What the error is saying that you're trying to read from userOption before you've ever written to it. If a variable is uninitialized, its memory contents will be full of junk left behind by other functions and it can easily cause bugs. In your case, you'll want to read input from the user into userOption before you do any logic on it. This can be done with a do-while loop:
char userOption; // not yet initialized
do {
...
cin >> userOption; // userOption gets initialized here on first loop run
} while (isValidOption(userOption)); // no need for == true, that's a tautology :-)
// NOTE: perhaps you want to loop while the input is INvalid, as in
// while (!isValidOption(userOption)); ?
A couply code-review comments I would additionally give are:
std::toupper already exists in <cctype>. Docs are here
return is not a function call and it's better to write return ch; than return(ch);
if (ch == 'I' || ch == 'O' || ch == 'L' || ch == 'X'){ return true; } else { return false; } is completely equivalent to the shorter return ch == 'I' || ch == 'O' || ch == 'L' || ch == 'X';
Also take a look at system(“pause”); - Why is it wrong?
Happy coding! Let me know if questions remain
What would the best way be of reducing my conditions in this code, is it to simply implement the Boost library for a string comparison or is there another way of doing it? I would much more prefer to avoid using boost if possible.
How could said question be implemented on the following code?
cout << " Please Enter An Answer Of Yes(Y) or No(N):";
string question; cin >> question;
if (question == "yes" || question == "Yes" || question == "Y" || question == "y" || question == "YEs" || question == "YES" || question == "yeS" || question == "yES")
{
cout << "You said yes!" << endl;
return 1;
}
else if (question == "No" || question == "NO" || question == "nO" || question == "N" || question == "n")
{
cout << "You said no!" <<endl;
return 0;
}
else
{
AskAQuestion();
}
It might not be the most efficent solution but if you convert the entire string to lower case then you only need to check against the word and the letter instead of all the possible permutation. So if you have
void make_lowercase(std::string& data)
{
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
}
Then
cout << " Please Enter An Answer Of Yes(Y) or No(N):";
string question; cin >> question;
if (question == "yes" || question == "Yes" || question == "Y" || question == "y" || question == "YEs" || question == "YES" || question == "yeS" || question == "yES")
//...
Becomes
cout << " Please Enter An Answer Of Yes(Y) or No(N):";
string question;
cin >> question;
make_lowercase(question);
if (question == "yes" || question == "y")
//...
The following does not do exactly the same since you did not check 'yEs' as a possible case in the first if statement, but this is probably along the lines what you are looking for. It is based on lower casing the answer of the user first before checking the answer, to reduce the number of cases to check.
#include <algorithm>
#include <cctype>
...
std::cout << "Please Enter An Answer Of Yes(Y) or No(N): ";
std::string answer; std::cin >> answer;
std::transform(answer.begin(), answer.end(), answer.begin(), std::tolower);
if (answer == "yes" || answer == "y")
{
std::cout << "You said yes!\n";
return 1;
}
else if (answer == "no" || answer == "n")
{
std::cout << "You said no!\n";
return 0;
}
else
{
AskAQuestion();
}
I took the liberty of renaming question to answer, seems more logical in this context.
#include <iostream>
using namespace std;
int main(){
cout << endl;
cout << "Welcome to the wonderful world of a spy" << endl;
cout << "Today we are to decode some information that has been provided." <<endl;
string response;
cout << "Are you ready?" << endl;
cin >> response;
if (response == "yes", "y", "Yes", "Y"){
cout << "Alright, let's go!!!" << endl;
}
else {
cout << "Well, too bad. We are going to do it anyways." << endl;
}
}
Exact Code Here is my code thus far. I can't get it to not say "Alright, let's go!!! What am I doing wrong?
The line if (response == "yes", "y", "Yes", "Y") doesn't do what you think it does. The comma operator evaluates each of its operands, discards the result on the left and takes the result on the right as the result of the expression. So what you wrote is equivalent to if ("Y"). You need to use the logical OR operator to combine your different cases. Like this if (response == "yes" || response == "y" || response == "Yes" || response == "Y").
your if statement conditions are wrong.
if(response == "yes" || response == "y" || response == "Yes" || response == "Y")
{
//then do whatever...
}else{
//do it anyway...
}
int OnLoad() {
cout << "Hi whats your name? ";
cin >> name;
system("cls");
cout << "Hi " << name << "." << " Are you here to Take Over the city from zombies?"<< endl;
cin >> userInput;
if (userInput == "yes" || "Yes") {
cout << "Yes" << endl;
}
else if (userInput == "no" || "No") {
cout << "No" << endl;
}
else {
cout << "I don't understand." << endl;
}
return 0;
}
int main() {
OnLoad();
system("pause");
return 0;
}
This code only returns Yes back, after the console window pops up and ask are you here to take over the city from zombies even after i type no it returns yes!
if (userInput == "yes" || "Yes")
actually means
if ((userInput == "yes") || ("Yes"))
It's logical OR between two expressions: userInput == "yes" and "Yes". The first one is correct and evaluates to bool directly. The second one is just a char* that will be converted to bool implicitly. Since it's a compile time string it cannot be nullptr, which means it will always evaluate to true. And that, in turn, means the whole condition is always true (that's how logical OR works).
The correct code is
if (userInput == "yes" || userInput == "Yes")
P. S. This is why I always recommend compiling with the highest warning level possible (/W4 for MSVC, -Wall -pedantic-errors for GCC and clang). Most compilers will generate a warning in this case.
that's not how the || operator works, if you just put "Yes" as a condition it will always evaluate to true
if (userInput == "yes" || userInput == "Yes") {
cout << "Yes" << endl;
}
the reason why is because of precedence
userInput == "yes"
and
userInput == "Yes"
get evaluated before || ( logical OR)