Not waiting for std::cin.ignore() - c++

Based on this answer, I've written the following code
#include <iostream>
#include <vector>
#include <cstddef>
#include <limits>
int main()
{
std::cout << "Enter x and y size, followed by enter: ";
std::size_t nrOfRows, nrOfCols;
std::cin >> nrOfRows >> nrOfCols;
// initialize dynamic array of arrays
std::vector<std::vector<char>> data(nrOfRows,
std::vector<char>(nrOfCols, 'O'));
// print array
for (std::size_t rowNr = 0; rowNr < nrOfRows; rowNr++)
{
std::cout << "Row " << rowNr << ": ";
for (const auto& el : data[rowNr])
std::cout << el << " ";
std::cout << std::endl;
}
std::cout << "Press enter to continue: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Compiled with VC++ 14.1 or Visual studio 2017 v15.7.4.
After the first prompt I enter e.g. "3 5" and enter. Then the program just rolls through and exits. E.g. it outputs the strings and does not wait for the final user input (enter) at std::cin.ignore().
What did I miss?
edit
For the down-voters/nay sayers. This code does work as described.
#include <iostream>
#include <limits>
int main()
{
std::cout << "Press enter to continue: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Your problem is that the extraction operation (std::cin >> nrOfRows >> nrOfCols;) will leave delimiting whitespace in the stream, unlike getline(), which will consume the delimiter. This normally isn't a problem because the >> operator will also ignore leading whitespace, but the line break left in the stream will cause std::istream::ignore() to not wait for input.
To fix this, add a call to std::istream::ignore() to discard any whitespace before you output the Press enter to continue: message.

Related

C++ istream (cin) and problem with waiting for a ENTER key press

Please, is there a way I can wait for a single ENTER key press in all of the below cases? It works fine except when the std::getline() is used, which consumes the \n, and the ENTER needs to be pressed twice.
The code below works fine:
#include <iostream>
#include <limits>
using std::cout;
using std::cin;
using std::string;
void waitForENTERKeyPress();
int main ()
{
char c;
string s;
cout << "Enter c:"; cin >> c;
waitForENTERKeyPress();
cout << "Enter c:"; c = cin.get();
waitForENTERKeyPress();
cout << "Enter s:"; cin >> s;
waitForENTERKeyPress();
cout << "Enter s:"; std::getline(cin, s);
waitForENTERKeyPress();
return 0;
}
void waitForENTERKeyPress()
{
// Does not work with std::getline(...)
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Press an ENTER to continue...\n";
cin.get();
}
====[UPDATE]============================================
Let me rephrase what I am looking for: The way how to make the waitForENTERKeyPress() function working in both cases – with \n in the buffer, when cin operator >> or cin.get() is used and also in cases the std::getline() is used.
From what I understand it is not possible as there is not a way how to detect if the \n is still in the buffer or not.
I have tried to use cin.rdbuf()->in_avail(), but it always returns 0.

C++ can't have cin.ignore() after cin?

I'm having an issue using cin.ignore(), if I use it after a cin >> statement it doesn't seem to work and ends the program instead.
Here's my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int number ;
int main () {
cin >> number;
cout << number;
cin.ignore()
return 0;
}
I am typing " 4 " (without quotes) at the prompt. I'm expecting it to prompt for an int (which it does) and then display that int until the user presses enter again. However as soon as I press enter on the first prompt the program closes. If I replace the cin.ignore() with a new cin >> then it waits until I enter data at that prompt before closing, however this way I have to put data into the prompt, I can't just press enter to close it.
I read about putting cin.clear() after the cin input but that didn't help. If I replace cin.ignore() with cin >> num2; then it works fine.
What am I doing wrong?
You can reset your input stream and ignore the rest of it if for example your user did not enter a valid int type as input. The while loop will not exit until number contains an actual integer. After that, if you want the program to wait until the user presses "Enter" or any other key, you can just call ignore again.
#include <limits>
#include <iostream>
int main()
{
int number;
// we need to enforce that the input can be stored as `int` type
while(!(std::cin >> number))
{
std::cout << "Invalid value! Please enter a number." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cout << "Your number is: " << number << std::endl;
// wait for user to press Enter before exiting
// you can do this with ignore() x2 once for the newline
// and then again for more user input
std::cout << "Press Enter to exit." << std::endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
return 0;
}

C++11 : cin doesn't wait for user input and ends the loop

My program takes user data as a tuple and stores it into a vector. There is no limit to how many tuples can be added and vector size changes with the adding of tuples. The program asks the user if they want to add another tuple. If no, the loop exits.
My problem is, when the program was supposed to wait for 'yes' or 'no' input, it skipped the cin and exited the loop.
I have tried searching for solutions, tried clearing the buffer but I am back to square one.
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
using namespace std;
void print(vector<tuple<int, string, string, bool>> const & data)
{
if (data.size() != 0)
{
for (auto row : data)
{
cout << get<0>(row) << ", " << get<1>(row) << ", " << get<2>(row)
<< ", " << get<3>(row) << endl;
}
}
else
{
cout << "\nNO ENTRIES CURRENTLY!";
}
}
int main()
{
int id;
char go;
string name, filePath;
bool flag = false;
typedef tuple<int, string, string, bool> pData;
vector<pData> pList;
do
{
cout << "Enter a Pattern Call:" << endl;
cin >> id >> name >> filePath >> flag;
pList.push_back(make_tuple(id, name, filePath, flag));
cout << "Do You wish to add another: ";
cin.ignore();
cin >> go; //The control skips here and exits the loop.
} while (go == 'y' || go == 'Y');
print(pList);
return 0;
}
I have a hack which seems to work on my Linux Machine.
Add cin.clear() before cin.ignore()
Replace cin.ignore() with cin.ignore(1)
Part of your code should look as below:
cout << "Do You wish to add another: ";
cin.clear();
cin.ignore(1);
cin >> go; //The control skips here and exits the loop.
Look here:
How do I flush the cin buffer?
Using cin is not that easy or safe if user input is not exactly what we want.

c++ std::cin being ignored (buffer?) [duplicate]

I'm having a problem with what should be incredibly simple code. I want to take in an integer between 1 and 3 with error checking. It works fine for checking for numbers that are too large or too small, but when a alpha/number combination is entered, it gets stuck in an infinite loop. Suggestions?
#include <iostream>
using namespace std;
int main(int argc, char *argv[]){
int input;
cout << "\nPlease enter a number from 1 to 3:" << endl;
cout << "-> ";
cin >> input;
while(input< 1 || input> 3){
cout << "\n---------------------------------------" << endl;
cout << "\n[!] The number you entered was invalid." << endl;
cout << "\nPlease re-enter a number from 1 to 3" << endl;
cout << "-> ";
cin >> input;
}
cout << "You chose " << input << endl;
}
The problem is that:
cin >> input;
Will cause the bad bit to be set when you try and read a non numeric value. After that happens any attempt to use the operator>> is silently ignored.
So the way to correct for this is to test if the stream is in a good state and if not then reset the state flags and try and read again. But note that the bad input (that caused the problem) is still on the input so you need to make sure you throw it away as well.
if (cin >> input)
{
// It worked (input is now in a good state)
}
else
{
// input is in a bad state.
// So first clear the state.
cin.clear();
// Now you must get rid of the bad input.
// Personally I would just ignore the rest of the line
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// now that you have reset the stream you can go back and try and read again.
}
To prevent it getting stuck (which is caused by the bad bit being set) read into a string then use a string stream to parse user input. I also prefer this method (for user interactive input) as it allows for easier combination of different styles of reading (ie combining operator>> and std::getline() as you can use these on the stringstream).
#include <iostream>
#include <sstream>
#include <string>
// using namespace std;
// Try to stop using this.
// For anything other than a toy program it becomes a problem.
int main(int argc, char *argv[])
{
int input;
std::string line;
while(std::getline(std::cin, line)) // read a line at a time for parsing.
{
std::stringstream linestream(line);
if (!(linestream >> input))
{
// input was not a number
// Error message and try again
continue;
}
if ((input < 1) || (input > 3))
{
// Error out of range
// Message and try again
continue;
}
char errorTest;
if (linestream >> errorTest)
{
// There was extra stuff on the same line.
// ie sobody typed 2x<enter>
// Error Message;
continue;
}
// it worked perfectly.
// The value is now in input.
// So break out of the loop.
break;
}
}
#include <iostream>
#include <string>
using namespace std;
int validatedInput(int min = 1, int max = 3)
{
while(true)
{
cout << "Enter a number: ";
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp && ret >= min && ret <= max)
return ret;
cout << "Invalid input. Allowed range: " << min << "-" << max <<endl;
}
}
int main(int argc, char *argv[])
{
int val = validatedInput();
cout << "You entered " << val <<endl;
return 0;
}
Most of these answers include unnecessary complexity.
Input validation is a perfect time to use a do-while
do{
cout << "\nPlease enter a number from 1 to 3:" << endl;
cout << "-> ";
if(!cin){
cout << "Invalid input"
cin.clear()
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}while(!(cin >> input))
Use numeric_limits<streamsize>::max() to completely clear the
buffer after a failed cin.
Use cin.clear() to reset the fail flag on cin so !cin wont
always evaluate false.
cin.fail() is fine. However some would consider !cin more natural.
from my previous post https://stackoverflow.com/a/43421325/5890809
You declared input as int but when you write an alphanumeric character to input it will try to implicitly convert it into integer. But you error checking does not account for this.
Ur problem can be easily solved by changing your while loop. instead of checking this how about you check
while(input!=1 || input!=2 || input!=3)

Fix spacing in copycat program

Here is my code for a basic copycat program that just copys whatever the user types:
#include <iostream>
using namespace std;
#include <string>
int main()
{
cout << "type something.. I dare you..." << endl;
for (;;)
{
string usrin;
cout << "You: ";
cin >> usrin;
cout << "Me: " << usrin;
}
return 0;
}
But when the user inputs more than one word i get this:
Me: more
You: than
You: Me: one
You: Me: word
You:
any and all help is appreciated! thank you!
You need to use cin.getline(usrin) instead of cin >> usrin.
cin >> usrin stops reading when it finds whitespace characters in the stream but leaves the rest of the stream for the next time cin is used.
cin.getline will read until the end of the line. However, you will need to change usrin to an array of char.
char usrln[MAX_LINE_LENGTH];
where MAX_LINE_LENGTH is a constant that is bigger than the length of the longest line you expect to see.
After each input, \n leaved behind in input buffer and read on next iteration. You need to flush your input buffer. Use
cin.ignore(MAX_INT, '\n'); //Ignores to the end of line
Add <limits.h> header.
#include <iostream>
#include <limits.h>
#include <string>
using namespace std;
int main()
{
cout << "type something.. I dare you..." << endl;
for (;;)
{
string usrin;
cout << "You: ";
cin >> usrin;
cout << "Me: " << usrin ;//<<endl;
cin.ignore(INT_MAX, '\n');
}
return 0;
}