Read Integer from User - c++

I am trying to read an integer from terminal. Here's my code:
int readNumber()
{
int x;
std::cin >> x;
while(std::cin.fail())
{
std::cin.clear();
std::cin.ignore();
std::cout << "Bad entry. Enter a NUMBER: ";
std::cin >> x;
}
return x;
}
Whenever I run this code I get:
Type in the number for the newsgroup that shall be deleted:
joöä
Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: Bad entry. Enter a NUMBER: 8
Why does it write "bad entry" multiple times?
If I remove std::cin.clear(); or std::cin.ignore();, the program just keeps writing
Enter a NUMBER: Bad entry. Can anyone explain why it does that?

This is actually a partial duplicate of an old question, but it is phrased differently enough that I will address it briefly here.
You get infinite printing without those two lines, because cin.clear() is required to clear the error flag that cin.fail() is reading. See the linked question for details.
Why does it still print more than once when those lines are there? When you do std::cin >> x;, your code will read the first character in your input, and attempt to parse it as an int. It will fail, and then in the next iteration of the loop, it will attempt to parse the next character and fail again. For each failure (that is, each character in your input), it will print Bad entry. Enter a NUMBER:. If you type some bad input with fewer characters, you will see what I mean.
There are multiple ways to fix this problem, but one simple fix is to read the entire input into a string, and try to parse it, instead of using cin directly into an int. Here is some sample code which needs to be compiled with one of the various compiler-dependent flags for C++11. I have tested it with your input and it appears to achieve the effect you desire.
#include <iostream>
#include <string>
#include <stdexcept>
bool tryParse(std::string& input, int& output) {
try{
output = std::stoi(input);
} catch (std::invalid_argument) {
return false;
}
return true;
}
int main(){
std::string input;
int x;
getline(std::cin, input);
while (!tryParse(input, x))
{
std::cout << "Bad entry. Enter a NUMBER: ";
getline(std::cin, input);
}
return x;
}

Try this anyway... As I type this directly into stackoverflow might have compilation error
int readNumber()
{
int x=0;
while(true)
{
std::cin >> x;
if(!std::cin.fail()){
break;
}
else{
std::cout << "Bad entry. Enter a NUMBER: " << std::endl;
std::cin.clear();
std::cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
}
}
}

int main() {
char* input;
std::cin >> input;
int x = std::atoi(input);
while(x == 0 && strcmp(input, "0") != 0) {
std::cout << "Bad entry. Enter a NUMBER: ";
std::cin >> input;
x = std::atoi(input);
}
return x;
}
Notice that when you have 3 non-int chars, it will repeat 3 times, when you have 5, it's repeated 5 times.
It's because cin is tries the first char, fails, try the second char, fails and so on until all your input chars are parsed.

cin.fail() returns true if the last cin command failed, and false otherwise.
Try this instead:
while(1)
{
std::cin >> x;
if (!std::cin.fail()) break;
std::cin.clear();
std::cin.ignore(10000,'\n');
std::cout << "Bad entry. Enter a NUMBER: ";
}

Related

Undefined behaviour when entering `char` for integer variable with `std::cin`

