Getline() always takes input - c++

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

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

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.

Menu char input to int

I'm working on something along the lines of a console based Tamagotchi (I can't draw, so I'm working with what I've got). For my menu functions, I'm trying to present a menu > take in user input as a char > convert the char to an int > perform selection.
#include <iostream>
//Functions
void menuShow();
int menuChoice();
void menuAction();
int main()
{
menuAction();
}
//Menu display
void menuShow()
{
std::cout << "\nPlease choose from the following:" << std::endl;
std::cout << "(S)tatus of your pet." << std::endl;
std::cout << "(F)eed your pet." << std::endl;
std::cout << "(Q)uit." << std::endl;
}
//Convert input from char to int
int menuChoice()
{
char userChoice;
int convertChoice = 0;
do
{
menuShow();
std::cout << "Choice: ";
std::cin >> userChoice;
if ((userChoice = 'S') || (userChoice = 's'))
{
convertChoice = 1;
}
else if ((userChoice = 'F') || (userChoice = 'f'))
{
convertChoice = 2;
}
else if ((userChoice = 'Q') || (userChoice = 'q'))
{
convertChoice = 3;
}
} while ((userChoice != 'S') || (userChoice != 's') || (userChoice != 'F') || (userChoice != 'f') || (userChoice != 'Q') || (userChoice != 'q')); //Repeat if incorrect selection is made
return convertChoice; //return converted int
}
//Get converted choice and perform related action
void menuAction()
{
int choice;
do
{
choice = menuChoice(); //initialize using returned convertChoice
switch (choice)
{
case 1:
std::cout << "You look at your pets' stats" << std::endl;
break;
case 2:
std::cout << "You feed your pet" << std::endl;
break;
default:
std::cout << "You have quit!" << std::endl;
break;
}
} while (choice != 3);
}
As of right now it doesn't accept an input and perform the action, it just spits out the menu over and over. So my questions are: 1) Am I on the right track for this conversion to work or am I not even close? 2) If I'm way off, can you push me in the right direction (given that this is possible)?
Also, I know this could be taken care of by using int's for the user selections and passed to the switch. However, I wanted to see if I could do this for future reference, as well as try to think "outside the box" in terms of the repetitive "option 1:", option 2:", etc.

C++ Tic Tac Toe Game: My code is doubling my outcome from my loop. What is wrong?

#include <iostream>
#include <cctype>
#include <ctime>
#include "Console.h"
using namespace System;
using namespace std;
int main()
{
// Console::SetCursorPosition(10,10 );
const int Rows = 3, Cols = 3;
char gameBoard[Rows][Cols]{
};
do
{
Console::Clear();
for (size_t row = 0; row < Rows; row++)
{
Console::SetCursorPosition(30, 10 + row);
for (size_t col = 0; col < Cols; col++)
{
cout << "|" << gameBoard[row][col];
}
cout << '|';
cout << "\n";
}
int rowInput;
int colInput;
Console::SetCursorPosition(28, 15);
cout << "Row (0 -> 2): ";
cin >> rowInput;
if (cin.fail() == true)
{
cin.clear();
cin.ignore(INT_MAX, '\n');
}
else if (rowInput <= 0 || rowInput >= 3)
break;
Console::SetCursorPosition(28, 16);
cout << "Col (0 -> 2): ";
cin >> colInput;
do
{
if (gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O'){
cout << "That is already taken";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
else {
break;
}
} while (true);
gameBoard[rowInput][colInput] = 'X';
// system("pause");
// return 0;
cout << "\n";
} while (true);
system("pause");
return 0;
}
The code that is outputting twice is :
do
{
if (gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O'){
cout << "That is already taken";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
else {
break;
}
} while (true);
This is part of my Tic Tac Toe game, but I am not sure why it prints out "This is already taken" twice. Any help is appreciated. Also another tip I am looking to receive if anyone can show me is how to make the game pick a random spot for the AI to choose.
You can follow the code through here quite easily. Singlestepping through windows debug should do the trick.
So, we enter our row and column values. Because you don't do cin.ignore after doing cin >> colInput there's still a \n on the input stream.
We check if that part of the board is already filled. Lets assume it is.
We output our message (without a newline at the end, I note)
We clear cin by ignoring everything up until the last \n. cin is now empty.
We reach while (true)
We check to see if that part of the board is already filled. It still is! We haven't changed our location yet!
We output our message (without a newline at the end, I note)
We clear cin by ignoring everything up until the last \n. Because cin is empty, this causes the program to wait until enter is returned.
As you can see, you've got yourself stuck in an infinite loop. That do...while loop needs to be rethought.
do
{
/* 2 and 6 */ if (gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O'){
/* 3 and 7 */ cout << "That is already taken";
/* 4 and 8 */ cin.clear();
cin.ignore(INT_MAX, '\n');
}
else {
break;
}
/* 5 */ } while (true);
Your loop has several problems, the code:
do
{
if (gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O'){
cout << "That is already taken";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
else {
break;
}
} while (true);
is equivalent to:
while (gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O'){
cout << "That is already taken";
cin.clear();
cin.ignore(INT_MAX, '\n');
};
and if you pay attention, the condition gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O' don't change its status, due to the variables rowInput and colInput are never modified inside the loop.
By the way, I think you don't need that loop at all. Just the code inside:
if (gameBoard[rowInput][colInput] == 'X' || gameBoard[rowInput][colInput] == 'O'){
cout << "That is already taken";
cin.clear();
cin.ignore(INT_MAX, '\n');
}

What is wrong with getchar (as program is exiting without a check at do while loop)?

In this in the main function the usage of getchar in do while loop is creating problem (as per what i m figuring out) and using getch resolves it..plz help why so..
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
const int size = 10;
int main()
{
int stack[size];
int top = -1;
char ch;
char chh;
do {
cout << "what you want to do? 1:Push,2:Pop,3:Display \n";
cin >> ch;
if (ch == '1')
{
int a;
cout << "enter element to be entered";
a = getchar();
int r = push(stack, &top, a);
if (r == -1) cout << "array already full \n";
}
if (ch == '2')
{
pop(stack, &top);
}
if (ch == '3')
{
display(stack, &top);
}
cout << "enter y to continue";
chh = getchar();
} while (chh == 'y');
return 0;
}
Some else clauses will help. Put all those if's into one big if/else if/else loop:
if (ch == '1') { ... }
else if (ch == '2') { ... }
else if (ch == '3') { ... }
else { /*print out the bad char*/ }
You're likely getting a character that you're not expecting, like a carriage return.
Also, why are you mixing cin and getc?