Returning to the loop c++ - c++

I'm trying to do a simple game Guess Number and created a while condition to do that, but I want to insert a question to play again if the player type "Y" on the queue or close the window if the player type "N". My way is not working and I didn't find a solution for this problem.
int main()
{
int guess, number;
char again;
srand(time(0));
number = rand() % 1000 + 1;
while (guess != number)
{
std::cout << "Enter the number guess between 1 and 1000: ";
std::cin >> guess;
if (guess < number)
{
std::cout << "Is more than this" << std::endl;
}
else if (guess > number)
{
std::cout << "Is less than this" << std::endl;
}
else if (guess < 1)
{
std::cout << "The value to guess is between 1 and 1000" << std::endl;
}
else if (guess > 1000)
{
std::cout << "The value to guess is between 1 and 1000" << std::endl;
}
else
{
std::cout << "This is the number" << std::endl;
std::cout << "Do want play again? [Y/N ]" << std::endl;
std::cin >> again;
if (again == 'N' || again == 'n')
{
break;
}
else if (again == 'Y' || again == 'y')
{
continue;
}
}
}

When you correctly guess the number, your while condition becomes false and hence the loop exits (i.e. guess becomes equal to number, and hence the condition guess != number is false). Try changing to condition of the while loop.
char again = 'Y';
while (again == 'Y' || again == 'y') { ... }

Starting with some presumably yet unrecognised problem: You won't reach all of your if branches:
if (guess < number)
{ }
else if (guess > number)
{ }
// now if you really get to the following else, guess was neither
// smaller nor greater than number, i. e. is EQUAL!
else if (guess < 1)
{ /* won't ever be entered as number(!) is never < 1 (be aware: guess == number) */ }
else if (guess > 1000)
{ /* won't ever be entered as number is never > 1000 */ }
else
{ }
You can solve in two variants, by moving the unreachable checks either in front of the initial ones:
if (guess < 1)
{ }
else if (guess > 1000)
{ }
else if (guess < number)
{ }
else if (guess > number)
{ }
else
{ }
or into them:
if (guess < number)
{
if (guess < 1)
{ }
else
{ }
}
else if (guess > number)
{
if (guess > 1000)
{ }
else
{ }
}
else
{ }
Now to the actual problem, let's consider the else:
// be aware that guess == number now!
if (again == 'N' || again == 'n')
{
break; // fine so far...
}
else if (again == 'Y' || again == 'y')
{
continue;
// re-enters the loop - be aware that the condition is still checked!!!
}
// and if none of all was entered???
// as is, we'd just go on with the loop body - as this was the last statement,
// though, the loop will be re-entered by checking the condition; i. e. if
// getting here, we do effectively exactly the same as in the second if check
// above...
OK, so you (implicitly) defined a default of 'y'. You then could just simply remove the second if (else if == y) and nothing would change.
However, the loop condition is not true any more (guess == number still applies!). Easiest now: just make an endless loop of:
for(;;)
{
if(again == 'n')
break;
// obsolete, just drop it:
//if(again == 'y')
// continue;
}
I personally, though, would rather have the 'n' as default (so typing 'x', 'q', 'a' all result in exiting as well), so I'd rather have:
for(;;)
{
if(again != 'y' && again != 'Y')
break;
}

Related

Fixing uninitialized local variable error

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

Trying to figure out how to properly break these nested loops

It's a simple game, where there are 23 sticks and you and the computer can remove 1, 2, or 3 and whoever removes the last one loses. It's, as you likely imagined, a project for a class.
The full code is here.
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
char playAgain = 'Y';
int totalSticks = 23;
int humanStickChoice = 1;
cout<<"**************************** RULES: Remove 1, 2, or 3 sticks per turn.\n";
cout<<"*Welcome to our Game of 23!* The player who removes the very last stick\n";
cout<<"**************************** loses. Good luck!\n";
cout<<endl;
while (totalSticks > 0 && playAgain == 'Y' || playAgain == 'y')
{
cout<<"There are "<<totalSticks<<" sticks left. How many sticks would you like to remove?:\n";
cin>>humanStickChoice;
cout<<endl;
if(totalSticks >= 3){
if(humanStickChoice != 1 && humanStickChoice != 2 && humanStickChoice != 3){
while(humanStickChoice != 1 && humanStickChoice != 2 && humanStickChoice != 3){
cout<<"Invalid choice; you can remove 1, 2, or 3 sticks. Choose again:\n";
cin>>humanStickChoice;
}
}
totalSticks=totalSticks-humanStickChoice;
cout<<"Player removes "<<humanStickChoice<<" sticks.\n";
}
else if(totalSticks == 3){
if(humanStickChoice != 1 && humanStickChoice != 2){
while(humanStickChoice != 1 && humanStickChoice != 2){
cout<<"Invalid choice; you can remove 1 or 2 sticks. Choose again:\n";
cin>>humanStickChoice;
}
}
}
else if(totalSticks == 2){
if(humanStickChoice != 1){
while(humanStickChoice != 1){
cout<<"Invalid choice; as there are 2 sticks remaining, you can remove only one.\n";
cin>>humanStickChoice;
}
}
totalSticks=totalSticks-humanStickChoice;
cout<<"Player removes "<<humanStickChoice<<" sticks.\n";
}
else if(totalSticks == 1){
if(humanStickChoice != 1){
while(humanStickChoice != 1){
cout<<"Invalid choice; as there is 1 stick remaining, you can remove only one.\n";
cin>>humanStickChoice;
}
}
int humanStickChoice = 1;
cout<<"Player removes "<<humanStickChoice<<" stick.\n";
totalSticks=totalSticks-humanStickChoice;
cout<<"*************************************************\n";
cout<<"Player removed the last stick! Computer wins!";
if(totalSticks == 0){
cout<<endl<<"Would you like to play again? If so, input Y and hit return.\n";
cin>>playAgain;
totalSticks = 23;
}
}
//This block above is where the logic error is occurring; instead of going back to the
//beginning of the "main" while loop and starting over with the human player starting,
//the totalSticks count is merely replenished and the program continues to go on with the
//computer making the first move; the human is supposed to make the first move every game.
if(totalSticks > 4){
int computerStickChoice = (4-humanStickChoice);
cout<<"Computer removes "<<computerStickChoice<<" sticks.\n";
totalSticks=totalSticks-computerStickChoice;
}
else if(totalSticks == 4){
int computerStickChoice = 3;
cout<<"Computer removes "<<computerStickChoice<<" sticks.\n";
totalSticks=totalSticks-computerStickChoice;
}
else if(totalSticks == 3){
int computerStickChoice = 2;
cout<<"Computer removes "<<computerStickChoice<<" sticks.\n";
totalSticks=totalSticks-computerStickChoice;
}
else if(totalSticks == 2){
int computerStickChoice = 1;
cout<<"Computer removes "<<computerStickChoice<<" stick.\n";
totalSticks=totalSticks-computerStickChoice;
}
else if(totalSticks == 1){
int computerStickChoice = 1;
cout<<"Computer removes "<<computerStickChoice<<" stick.\n";
totalSticks=totalSticks-computerStickChoice;
cout<<"*************************************************\n";
cout<<"Computer removed the last stick! You win!";
if(totalSticks == 0){
cout<<endl<<"Would you like to play again? If so, input Y and hit return.\n";
cin>>playAgain;
totalSticks = 23;
}
}
}
return 0;
}
The section causing the error:
else if(totalSticks == 1){
if(humanStickChoice != 1){
while(humanStickChoice != 1){
cout<<"Invalid choice; as there is 1 stick remaining, you can ";
"remove only one.\n";
cin>>humanStickChoice;
}
}
int humanStickChoice = 1;
cout<<"Player removes "<<humanStickChoice<<" stick.\n";
totalSticks=totalSticks-humanStickChoice;
cout<<"*************************************************\n";
cout<<"Player removed the last stick! Computer wins!";
if(totalSticks == 0){
cout<<endl<<"Would you like to play again? If so, input Y and hit
return.\n";
cin>>playAgain;
totalSticks = 23;
}
}
I've debugged every scenario (I think) where these nested loops could break except for one which I can't figure out.
I've added comment lines above it to explain but I'll explain here as well; when the player loses in the last else-if block, the # of sticks are replenished and there is a cin-input to ask the user if they want to play another game. It's supposed to start over and have them play the first move, but, it's just continuing down the code and having the computer make the first move.
How do I have the human make the first move again?
I tried using break; and messing with the "main" while loop requirements but I can't get it right.
Use continue to skip the rest of the loop body and go immediately to the next iteration.
Use break to exit the loop completely. So the final test should be:
if(totalSticks == 0){
cout<<endl<<"Would you like to play again? If so, input Y and hit
return.\n";
cin>>playAgain;
if (playAgain == 'y' || playAgain == 'Y') {
totalSticks = 23;
continue;
} else {
break;
}
}
With this change, there's also no need to test playAgain in the while condition. The test here handles it completely.
Im short on time so not the most ideal way to do it but here's the code:
humanFirstMove = false;
cout << "There are " << totalSticks << " sticks left. How many sticks would you like to remove?:\n";
cin >> humanStickChoice;
cout << endl;
And
if (totalSticks == 0) {
cout << endl << "Would you like to play again? If
so, input Y and hit return.\n";
cin >> playAgain;
totalSticks = 23;
humanFirstMove = true;
}
Finally
//This block above is where the logic error is
occurring;instead of going back to the
//beginning of the "main" while loop and starting over with the human player starting,
//the totalSticks count is merely replenished and the program continues to go on with the
//computer making the first move; the human is supposed to make the first move every game.
if (!humanFirstMove) {
if (totalSticks > 4) {
int computerStickChoice = (4 - humanStickChoice);
cout << "Computer removes " << computerStickChoice << " sticks.\n";
totalSticks = totalSticks - computerStickChoice;
}
Pretty much just added a boolean

How to check every character in string?

The program will ask user to input strand which has to be composed of only ABCD and if the input contains letter other than ABCD it must show error, otherwise it should output "ok!"
string strand1;
again:
cout << "Enter String 1:\n";
cin >> strand1;
for (int i = 0; i <= strand1.length(); i++)
{
if (strand1.at(i) != 'A'&&strand1.at(i) != 'B'&&strand1.at(i) != 'C'&&strand1.at(i) != 'D')
{
cout << "Invalid Input";
system("cls");
goto again;
}
else
{
i++;
}
}
cout << "ok";
_getch();
return 0;
Move the necessary checks to a function -- isValidInput.
Use hand coded logic to check whether the input is valid or use the standard library function std::find_if to do the same.
Use the function in a while loop in the main function.
bool isNotABCD(char c)
{
return !((c == 'A') || (c == 'B') || (c == 'C') || (c == 'D'));
}
bool isValidInput(std::string const& str)
{
return (std::find_if(str.begin(), str.end(), isNotABCD) == str.end());
}
int main()
{
string strand1;
cout << "Enter String 1:\n";
while ( cin >> strand1 && !isValidInput(strand1) )
{
cout << "Invalid Input";
system("cls");
cout << "Enter String 1:\n";
}
cout << "ok";
}
Update
You can also use a simpler version of isValidInput(), Thanks to #Blastfurnace for the suggestion.
bool isABCD(char c)
{
return (c == 'A') || (c == 'B') || (c == 'C') || (c == 'D');
}
bool isValidInput(std::string const& str)
{
return (std::all_of(str.begin(), str.end(), isABCD));
}
Update 2
You can also use a still simpler version of isValidInput(), Thanks to #JorenHeit for the suggestion.
bool isValidInput(std::string const& str)
{
return (std::find_first_not_of("ABCD") == std::string::npos);
}
Your question is unclear, but after examining your code I believe the problem is that for your loop condition you are using i <= strand1.length when you should be using i < strand1.length.
The loop condition you are using will check an index out of bounds of the string. In addition, you should not be incrementing i in the else statement as that is already done in the for statement. In the future, please clearly state your question along with any error codes you are getting.

Getline() always takes input

I am capturing video from my webcam and if the user hits the Enter key I take a picture. Then I ask "Is the picture okay?" to user and wait for an input. If he says "No", I keep doing the same thing, until he says "Yes".
But if he says "No", and in the meantime I type something in the terminal, getline() function writes whatever I type into its buffer, and when I ask the question again it goes directly to "invalid input" state.
How do I prevent this?
I have read a lot of questions regarding this and I tried to use cin.ignore() and cin.clear() before/after after I call getline(), but they didn't help.
// Do capturing here
string choice;
int choiceIsOkay = 0;
while (choiceIsOkay == 0)
{
cout << "Is the picture okay? (Y/N): ";
getline(cin, choice);
if ((choice == "Y") || (choice == "y"))
{
choiceIsOkay = 2;
}
else if ((choice == "N") || (choice == "n"))
{
choiceIsOkay = 1;
}
else
{
cout << "\nInvalid input\n";
choiceIsOkay = 0;
}
}
if (choiceIsOkay == 2)
{
runAlgorithm = 1;
break;
}
else choiceIsOkay = 0;
If I understand your issue, if user enters Some Random Text In, your program always jump in "Invalid input" and never stops to wait for users input. Following code should resolve your issue.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int runAlgorithm;
// Do capturing here
int i = 0;
while (i++ < 3)
{
int choiceIsOkay = 0;
string choice;
while (choiceIsOkay == 0)
{
cout << "Is the picture okay? (Y/N): ";
getline(cin, choice);
if ((choice == "Y") || (choice == "y"))
{
choiceIsOkay = 2;
}
else if ((choice == "N") || (choice == "n"))
{
choiceIsOkay = 1;
}
else
{
cout << "nInvalid inputn";
choiceIsOkay = 0;
}
// Ignore to the end of line
cin.clear();
}
}
return 0;
}