I have this while loop, just to check if the entered number is 2. If the user entered by accident a letter instead of a number the loop goes to infinity even though I've added isdigit, but didn't fix the loop from going crazy if the input is a character. This is code:
int num1;
bool cond {false};
while(!cond){
cout<<"enter 2:";
cin>>num1;
if (!isdigit(num1)){
cout<<"not a digit:";
cin>>num1;
}
//
if(num1 == 2)
cond = true;
}
I would suggest trying something a little more straightforward instead of your current code:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num1;
cout << "Please enter the number 2:";
cin >> num1;
while (num1 != 2)
{
cin.clear(); //Clears the error flag on cin.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You did not enter the number 2, Please try again:";
cin >> num1;
}
return 0;
}
Now, cin.ignore(numeric_limits<streamsize>::max(), '\n'); is when it ignores up until '\n' or EOF \n is the delimiter meaning that, that is the character at which cin will stop ignoring.
Furthermore, numeric_limits<streamsize>::max() is basically saying there is no limit to the number of characters to ignore.
You need to use the header file #include<limits> to use this.
I recommend separating the reading of input data from converting it to a number. A good method for this is to use stringstream. Here's a working example:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int num1;
string input;
bool cond{ false };
cout << "enter 2:";
while (!cond) {
getline(cin, input);
stringstream ss(input);
ss >> num1;
if( ss.fail() ){
cout << "not a digit:";
continue;
}
//
if (num1 == 2)
cond = true;
else
cout << "enter 2:";
}
return 0;
}
int num1;
bool cond {false};
do{
cout<<"enter 2:";
cin>>num1;
if (cin.good()) {
cond = true;
}else {
cin.clear();
cin.ignore();
cout << "Invalid, please enter 2." << endl;
}
}while(!cond);
While false, execute statements. Also, if you want the user to re-enter a number, cin must be flushed.
Try declaring the variable num1 as char because isdigit(ch) works for char and not for int.
I hope this solves your problem
Why does the loop iterate infinitely?
Let's take this example
int a;
std::cin >> a;
std::cout << "Entered: " << a;
Now let's test it with different inputs
with int
5
Entered: 5
10
Entered: 10
Yes just as we would expect, but what happens when you enter a char?
with char
r
Entered: 0
f
Entered: 0
Why does this happen?
When you declare the variable int, and then do std::cin >> , you are telling the input method that the user will enter an integer, but when it doesn't get what it expected, it will fail. C++ will not implicitly convert the value of char into int. Hence, you get strange results.
How to solve this?
As I have mentioned earlier, it fails. When this fails you can catch it this way
if (!(std::cin >> a))
{
std::cout << "Invalid input ! \n";
}
We're saying, if the input fails, show the message.
let's test this new code.
int a;
if (!(std::cin >> a))
{
std::cout << "Invalid input !\n";
}
else
{
std::cout << "Entered: " << a;
}
5
Entered: 5
r
Invalid input !
How to print char value of the int?
If you want to just print the ASCII value of the entered number, you need to cast the value into char.
You can do
int num = 48;
char character_value = num;
Here C++ will implicitly convert char into int.
But if you need a safer type of conversion, prefer using static_cast<>.
The syntax looks like this
int a = 5;
char character_value = static_cast<char>(a);
Static cast in C++
Type casting in C++
Dealing with invalid input in C++

While loop skips line

