Cin Not Working in While Loop [duplicate] - c++

Here Im trying to get an integer from user, looping while the input is correct.
After entering non integer value (e.g "dsdfgsdg") cin.fail() returns true, as expected and while loop body starts executing.
Here I reset error flags of cin, using cin.clear(); and cin.fail() returns false, as expected.
But next call to cin doesn't work and sets error flags back on.
Any ideas?
#include<iostream>
using namespace std;
int main() {
int a;
cin >> a;
while (cin.fail()) {
cout << "Incorrect data. Enter new integer:\n";
cin.clear();
cin >> a;
}
}

After cin.clear(), you do this:
#include <iostream> //std::streamsize, std::cin
#include <limits> //std::numeric_limits
....
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
What the above does is that it clears the input stream of any characters that are still left there. Otherwise cin will continue trying to read the same characters and failing

As a matter of style, prefer this method:
int main()
{
int a;
while (!(std::cin >> a))
{
std::cout << "Incorrect data. Enter new integer:" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}

cin.clear() does not clear the buffer; it resets the error flags. So you will still have the sting you entered in your buffer and the code will not allow you to enter new data until you clear the cin buffer. cin.Ignore() should do the trick

There is also a very easy method:
#include <iostream>
std::cin.clear() //reset stream state so that cin.fail() becomes false.
std::cin.ignore(INT_MAX,'\n'); //clear the stream from any remaining characters until the \n which is present at the end of any cin.
This will reset stream state and clear any remaining things in it. Much easier, less code, and less header files.

Related

Need to ask for car make in C++ program [duplicate]

In the following code, getline() skips reading the first line.
I noted that when commenting the "cin >> T" line, it works normally. But I can't figure out the reason.
I want to read an integer before reading lines! How to fix that?
#include <iostream>
using namespace std;
int main () {
int T, i = 1;
string line;
cin >> T;
while (i <= T) {
getline(cin, line);
cout << i << ": " << line << endl;
i++;
}
return 0;
}
cin >> T;
This consumes the integer you provide on stdin.
The first time you call:
getline(cin, line)
...you consume the newline after your integer.
You can get cin to ignore the newline by adding the following line after cin >> T;:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
(You'll need #include <limits> for std::numeric_limits)
Most likely there is a newline in your input file, and that is being processed immediately, as explained on this page:
http://augustcouncil.com/~tgibson/tutorial/iotips.html
You may want to call cin.ignore() to have it reject one character, but, you may want to read more of the tips, as there are suggestions about how to handle reading in numbers.
This line only reads a number:
cin >> T;
If you want to parse user input you need to take into account they keep hitting <enter> because the input is buffered. To get around this somtimes it is simpler to read interactive input using getline. Then parse the content of the line.
std::string userInput;
std::getline(std::cin, userInput);
std::stringstream(userInput) >> T;

Cin not waiting for input despite cin.ignore()

I'm new to C++ and I'm using Visual Studio 2015.
cin is not waiting for input after "Please enter another integer:\n" and outputs "You entered 0" every time.
I've searched the Internet more than an hour without a solution. No combination of cin.ignore() is working. Why is the cin buffer still not cleared?
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vals;
int val = 0;
int n = 0;
cout << "Please enter some integers (press a non-numerical key to stop)\n";
while (cin >> val)
vals.push_back(val);
cin.ignore(INT_MAX, '\n');
cin.ignore();
cout << "Please enter another integer:\n";
cin.ignore();
cin >> n;
cout << "You entered " << n;
system("pause");
return 0;
}
The problem is for the user to exit the loop you need to put the cin in a failed state. That is why your
while(cin >> val){ .... }
is working.
If in a failed state cin is no longer in a position to supply you with input so you need to clear() the failed state. You also need to ignore() the previously non-integer response that triggered the failed state initially.
It would also be of merit to use
if(cin >> n){
cout << "You entered " << n;
}
This will assert that a proper input for n was provided.
The problem in your program is that it expects integers, whereas a user can input anything, like a non-integer char.
A better way to do what you seem to want to do is to read characters one by one, ignoring whitespace, and if it's a digit, then continue reading to get the whole number, else stop the loop. Then you can read all chars until you reach '\n', and do the same for one number. While you do that, for each character you should check that there can still be characters in the stream with cin.eof().
Also, instead of using system("pause"), you can prevent the command line window from closing by requesting a last character before terminating the application.
Try getting your integers like this :
#include <sstream>
...
fflush(stdin);
int myNum;
string userInput = "";
getline(cin, userInput);
stringstream s (userInput);
if (s >> myNum) // try to convert the input to int (if there is any int)
vals.push_back(myNum);
without sstream you have to use try catch, so your programme won't crash when input is not an integer

Why does this code give me an infinite loop?

When I enter in a correct value (an integer) it is good. But when I enter in a character, I get an infinite loop. I've looked at every side of this code and could not find a problem with it. Why is this happening? I'm using g++ 4.7 on Windows.
#include <iostream>
#include <limits>
int main()
{
int n;
while (!(std::cin >> n))
{
std::cout << "Please try again.\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
}
}
Input: x
Output:
It's because your recover operations are in the wrong order. First clear the error then clear the buffer.
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You have to clear the error state first, and then ignore the unparsable buffer content. Otherwise, ignore will do nothing on a stream that's not in a good state.
You will separately need to deal with reaching the end of the stream.

Code stuck looping while when numeric value entered

Hey my code is stuck on looping my while when I input numeric letters, it just floods my output with "Invalid Input, please try again." It's just a simple menu.
If you ever enter anything "invalid", such that reading from cin will cause an error, you have to call cin.clear() to be able to read further input, otherwise the stream in operator will just return immediately.
Typically, when reading user input, you check the state of cin and exit or do some error handling when it is invalid. In addition, on a failed input attempt, the characters that caused the error will still be sitting in cin, and need to be ignored (e.g., up to the next newline):
#include <iostream>
#include <limits>
int main() {
int userOption;
while(1) {
while(!(std::cin >> userOption)) {
std::cout << "Invalid input." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << userOption << std::endl;
}
return 0;
}
The problem is with the following line of code,
cin.ignore(numeric_limits<streamsize>::max(), '\n');
When you are entering a single number, you don't have to ignore any other character. So simply remove the above line of code to correct your program.

How to validate numeric input in C++

I'd like to know how to limit an input value to signed decimals using std::cin.
double i;
//Reading the value
cin >> i;
//Numeric input validation
if(!cin.eof())
{
peeked = cin.peek();
if(peeked == 10 && cin.good())
{
//Good!
count << "i is a decimal";
}
else
{
count << "i is not a decimal";
cin.clear();
cin >> discard;
}
}
This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.
If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:
int someVal;
while(!(cin >> someVal)) {
cin.reset();
cout << "Invalid value, try again.";
}
Combining the techniques from the top answer here and this website, I get
input.h
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
inputtest.cpp
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}
Sample run
Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.
cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char for the second field.
I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.
Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:
#include <iostream>
#include <cstdlib>
// #arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
using namespace std; // *1
while(true)
{
cout << prompt;
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp)
return ret;
}
}
*1: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
Something like:
double a;
cin >> a;
Should read your signed "decimal" fine.
You'll need a loop and some code to make sure it handles invalid input in a sensible way.
Good luck!