I want the user to enter a positive double variable. If they enter anything else, I want the program to loop and continue to ask them to enter a number instead of getting an error and closing. I made an infinite loop with a conditional statement and a break. For some reason if they enter something other than a positive number it infinitely asks for the the radius. Can someone help me with this?
for(;;) {
cout << "Radius: ";
cin >> radius;
if(radius > 0){
break;
}
}
You can simply check the stream state of cin:
double radius;
for(;;) {
cout<<"Radius: ";
if(!(cin>>radius) || radius < 0.0) {
cout << "Invalid input, please enter a positive double value." << endl;
cin.clear();
std::string dummy;
cin >> dummy; // Read the left invalid input
}
else {
break;
}
}
You need to clear the stream's error flags, otherwise you keep looping, since no more other reads are performed when the stream is in a bad state, and radius keeps its value before the loop. You need to do the following (must #include <limits>):
if(!(cin >> radius)) // we didn't read a number, cin has a "bad" state
{
cin.clear(); // clear the error flags
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // ignore the rest
continue;
}
Related
I have a program which has the ability to reject user input if a char is entered instead of an int, and this works almost perfectly - anything entered that isn't a number is being rejected.
However, all of these cins need to accept any value between a minimum and a maximum, but I can't get it to work. The code below shows my efforts so far, but there's a slight bug. If a char is entered, followed by an int that is out of range, and another char is entered (I like to test rigorously - I mean, who knows what could happen if an actual end user came across the problem) the program throws the final value of mortgageTerm out as 0.
Could anyone tell me where I'm going wrong and give me any pointers to help me fix it? Thanks in advance to anyone who's able to help me solve my problem!
int mortgageTerm;
string line;
cout << "Mortgage term (1 - 40 years) : ";
while (!(cin >> mortgageTerm))
{
cout << "That's not a valid choice! Try again : ";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
while (getline(cin, line))
{
stringstream linestream;
if (!linestream >> mortgageTerm)
{
cout << "Input was not a number! Try again : ";
cin >> mortgageTerm;
continue;
}
if ((mortgageTerm <= 0 || mortgageTerm > 40))
{
cout << "Input out of range. Try again : ";
cin >> mortgageTerm;
continue;
}
char errorTest;
if (linestream >> errorTest)
{
cout << "Invalid input. Try again : ";
cin >> mortgageTerm;
continue;
}
break;
}
cout << mortgageTerm;
You're almost there. Your first issue is your first while loop is not needed at all. Then we just need to tweak the second loop to make sure that all the input read was used in the value you get. We can also simplify it by using a single error statement, Making those changes gives you
int mortgageTerm;
string line;
cout << "Mortgage term (1 - 40 years) : ";
while (getline(cin, line)) // consume all input given
{
stringstream linestream(line); // you have to construct the stream from the string here
linestream >> mortgageTerm; // try and read the data
if (!linestream.eof() || mortgageTerm <= 0 || mortgageTerm > 40)
{
// either there is input left in linestream or the value is not in range
cout << "Invalid input. Try again : ";
}
}
Just check for the minimum and maximum in the same condition where you check if it was able to be converted into an int, using ||, in a condition the expressions are checked left to right in order, so the first did its work already when you evaluate the second and mortageTerm will have the value.
Edited to address comments.
int mortgageTerm;
cout << "Mortgage term (1 - 40 years) : ";
while (!(cin >> mortgageTerm) ||
mortageTerm < 1 ||
mortgageTerm > 40 )
{
cout << "That's not a valid choice! Try again : ";
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
}
// If you are concerned about extra input after the number and want to clear the input stream
// cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
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;
}
bool correct = false;
while (!correct)
{
cout << "Please enter an angle value => ";
cin >> value; //request user to input a value
if(cin.fail())
{
cin.clear();
while(cin.get() != '\n');
correct = false;
}
else
cin.get();
cin.ignore();
correct = true;
}
Here's my problem according to the code above:
After I input a value, the program will pause and I have to press enter again to proceed to next part of the program; how can I avoid it?
Besides, if I enter value like 'abcd', program will not loop to request user to input value again, why is it so?
Instead, it will still proceed and output a value of 0.
I'm still new to these kind of command, just playing and explore them, I appreciate your guides!
edit:
while (!correct)
{
cout << "Please enter an angle value => ";
cin >> value; //request user to input a value
if(cin.fail())
{
cin.clear();
while(cin.get() != '\n');
correct = false;
}
else
{
cin.get();
cin.ignore();
correct = true;
}
}
You set correct=true unconditionally on the very first iteration, and bail out of the loop. Looks like you meant to add a pair of braces around the three statements after else.
I'm trying to print an error message if the user does not enter anything into the input prompt, and if what they enter is zero or less.
void checkScoreInputed(int* qaltScores, int i){
while(true){
// cin.clear(); here?
if ((cin >> qaltScores[i]) && (qaltScores > 0)){
// also tried placing cin.clear() here.
break;} else // else is optional
cout << "Please supply a positive number for the score: ";
}
}
I've tried placing cin.ignore() and cin.clear() both before and after the if statement, but I am still getting an infinite loop of cout << "Please supply...." after the user enters a non-integer value, like a character. How can I fix this?
You forgot the [i] in
if ((cin >> qaltScores[i]) && (qaltScores[i] > 0))
^^^
Without it, you're checking the value of the pointer, not the number you've just read.
You also need to call cin.clear() and cin.ignore().
void checkScoreInputed(int* qaltScores, int i) {
while(true) {
if ((cin >> qaltScores[i]) && (qaltScores[i] > 0)){
break;
}
cout << "Please supply a positive number for the score: ";
cin.clear();
cin.ignore(10000,'\n');
}
}
See Why would we call cin.clear() and cin.ignore() after reading input?
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/