I currently have this function:
double GrabNumber() {
double x;
cin >> x;
while (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You can only type numbers!\nEnter the number: ";
cin >> x;
}
return x;
}
Its purpose is to check if x is a valid number, returning it if it is valid or repeating cin >> x if it is not.
It's called during this function:
void addition() {
cout << "\nEnter the first number: ";
double a = GrabNumber();
cout << "Enter the second number: ";
double b = GrabNumber();
// rest of code
When I type for example "6+" when it tells me to enter the first number, it accepts it but immediately goes to the second line and calls it an error where I haven't even entered my input.
I assume this is because the first input only accepts "6" while "+" goes to the second input returning an error. Therefore, there must be an issue with the parameters of while.
If your input is immediately successful, you don't ignore the rest of the line, which ends up into the next input. This can be fixed by simply duplicating the cin.ignore call.
double GrabNumber() {
double x;
cin >> x;
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // <--
while (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "You can only type numbers!\nEnter the number: ";
cin >> x;
}
return x;
}
I'll leave DRYing this code as an exercise ;)
To avoid this kind of issue, prefer using getline and stod:
double GrabNumber() {
double x;
bool ok = false;
do
{
std::string raw;
std::getline (std::cin, raw);
try
{
x = stod(raw);
ok = true;
}
catch(...)
{}
} while(!ok);
return x;
}
In general case, it's easier to acquire raw string with getline and to parse it just after. In this way, you can check everything you want: number of characters, sign position, if there are only numerical character, etc.

Why do I get an infinite loop when I press a letter? How do I change for error checking?

Why do I get an infinite loop when I press a letter? How do I prevent my code from going into an infinite loop when error checking?
#include <iostream>
using namespace std;
int main()
{
int number;
cout << "Enter a number in the range 1-100: ";
cin >> number;
while (number > 1 || number < 100)
{
cout << "ERROR: Enter a value in the range 1-100: ";
cin >> number;
}
return 0;
}
Because std::cin is type safe, it knows that a letter is not a valid input for "int number". It raises an error flag in std::cin and any subsequent operation will fail and return immediately.
You'll need to check the error state and clear any error flag(s) before you can proceed.
See existing post Why do I get an infinite loop if I enter a letter rather than a number?
Thanks a lot y'all. I ended up going with this one.
while (!(cin >> number))
{
cout << "ERROR: Enter a value in the range 1-100: ";
//to clear input stream
cin.clear();
//to discard previous input
cin.ignore(1200, '\n');
cin >> number;
}

How do I make a C++ program that filter out non-integers?

Something like this
cout << "Enter the number of columns: " ;
cin >> input ;
while( input != int ){
cout << endl <<"Column size must be an integer"<< endl << endl;
cout << "Enter the number of columns: " ;
cin >> input ;
}
cin will do this for you, kind of. cin will fail if it receives something that is not of the same type as input. What you can do is this:
int input;
while(!(cin >> input))
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << endl <<"Column size must be an integer"<< endl << endl;
cout << "Enter the number of columns: " ;
}
The cin.clear() clears the error bits, and cin.ignore() clears the input stream. I'm using number_limits to get the maximum size of the stream, that requires that you #include<limits>. Alternatively you can just use a big number or a loop.
You can't do it like that; input has to have some concrete type.
The simplest approach that will work is to read a string from cin, then convert it to an integer in a second step with strtol or one of its relatives, and issue an error message if strtol doesn't consume the whole string.
#include<iostream.h>
using namespace std;
int main()
{
int x;
int input;
while(!0){
cout<<"Enter your option :";
cout<<"1 .Enter Column size :"<<endl;
cout<<"2.Exit "<<endl;
cin>>x;
switch(x)
{
case 1: cout << "Enter the number of columns: "<<endl ;
cin>>input;
if(input>0)
cout << "The number of columns: is "<<input<<endl ;
else
cout << "Enter the number of columns as integer "<<endl ;
case 2:exit(0);
}
};
return 0;
}
Many of the answers here use the cin's built in filter. While these work to prevent a char or string from being entered, they do not prevent a float entry. When a float is entered, it is accepted and the decimal value remains in the buffer. This creates problems with later requests to cin. The following code will check the cin error flag and also prevent float inputs.
*note: The cin.ignore statement may require some tweaking to fully bullet proof the code.
void main()
{
int myint;
cout<<"Enter an integer: ";
intInput(myint);
}
void intInput(int &x)
{
bool valid = true; //flag used to exit loop
do
{
cin>>x;
//This 'if' looks for either of the following conditions:
//cin.fail() returned 'true' because a char was entered.
//or
//cin.get()!='\n' indicating a float was entered.
if(cin.fail() || cin.get()!='\n')
{
cout<<"Error. The value you entered was not an integer."<<endl;
cout<<"Please enter an integer: ";
cin.clear(); //clears cin.fail flag
cin.ignore(256,'\n'); //clears cin buffer
valid = false; //sets flag to repeat loop
}
else valid = true; //sets flag to exit loop
}while(valid == false);
}
This is a very basic solution to your problem that newer programers should find useful for people trying to break their programs. Eventually there are more advanced and efficient ways to do this.
int input;
int count = 1;
while(count == 1){ //this is just a simple looping design
cin >> input;
if(cin.fail()){ //If the input is about to crash your precious program
cin.clear(); //Removes the error message from internal 'fail safe'
cin.ignore(std::numeric_limits<int>::max(), '\n'); //Removes the bad values creating the error in the first place
count = 1; //If there is an error then it refreshes the input function
}
else{
count--; //If there is no error, then your program can continue as normal
}
}
Here is the advanced code: stackoverflow.com/questions/2256527/

While loop with try catch fails at bad cin input

