New to C++. Having issues correctly looping while handling errors. I am trying to check if user input is an integer, and is positive.
do{
cout << "Please enter an integer.";
cin >> n;
if (cin.good())
{
if (n < 0) {cout << "Negative.";}
else {cout << "Positive.";}
}
else
{
cout << "Not an integer.";
cin.clear();
cin.ignore();
}
}while (!cin.good() || n < 0);
cout << "\ndone.";
When a non-integer is entered, the loop breaks. I feel like I am misunderstanding the inherent usage of cin.clear() and cin.ignore() and the status of cin during this loop. If I remove the cin.ignore(), the loop becomes infinite. Why is this? What can I do to make this into an elegantly functioning loop? Thank you.
In your non-integer branch you are invoking further cin methods so cin.good() gets reset to true.
You could change your code to something like this:
while(1) { // <<< loop "forever"
cout << "Please enter an integer.";
cin >> n;
if (cin.good())
{
if (n < 0) {cout << "Negative.";}
else { cout << "Positive."; break; }
} // ^^^^^ break out of loop only if valid +ve integer
else
{
cout << "Not an integer.";
cin.clear();
cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
}
}
cout << "\ndone.";
or you can simplify it even further like this:
while (!(cin >> n) || n < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Bad input - try again: ";
cin.clear();
cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
}
cout << "\ndone.";
int n;
while (!(cin >> n)||n<0)//as long as the number entered is not an int or negative, keep checking
{
cout << "Wrong input. Please, try again: ";
cin.clear();//clear input buffer
}
//only gets executed when you've broken out of the while loop, so n must be an int
cout << "Positive.";
cout << "\ndone.";//finished!
Should do what you want.
Related
I currently have a function set up that asks the user for an int, obtains that int, and then checks to make sure that the input meets a certain specification. In this case, its expected that the input will be an integer between -10 and 100. As of now, if I input any string of letters E.G. "gfUIWYDUF", the function returns a 0. Why is this happening and how do I fix it?
int readUserInput() {
cout << "What is the answer?: " << endl;
int answer;
do {
cin >> answer;
if (!cin || answer < -10 || answer > 100) {
cout << "Invalid Input!" << endl;
cout << "What is the answer?: " << endl;
cin.clear();
cin.ignore();
}
} while(!cin || answer < -10 || answer > 100);
return answer;
}
If you play with the input values you will find that cin >> scans from left to right until it finds any non-numeric value. It then evaluates the numbers it did find.
For example, putting:
57gh5
Returns 57
If you enter only numeric characters, you have a score of 0.
If you cin >> string instead, then you will be able to parse/validate the string and convert a valid number into an int
The problem is that your validation loop for this type of input depends on the error state of std::cin. However, you clear that error state before the loop checks for it.
The simplest way to fix this is to move your reading from std::cin to after the clear() like this:
// Read first
cin >> answer;
do {
if (!cin || answer < -10 || answer > 100) {
cout << "Invalid Input!" << endl;
cout << "What is the answer?: " << endl;
cin.clear();
cin.ignore();
cin >> answer;
}
} while(!cin || answer < -10 || answer > 100);
Though, I think I prefer using a regular while loop instead myself:
cin >> answer;
while(!cin || answer < -10 || answer > 100) {
cout << "Invalid Input!" << endl;
cout << "What is the answer?: " << endl;
cin.clear();
cin.ignore();
cin >> answer;
}
This feels cleaner to me, but that's just me. Both loops will work.
0 is returned as the initial value of answer
You may use cin.fail() to check if the input is valid.
int readUserInput() {
cout << "What is the answer?: " << endl;
int answer;
do {
cin >> answer;
if (cin.fail() || !cin || answer < -10 || answer > 100) {
cout << "Invalid Input!" << endl;
cout << "What is the answer?: " << endl;
cin.clear();
cin.ignore();
}
} while(cin.fail() || !cin || answer < -10 || answer > 100);
return answer;
}
I'm trying to make a validation loop in C++ that checks the user's input until they enter a number between 0 and 100 and however my loop only checks the first condition. Any guidance is appreciated!
#include <iostream>
using namespace std;
int main()
{
const int max_num = 100;
const int min_num = 0;
int num;
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
do {
if (!(cin >> num))
{
cout << "ERROR:The value provided was not a number" << endl;
cin.clear();
cin.ignore(1024, '\n');
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
}
else if (num<min_num || num>max_num)
{
cout << "ERROR: value out of range" << endl;
cin.clear();
cin.ignore(1024, '\n');
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
}
} while (!(cin >> num) || (num<min_num || num>max_num));
return 0;
}
Add lots of logging to your code so that you know what it's doing. This will help you find the problem. For example, instead of:
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
Try:
cout << "Enter a number between 0 and 100" << endl;
cerr << "About to read into num outside the loop" << endl;
cin >> num;
cerr << "Read into num outside the loop, got: " << num << endl;
And so on, throughout your code. This should give you enough information to find the bug. Alternatively, use a debugger with a single step function to accomplish the same thing.
Check that in the part of while:
instead of
while (!(cin >> num) || (num<min_num || num>max_num));
this:
while (!cin || (num<min_num || num>max_num));
the same for the upper if
cin >> num means putting user input to the variable num . So you are trying to take user inputs 2 times in the loop. Maybe the check condition: (num == (int)num)will solve your problem. It will try to verify the number you have stored in num is really of the type int
I am trying to verify the user input, but I have tried two compilers and I either have one of two things happen. Either it will:
-Constantly loop the error message without asking for user input
OR
-Wait for user input, and if the input is incorrect, will constantly loop the error message.
Here is the code:
cout << "Input number of the equation you want to use (1,2,3): " ;
cin >> userInput;
cout << endl;
while (userInput <= 0 || userInput >= 4)
{
cout << "Please enter a correct input (1,2,3): " ;
cin >> userInput;
cout << endl;
}
if (userInput == 1)
{
userInput is declared as an integer. Is there an easier way to verify user input, or a while loop is necessary? I am still very new to coding.
While using int userInput seems straight forward, it fails when the user inputs non-numeric values. You can use a std::string instead and check, if it contains a numeric value
std::string userInput;
int value;
std::cout << "Input number of the equation you want to use (1,2,3): " ;
while (std::cin >> userInput) {
std::istringstream s(userInput);
s >> value;
if (value >= 1 && value <= 3)
break;
std::cout << "Please enter a correct input (1,2,3): " ;
}
std::istringstream is similar to other input streams. It provides input from an internal memory buffer, in this case the value provided by userInput.
I would add an additional check to make sure that if the user enters non-integral input, the stream is cleared before attempting the next read.
cout << "Input number of the equation you want to use (1,2,3): " ;
cin >> userInput;
cout << endl;
while (userInput <= 0 || userInput >= 4)
{
if ( !cin.good() )
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
cout << "Please enter a correct input (1,2,3): " ;
cin >> userInput;
cout << endl;
}
I would suggest using a do loop instead so you have less repeated lines
int userInput = 0;
do
{
cout << "Input number of the equation you want to use (1,2,3): " ;
cin >> userInput;
cout << endl;
if ( !cin.good() )
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
} while (userInput <= 0 || userInput >= 4);
You don't want to cin >> int, if you are to perform any error checking. If the user enters a non-integer, you'll end up in difficult-to-recover-from situations.
Rather, cin into a string, perform any error checking you want and convert the string to a integer:
long x;
string sx;
cin >> sx;
x = strtol(sx.c_str(), NULL, 10);
i am trying to get a grip on built-in cin functions like cin.good() cin.fail() cin.ignore() cin.clear() etc. but there seems to be a problem with the following code, it works just fine but the line i have commented doesn't show on the runtime prompt. could someone point me to the right direction? :/
using namespace std;
void main()
{
int x = 0;
char y = 0;
int ch = 0;
do
{
cout << "Press 1 for int" << endl;
cout << "Press 2 for char" << endl;
cout << "Press 3 for exit" << endl;
cout << "enter choice = ";
cin >> ch;
if (ch == 1)
{
do
{
cout << "Enter an integer only = ";
cin >> x;
if (!cin.good())
{
cout << "Please enter integer only" << endl;
cin.clear();
cin.ignore(INT_MAX, '\n');
}
} while (cin.good() && x != 1);
}
else
if (ch == 2)
{
do
{
cout << "enter char only = ";
cin >> y;
if (cin.fail())
{ //the line below doesn't show up!
cout << "Please enter char only" << endl;
cin.clear();
cin.ignore(INT_MAX, '\n');
}
} while (!cin.fail() && y != 'e');
}
} while (ch != 3);
cout << "End of Program" << endl;
system("PAUSE"); // exit(1);
_getch();
}
cin.good()
Returns 0 if the stream has encountered problems such as reading the end of file, non-existent file. and 1 otherwise.
cin.bad()
Returns non-zero value if the stream is totally unusable, e.g. the file cannot be opened (but not if the stream has merely hit the end of the file).
cin.fail()
returns true if the last cin command failed, and false otherwise.
An example
int main() {
int i, j = 0;
while (1) {
i++;
cin >> j;
if (cin.fail()) return 0;
cout << "Integer " << i << ": " << j << endl;
}
}
Now suppose you have a text file - input.txt and it's contents are:
1 2 3 4 5 sahil 6 7
When you will run above short program on that, it will result like:
Integer 1: 1
Integer 2: 2
Integer 3: 3
Integer 4: 4
Integer 5: 5
it will not continue after 5th value as it quits after reading the sixth word, because that is not an integer: cin.fail() holds true.
cin.clear() and cin.ignore()
int age;
for (;;) {
cout << "Please enter your age: ";
if (cin >> age) {
break;
} else {
cout << "Please enter a valid integer age" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
Refer this for use in file handling:
bad()
Returns true if a reading or writing operation fails. For example, in
the case that we try to write to a file that is not open for writing
or if the device where we try to write has no space left.
fail()
Returns true in the same cases as bad(), but also in the case that a
format error happens, like when an alphabetical character is extracted
when we are trying to read an integer number.
eof()
Returns true if a file open for reading has reached the end.
good()
It is the most generic state flag: it returns false in the same cases
in which calling any of the previous functions would return true. Note
that good and bad are not exact opposites (good checks more state
flags at once).
The member function clear() can be used to reset the state flags.
I'm trying to write a program which calculates prime numbers and I have issues with a do-while-loop I am using.
Code:
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
unsigned long int lower_limit;
unsigned long int upper_limit;
cout << "\n" << "Program calculates prime numbers in a given range between 2 and 4.294.967.295.";
cout << "\n" << "Input range in which prime numbers are to be calculated... ";
do
{
cout << "\n\n" << "Lower Limit:\t"; cin >> lower_limit;
cout << "\n" << "Upper Limit:\t"; cin >> upper_limit;
if(lower_limit >= upper_limit)
{
cout << "\nInvalid Input: Value of Upper Limit has to be bigger than value of Lower Limit.";
cout << "\nSelect new numbers.";
}
if(!(cin >> lower_limit) || !(cin >> upper_limit))
{
cout << "\nInvalid Input: Values of Lower Limit and Upper Limit have to be integers.";
cout << "\nSelect new numbers.";
}
}while(lower_limit >= upper_limit || !(cin >> lower_limit) || !(cin >> upper_limit));
return(0);
}
If I input values to trigger Lower Limit >= Upper Limit it triggers the first error properly, but doesn't repeat the do-while-loop afterwards and doesn't close the program (return(0)) either... So the program is not repeating the do-while-loop, neither is the program exiting it. I really have no clue what it is actually doing there.
If I input values to trigger !(cin >> lower_limit) || !(cin >> upper_limit) ("adfd" or the like) the whole program just goes mental and rapidly repeats the do-while-loop, even ignoring the cin >> lower_limit; and cin >> upper_limit; statements.
Does anybody have an idea that can help me out?
Cheers!
One point is that if you get invalid input, you need to clear the error state by:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Your loop should be changed to something like:
do
{
while ( !(cin >> lower_limit >> upper_limit) ) {
cout << "Invalid input, Please re-enter\n";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
if(lower_limit >= upper_limit)
{
cout << "\nInvalid Input: Value of Upper Limit has to be bigger than value of Lower Limit.";
cout << "\nSelect new numbers.";
}
} while(lower_limit >= upper_limit);