Infinite While loop in C++

I am teaching myself c++ and am building a simple menu program. Im a complete noob to C++ so I apologize in advance for the question if it seems foolish. My code continuously calls getNum() and never exits, despite the correct menu selections. What am I doing wrong? Here is my code:
#include <iostream>
#include <string>
using namespace std;
void calc();
void pass();
string getNum(string num);
int main(int argc, const char * argv[])
{
string num = "0";
string menu = "Enter... \n 1 For calculator \n 2 for Passwords";
cout << "Hello this is a sample menu program" << endl;
while(num != "1" || num != "2")
{
getNum(num);
cout << "You selected: " << num << endl;
}
if(num == "1"){
calc();
}
else {
pass();
}
}
void calc() {
cout << " You are running the calculator" << endl;
}
void pass() {
cout << "You are running passwords" << endl;
}
string getNum(string num) {
cout << "What would you like to do?" << endl;
cout << "Enter... \n 1 For calculator \n 2 for Passwords" << endl;
getline(cin, num);
return num;
}
Change this condition
while(num != "1" || num != "2")
to
while(num != "1" && num != "2")
To write the condition correctly you should consider that the loop should not be repeated if num either equal to "1" or "2". This condition can be written as
num == "1" || num == "2"
However the loop shall be repeated if this condition is not true. So the condition for the loop will be repeated will look like
! ( num == "1" || num == "2" )
According to the mathematical logic this condition is equivalent to
num != "1" && num != "2"
It would be better to rewrite the loop like
string num;
//...
do
{
getNum(num);
cout << "You selected: " << num << endl;
} while ( num != "1" && num != "2")
At least one iteration should be done in any case should not it?
Also define the function as
void getNum(string &num);
//...
void getNum( string &num) {
cout << "What would you like to do?" << endl;
cout << "Enter... \n 1 For calculator \n 2 for Passwords" << endl;
getline(cin, num);
}
getNum(num);
In getNum you have a return statement that returns what the user entered. When you call getNum you don't save that return value.
num = getNum(num);
To make things clearer, I would remove the input parameter from getNum. You don't need to pass anything to it since it's job is to prompt for a number and return that number.
string getNum() {
cout << "What would you like to do?" << endl;
cout << "Enter... \n 1 For calculator \n 2 for Passwords" << endl;
string num;
getline(cin, num);
return num;
}
Then change the call to:
num = getNum();
Another issue is your loop condition.
while(num != "1" || num != "2")
Think about what this will do if num were, say, "1". You'd want the loop to stop, right? Look what happens if we evaluate and reduce the expression bit by bit:
while(num != "1" || num != "2")
while("1" != "1" || "1" != "2")
while(false || true)
while(true)
Well that's not right. It should have evaluated to false. The || should be &&.
while(num != "1" && num != "2")
Line
while(num != "1" || num != "2")
be DeMorgan laws is the same as
while(!(num == "1" && num == "2"))
So you need
(num == "1" && num == "2")
to be true
Hence the difficulty
apart from the other bits of the code that are in error
You have written while(num != "1" || num != "2")
so either num would be equal to "1" or "2" or none of these. In any condition one of these condition is true( i.e. either num is not equals to 1 , this is true or num is not equals to 2 , this is true), therefore your while loop is always true and continuously run without stop
this condition
while(num != "1" || num != "2")
will always return true for all inputs. for example, "1", it is false on num != "1" but will still return true on the other condition num != 2, thus it will never exit (true || false == true)
also it should be
else if(num == '2') {
pass();
}
correct condition should be while(!(num != "1" && num != "2")) to only allow "1" and "2" inputs