I can't seem to figure out why this falls into a loop after getting non-int input. I've tried cin.flush(), which doesn't seem to exist, cin.clear(), which seems like it should work, even cin.sync() after reading someone else post about it working, but didn't seem to make much sense. Also tried cin.bad().
Thank you very much for any help
Please enter the first number: f
Sorry, I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?
Please enter the first number: Sorry,
I don't think that's a number?Sorry,
you d on't get any more tries. Press
any key to continue . . .
#include <iostream>
using namespace std;
int main(){
int entry;
int attempts = 1;
int result;
while(attempts <= 5) {
try {
cout << "\n\nPlease enter the first number: ";
cin >> entry;
if (cin.fail())
throw "Sorry, I don't think that's a number?";
if (entry < 0)
throw "Sorry, no negative numbers. Try something else? ";
cout << "\nNow the second number: ";
cin >> entry;
cin.clear();
cin.get();
}
catch (char* error) {
cout << error;
attempts++;
}
}
if (attempts > 5)
cout << "Sorry, you don\'t get any more tries.\n";
system("pause");
return 0;
}
You should think carefully what you want to do if user gives invalid input in this case. Usually in these cases the best solution is to read one line from the input and throw it away.
Try putting cin.clear() and std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n'); in your catch clause. cin.clear() clears the failure state in cin, and cin.ignore() throws away rest of the line waiting in the input buffer.
(And yes, you probably should rethink your use of exceptions).
The most straight-forward (but not usually the easiest nor the fastest) way of dealing with validation of line-based input is to always read it line at a time. This way no extra whitespace (such as linefeed characters) is left unread in the buffer in any case, and discarding erroneous input is also quite automatic.
// Infinite loop for retrying until successful
while (true) {
// Ask the user something
std::cout << prompt;
// Read the answer (one full line)
std::string line;
if (!std::getline(std::cin, line))
throw std::runtime_error("End of input while expecting a value");
// Put the line read into iss for further parsing
std::istringstream iss(line);
int val;
// Read val from iss and verify that reading was successful and
// that all input was consumed
if (iss >> val && iss.get() == EOF) return val;
std::cout << "Invalid input, try again!\n";
}
It is fun to make a BASIC style input function out of this:
template <typename Val> void input(std::string const& prompt, Val& val) {
// (the above code goes here, slightly adjusted)
}
int main() {
int w;
double l;
input("Enter weight in kg: ", w);
input("Enter length in m: ", l);
std::cout << "BMI: " << w / (l * l) << std::endl;
}
Notes for the pedantics who were going to downvote me:
function input should be specialized for std::string
exceptions thrown by the input function should be caught in main
My Problem was to block char input to a cin >> number
This error caused an 'infinite' loop showing my prompt cout << prompt
with no way of exit but kill the process ...
The following shows what worked for me!
========================================
double fi_trap_d() // function to return a valid range double catching errors
{
double fi_game_sec;
//-------------------------------------------
do
{
fi_game_sec = -1;
cout << fi_game_sec_c;
//------------------------------
cin.ignore(); // (1)
//------------------------------
try
{ cin >> fi_game_sec; cin.clear(); } // (2)
catch (...) //out_of_range)
{
fi_game_sec = -1;
cout << " Dis am an error!\n";
// just loop back as we asked for a number
}
} while (fi_game_sec < 1);
//-------------------------------------------
return fi_game_sec;
}
========================================
Despite trying the " Dis am an error! " has NEVER shown up.
The key was (1) & (2) !
Exceptions should be used to handle exceptional, unexpected situations. Incorrect input from a user is neither unexpected nor exceptional -- it's more or less the norm. Personally, I tend to just ignore most bad input completely (when it can't be prevented). When (and only when) they enter something unusable repeatedly is it even worth pointing it out to them. As such, I'd tend to write the code something like:
char ch;
int attempts = 0;
std::cout << "Please enter the first number: ";
do {
cin >> ch;
attempts++;
if (attempts > 5)
std::cerr << "The only allowable inputs are '0' through '9'\n";
} while (cin.good() && !isdigit(ch));
int first_number = ch - '0';
This reads the input as a character, so it's always removed from the input stream. Then it attempts to validate the input, and if it fails, attempts to read again. Of course, you might want/need to get a little more elaborate, such as reading an entire line, attempting to convert it to a number, and reading another line if that fails.
Why are you doing this with exceptions? You're not going to kill the program on input, so you shouldn't throw an exception.
Just print out your error message and attempt to read in again.
It looks like you would be better off with iostream's native exceptions. Enable with
cin.exceptions( ios::failbit );
try {
…
} catch( ios_base::failure & ) {
cin.clear();
…
}
Never, ever throw an an object not derived from std::exception, and especially not a native type like char*.