is sequence necessary between cin.clear() and cin.ignore()? - c++

Let me show you my source at first.
#include <iostream>
#include <limits>
using namespace std;
int main() {
int n;
while (true) {
cout << "Type >> ";
cin >> n;
if (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Not a number" << endl;
continue;
}
if (n % 2)
cout << "odd";
else
cout << "even";
cout << endl;
}
return 0;
}
Well, This code can run without any problems. however, if I swap between cin.clear() and cin.ignore(), then type character(not integer), it stucks in infinite loop. (consult next code)
#include <iostream>
#include <limits>
using namespace std;
int main() {
int n;
while (true) {
cout << "Type >> ";
cin >> n;
if (cin.fail()) {
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.clear();
cout << "Not a number" << endl;
continue;
}
if (n % 2)
cout << "odd";
else
cout << "even";
cout << endl;
}
return 0;
}
I wonder sequence is neccesary between cin.clear() and cin.ignore().
if it is, I wanna know why it needs sequence.
Thx for read my Question. I will be very appreciated for any your replies.
sorry for inarticulate Writing.

Let's look at the second snippet step by step:
if (cin.fail()) {
If we enter this, the stream is already bad. So the input operation
cin.ignore(numeric_limits<streamsize>::max(), '\n');
fails immediately and does nothing. Thus, after
cin.clear();
the garbage input is still in the stream and makes
cin >> n;
fail again, without even waiting for input, which gets us back to the beginning.
If you swap the calls around (like in the first snippet), the clear will make the stream "good" again, then ignore successfully gets rid of the garbage input, and the cin >> n; will work as expected.

While cin.fail() is true, any attempts to read from the stream will - eh - fail.
Calling cin.clear() removes the failure flags from the stream, and thus enables input again.

Related

c++ why the second input is ignored?

I need to check whether digit was entered and if not, ask for correct input.
Second input is ignored for some reason.
(There should be "while" instead of "if" in the final version, but I replaced it to "if" for debug to avoid eternal loops)
#include <iostream>
int main()
{
int number = 0;
std::cout << "Please enter some digit:\n";
std::cin >> number;
if (!isdigit(number))
{
std::cout << "Wrong input, please enter digit\n";
std::cin >> number;
}
}
There is no point in using isdigit() on an int, it only makes sense to use it with a char, as it looks for characters between '0'..'9', not integers between 0..9.
If cin >> number fails to read in a valid integer, it will put the stream into a failure state, which blocks further input. You must clear() that state, and also ignore() the erroneous input, before you can read in further input.
Try something more like this:
#include <iostream>
#include <limits>
int main()
{
int number;
std::cout << "Please enter a single digit:\n";
do
{
if (std::cin >> number)
{
if (number >= 0 && number <= 9)
break;
std::cout << "Wrong input, please enter a single digit\n";
}
else
{
std::cout << "Wrong input, please enter a valid digit\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
while (true);
std::cout << "You entered: " << number << std::endl;
}

Which flag in cin turns to false when you enter a wrong type input [duplicate]

I want to check if the input is valid, but when i do run this code I see that it checks only input for charcters. If i input a float number it will take it and going to use like integer without fractional part.
#inclide <iostream>
using namespace std;
...
int n;
cout << "Your input is: "<<endl;
cin >> n;
while (cin.fail()) {
cout << "Error. Number of elements must be integer. Try again: " << endl;
cin.clear();
cin.ignore(256, '\n');
cin >> n;
}
...
`
So, how to make this code see if the input is float?
You can try to convert the input string to a int using a std::istringstream. If it succeeds then check for eof() (after ignoring blank spaces) to see if the whole input was consumed while converting to int. If the whole input was consumed then it was a valid int.
Something a bit like this:
int input_int()
{
int i;
// get the input
for(std::string line; std::getline(std::cin, line);)
{
// try to convert the input to an int
// if at eof() all of the input was converted - must be an int
if(!line.empty() && (std::istringstream(line) >> i >> std::ws).eof())
break;
// try again
std::cout << "Not an integer please try again: " << std::flush;
}
return i;
}
int main()
{
std::cout << "Enter an integer: " << std::flush;
std::cout << "i: " << input_int() << '\n';
}
Building on Raindrop7's solution, here's the full code to do what you need:
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double m;
cout << "Your input is: "<<endl;
cin >> m;
while (cin.fail() || (m-floor(m)))
{
cout << "Error. Nubmer of elements has to be integer. Try again: " << endl;
cin.clear();
cin.ignore(256, '\n');
cin >> m;
}
int n = (int)m;
return 0;
}
Here's a sample output:
Your input is:
2.7
Error. Nubmer of elements has to be integer. Try again:
erer
Error. Nubmer of elements has to be integer. Try again:
2
The code below should be able to do what you are hoping to achieve:
#inclide <iostream>
using namespace std;
int n;
cout << "Your input is: "<<endl;
while (!(cin >> n) || cin.get() != '\n') {
cout << "Error. Number of elements must be integer. Try again: " << endl;
cin.clear();
cin.ignore(256, '\n');
}
The program asks the user to re-enter an integer if either of the following happens:
If the program is unable to extract an integer from the std::cin stream. (For example, when a character or string is entered by the user)
If, after an integer is extracted successfully, the next character in std::cin is not the new line '\n' character. (For example, when a number with a decimal point like 1.1 is entered, or when an integer followed by a character like 1a is entered.)

loop repeats without prompting the user again?

I have this snippets of code from my original long program, and as much as it looks simple, it doesn't work correctly! I am brand-new to c++ language, but I know in Java that would be the way to do it (Regardless of the syntax).
Simply put, this should ask the user for an input to answer the following multiplication (5*5), however, it should also check if the user entered a wrong input (not number), keep asking the user again and again... Somehow, it keeps running forever without taking a new input!!
I hope to get, not only an answer, but also a reason for such an error!
int main() {
int userAnswer;
bool isValidAnswer = true;
cout << 5 << " * " << 5 << " = ";
cin >> userAnswer;
cin.ignore();
do {
if (cin.fail()) { //user input is not an integer
cout << "Your answer is not valid! Please enter only a natural number: ";
cin >> userAnswer;
cin.ignore();
} else {
isValidAnswer = false;
}
} while (isValidAnswer);
return 0;
}
Well you need to clear the error state before accepting new input. Call cin.clear() then cin.ignore() before trying to read input again.
I would do something like.
cout << "Enter a number: ";
cin >> number;
while(cin.fail())
{
cin.clear();
cin.ignore(1000, '\n'); //some large number of character will stop at new line
cout << "Bad Number Try Again: ";
cin >> number;
}
First, cin.fail() is not going to adequately check if your answer is a natural number or not with the type set to int (could also be negative).
Second, your boolean isValidAnswer is really checking if it's is an invalid answer.
Third (and most importantly), as another answer suggests, you should put in cin.clear() to clear the failure state, and then followed by cin.ignore(), which will remove the failed string from cin.
Fourth, cin will only check if an int exists somewhere in the string. You'll need to perform your own string comparison to determine if the entire input is a int (see answer below, based on this answer).
Updated:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
bool isNum(string line)
{
char* p;
strtol(line.c_str(), &p, 10);
return *p == 0;
}
int main() {
int userAnswer;
string input;
bool isInvalidAnswer = true;
cout << 5 << " * " << 5 << " = ";
while (isInvalidAnswer) {
if (!(cin >> input) || !isNum(input)) {
cout << "Answer is not a number! Please try again:\n";
cin.clear();
cin.ignore();
}
else {
userAnswer = atoi(input.c_str());
if (userAnswer < 0) { //user input is not an integer
cout << "Answer is not a natural number! Please try again:\n";
} else {
isInvalidAnswer = false;
}
}
}
cout << "Question answered!\n";
return 0;
}

How to forbid the inclusion of non-numbers?

I have this program:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int i=0;
float reader, tot = 0;
while(i!=10)
{
cout << "Insert a number: " << endl;
cin >> reader;
if(cin)
{
tot += reader;
i++;
}
else
{
cout << "Error. Please retry." << endl;
cin.clear();
}
}
cout << "Media: " << tot/i << endl;
return 0;
}
In the IF() i want the user to insert ONLY FLOAT VALUES in "reader" variable.
I want that if the user inserts a number, the program continues... else the program should re-ask to the user to insert a correct value.
How to do this checking the INPUT? I tried with a TRY CATCH but it didn't work.
Thanks in advance!
"How to do this checking the INPUT?"
It's already ensured by
cin >> reader;
that only valid float values can be entered by the user. The way to check for validity is
if( cin >> reader ) {
tot += reader;
i++;
}
else {
cout << "Error. Please retry." << endl;
cin.clear();
std::string dummy;
cin >> dummy; // <<< Read invalid stuff up to next delimiter
}
Here's the fully working sample.
"I tried with a TRY CATCH but it didn't work."
To get exceptions from std::istream operations, set the std::istream::exceptions mask.
Just check the result of operator>>:
if (cin >> reader) {
// user gave you a float
tot += reader;
i++;
}
else {
cout << "Error. Please retry." << endl;
// clear the error flag on cin, and skip
// to the next newline.
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Your original program was fine except you need to skip over that bad input when you get an error. Simply clearing the error is not enough:
#include <iostream>
#include <string>
#include <limits> // include this!!!
using namespace std;
int main()
{
int i=0;
float reader, tot = 0.0f; // tot needs to be float
while(i!=10)
{
cout << "Insert a number: " << endl;
if( cin >> reader )
{
tot += reader;
i++;
}
else
{
cout << "Error. Please retry." << endl;
cin.clear();
// Then you ned to skip past the bad input so you
// don't keep tripping the same error
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
cout << "Media: " << tot/i << endl;
return 0;
}
The function cin.ignore() ignores as many input characters as possibly up until the end-of-line character '\n'. The std::numeric_limits<std::streamsize>::max() function tells us the maximum number possible characters that can be stored in an input buffer.
If it is confusing an alternate way to skip the bad input would be to simply read up to the next line into a std::string.
else
{
cout << "Error. Please retry." << endl;
cin.clear();
// Then you need to skip past the bad input so you
// don't keep tripping the same error
std::string skip;
std::getline(cin, skip); // read the bad input into a string
}

How Can I avoid char input for an int variable?

The program below shows a 'int' value being entered and being output at the same time. However, when I entered a character, it goes into an infinite loop displaying the previous 'int' value entered. How can I avoid a character being entered?
#include<iostream>
using namespace std;
int main(){
int n;
while(n!=0){
cin>>n;
cout<<n<<endl;
}
return 0;
}
Reason for Infinite loop:
cin goes into a failed state and that makes it ignore further calls to it, till the error flag and buffer are reset.
cin.clear();
cin.ignore(100, '\n'); //100 --> asks cin to discard 100 characters from the input stream.
Check if input is numeric:
In your code, even a non-int type gets cast to int anyway. There is no way to check if input is numeric, without taking input into a char array, and calling the isdigit() function on each digit.
The function isdigit() can be used to tell digits and alphabets apart. This function is present in the <cctype> header.
An is_int() function would look like this.
for(int i=0; char[i]!='\0';i++){
if(!isdigit(str[i]))
return false;
}
return true;
If you want use user define function you can use the ascii/ansi value to restrict the char input.
48 -57 is the range of the 0 to 9 values
#include <iostream>
#include <climits> // for INT_MAX limits
using namespace std;
int main()
{
int num;
cout << "Enter a number.\n";
cin >> num;
// input validation
while (cin.fail())
{
cin.clear(); // clear input buffer to restore cin to a usable state
cin.ignore(INT_MAX, '\n'); // ignore last input
cout << "You can only enter numbers.\n";
cout << "Enter a number.\n";
cin >> num;
}
}
You need to check for cin fail
And
You need clear the input stream
See the following example.
It is tested in recent compilers
#include <iostream>
using namespace std;
void ignoreLine()
{
cin.clear();
cin.ignore();
}
int main(int argc, char const* argv[])
{
int num;
cout << "please enter a integer" << endl;
cin >> num;
while (cin.fail()) {
ignoreLine();
cout << "please enter a integer" << endl;
cin >> num;
}
cout << "entered num is - " << num << endl;
return 0;
}