Why is failbit set when I enter EOF? - c++

I'm currently learning how while (cin >> num) work and I found out that there are two steps.
First one is the operator>> function return a istream object with error state, and the second is bool converter that convert istream object into bool depend on its state.
But I find it confusing that in the bool convert function, it will return 0 only if failbit or badbit is set. And the operator>> function will set eofbit if it read EOF.
bool convert function: https://www.cplusplus.com/reference/ios/ios/operator_bool/
operator>> function: https://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
In this case, After I enter EOF the bool converter should return 1 because the failbit and badbit aren't set.
Therefore, I use the below program to check what actually happened to the error bit after I enter EOF. And I find out that the failbit will be set after entering EOF!!
So I'm wondering if anyone can help me understand why is failbit set?
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num;
cout << cin.eof() << " " << cin.fail() << " " << cin.bad() << endl;
return 0;
}
Input: ^Z(on windows using qt creator, non qt c++ project)
Output: 1 1 0
Input: ^D(on windows using qt creator, non qt c++ project)
Output: 0 1 0

eofbit is set when a read operation encounters EOF while reading data into the stream's buffer. The data hasn't been processed yet.
failbit is set when the requested data fails to be extracted from the buffer, such as when reading an integer with operator>>. While waiting for digits to arrive, EOF could occur. eofbit alone is not enough to enter an error state, as there may be usable data in the buffer.
So, for example, imagine a while (cin >> num) loop is used and the user enters 123<Ctrl-Z>.
on the 1st iteration, operator>> reads 1, 2, 3 into the buffer, then encounters Ctrl-Z, so it sets eofbit and stops reading. 123 is then extracted from the buffer into num and the operator exits. At this point, the stream is not yet in an error state. When the stream's bool conversion is evaluated by while, it returns true, allowing the while body to be entered so it can process num.
on the next iteration, operator>> sees eofbit is set, preventing further reading. There is nothing left in the buffer to extract into num, so the operator sets failbit and exits. The stream is now in an error state. When the stream's bool conversion is evaluated by while, it returns false, breaking the while loop.

If the EOF is the first input, the operator>> fails to read an integer, so the stream enters the fail() state.
If you type at least one digit before the Ctrl-Z, that digit is read and the input succeeds.

Related

Why is cin.failbit always set even when input is valid?

I was trying to write a program that asks to input a char array using cin.getline() and if given input is bigger than array length array gets extended.
I used cin.failbit to see if user's input was too long. But nothing went right. So after debugging I figured out that the problem lies in failbit.
So I wrote a simple program to see what was wrong about it and it turned out that somehow cin.failbit always returns true when in if-statement even when input seems valid.
int main () {
char name[256];
std::cout << "Enter your name: ";
std::cin.getline (name,256, '\n');
std::cout << "characters read: " << std::cin.gcount() << std::endl;
if (std::cin.failbit){
std::cin.clear();
std::cout << "failed\n";
}
}
For example, when input is "qwer" program outputs that 5 characters have been read (cin.gcount), so it should be fine but it also outputs "fail" meaning that failbit flag is set. But I believe it shouldn't be in this case.
program output here
So can anyone explain why failbit appears to be set permanently?
Any help will be highly appreciated
std::cin.failbit is a constant that indicates which of the error bits represents stream failure. It is not an indication of the stream's current state. To check if that bit is set, use the member function std::cin.fail() instead.
However, if the stream failed to read due to reaching the end of the stream fail() will return false leading you to believe that it succeeded. Prefer std::cin.good() to check if the last operation succeeded.

Clarification regarding use of flagbit to set internal error flag

In C++ primer I found this code:
if (cin.fail())
{ // bad input
cerr<< "bad data, try again"; // warn the user
cin.clear(istream::failbit); // reset the stream
continue; // get next input
}
I am confused that why the istream::failbit is used to set the error state flag, I mean that since the error has occurred (hence the flow is right now in if block then the failbit must be set, they why use it to set the error flag with that again. Where am I wrong in understanding this?
EDIT:
The book says "We print a warning and clear the failbit state", but IMO clear(istream::failbit) is setting the current state of stream with the value contained in failbit. So why the book is setting the stream's state with that of failbit as it will stop cin from functioning as it will be in error state. ++++ By state of a stream, what bit actually is being talked about, is it eofbit, badbit, goodbit, failbit or a combination of them? How can I know the value of these individual bit as well?
std::basic_ios::clear
void clear( std::ios_base::iostate state = std::ios_base::goodbit );
Sets the stream error state flags by assigning them the value of state. By default, assigns std::ios_base::goodbit which has the effect of clearing all error state flags.
If rdbuf() is a null pointer (i.e. there is no associated stream buffer), then state | badbit is assigned. May throw an exception.
Essentially in this case to set bit means that it sets bit to clear state.
If you call clear without parameters, it sets all bits to clear state, by setting "goodbit", which is exclusive with other states. If you mark only certain bit, only that bit will will be set, clearing other bits ( and good bit as well). Anyway, as said above, if during call of this method input buffer of stream is not valid, then clear() also sets badbit to true, so method good() and operator bool will return false and fail() will still return true.
To wit, why one need to clear those bits but keep a error state is depends on further code, often it is to be able to detect that error happened , but being able to request more data from stream (ask for correct input?)
#include <iostream>
#include <limits>
#include <string>
int main() {
using std::cout;
using std::cin;
int a;
do
{
cout << " Please enter an integer number:";
cin.clear();
cin >> a;
if(cin.fail())
{
cout << "Error occured while parsing input.\n";
cin.clear(std::istream::failbit);
}
// do something
if(cin.fail())
{
std::string str;
//now clear everything, to unlock the input.
cin.clear();
cin >> str;
cout << "Wrong input was: " << str << "\n";
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// setting fail bit again, so loop will go on
cin.clear(std::istream::failbit);
}
} while(cin.fail());
cout << "Thank you!";
}
Without calling ::clear(std::istream::failbit) and ::ignore the loop would be working forever, because state of the flags and buffer would force an attempt to parse same buffer content over and over. Actually, a that point you may try to reparse it , e.g. read the string and print it. It would be ok to call just clear() but then we need to create own flag that would allow us to react correctly.
The "state" of stream is a private field of type std::ios_base::iostate, which value is equal to a binary combination of it eofbit, badbit, and failbit constants. goodbit constant is equal to zero and represents no-error state. Two accessors that provide read and write operations to this field:
void setstate( iostate state );
iostate rdstate() const;
Note, setstate(state) got effect of clear(rdstate() | state), which means that if clear can set exact value of iostate, setstate can only set new bits to true, but can't clear bits that already set.
int main()
{
std::ostringstream stream;
if (stream.rdstate() == std::ios_base::goodbit) {
std::cout << "stream state is goodbit\n";
}
stream.setstate(std::ios_base::eofbit);
// check state is exactly eofbit (no failbit and no badbit)
if (stream.rdstate() == std::ios_base::eofbit) {
std::cout << "stream state is eofbit\n";
}
}
for each bit there are accessors: fail(), bad(), eof(), good().
Essentially, fail() returns true if (rdstate()|std::ios_base::failbit) != 0, and so on (See 30.5.5.4 basic_ios flags functions, ISO/IEC 14882:2017, Programming
Languages — C++)
operator bool is defined and returns good()
operator! is defined and returns !good()
The line
if (stream.rdstate() == std::ios_base::goodbit)
can be replaced by
if (stream)
because the latter results in contextual conversion to bool.
Effects, associated with iostate's bits (according to ISO C++):
badbit indicates a loss of integrity in an input or output sequence (such as an irrecoverable read error from a file);
eofbit indicates that an input operation reached the end of an input sequence;
failbit indicates that an input operation failed to read the expected characters, or that an output operation failed to generate
the desired characters.

Getting infinite loop when want to terminate it with a character like | in c++

So this is the code
#include<iostream>
using namespace std;
int main(){
int a,b;
while(true){
cout<<"Enter the value of a and b ";
cin>>a>>b;
if(a=='|'||b=='|')
break;
else
cout<<"The value of a is "<<a<<"\nThe value of b is "<<b<<endl;
}
}
and the question is Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the program when a terminating '|' is entered.
When i enter input like | it prints infinitely "The value of a is and value of b is ". What is the reason for this?enter code here
std::cin (and I think all streams) by default will set an error flag when you try to read into an invalid data type (e.g. here with trying to read a char into an int variable) and that flag will prevent other std::cin to run until the flag is cleared. To rest the stream, use std::cin.clear() to the reset the error flag and then you have to remove the bad input, either through std::cin.ignore() or read into a string buffer or something, from the stream as it will still be there.
Your istream operator >> as_int is failing and really doing nothing so your loop just keeps going. Either input as chars and convert to ints with checks, or or check the stream for errors.
cin>>a>>b;
if( cin.fail( ) )
break;
istream reading after failure
Additionally: If you had have traced into the istream operator you would have seen why it was not blocking, that it had failed. Always trace when something is wrong...

How is (cin) evaluated?

In Bjarne Stroustrup's Programming Principles and Practice Using C++ (Sixth Printing, November 2012), if (cin) and if (!cin) are introduced on p.148 and used in earnest on p.178. while (cin) is introduced on p.183 and used in earnest on p.201.
However, I feel I don't fully understand how these constructs work, so I'm exploring them.
If I compile and run this:
int main()
{
int i = 0 ;
while (cin) {
cout << "> ";
cin >> i ;
cout << i << '\n';
}
}
I get something like:
$ ./spike_001
> 42
42
> foo
0
$
Why is it that entering "foo" apparently causes i to be set to 0?
Why is it that entering "foo" causes cin to be set to false?
Alternatively, if I run and compile this:
int main()
{
int i = 0 ;
while (true) {
cout << "> ";
cin >> i ;
cout << i << '\n';
}
}
I get something like:
$ ./spike_001
> 42
42
> foo
> 0
> 0
...
The last part of user input here is foo. After that is entered, the line > 0 is printed to stdout repeatedly by the program, until it is stopped with Ctrl+C.
Again, why is it that entering "foo" apparently causes i to be set to 0?
Why is it that the user is not prompted for a new value for i on the next iteration of the while loop after foo was entered?
This is using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3.
I'm sorry for such a long question, but I think it all boils down to, "How is cin evaluated?"
Well, std::cin (or more precisely std::basic_ios) has an operator bool to implicitly convert the std::cin object to a bool when requested (for example in your if evaluation).
The semantic is as follows:
Checks whether the stream has no errors. Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().
Why is it that entering "foo" apparently causes i to be set to 0?
Again, why is it that entering "foo" apparently causes i to be set to 0?
Because operator>> on an int expects an integer in the string.
From cppreference:
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
Why is it that entering "foo" causes cin to be set to false?
Because the fail bit is set, therefore leading fail() to return true.
Why is it that the user is not prompted for a new value for i on the next iteration of the while loop after foo was entered?
That is because std::cin has the fail bit set, therefore it fails to get the input and just prints the old value of i which is 0.
When you use the >> operator on a stream, it attempts to extract a value of that type from the string. In other words, when you do cin >> i where i is an int, the stream attempts to pull an int from the stream. If this succeeds, i is set to the extracted value, and all is well. If it fails, the stream's badbit is set. This is important because treating a stream as a bool is equivalent to checking if it's badbit is set (if (cin) is like if (cin.good())).
So anyway... what's happening is that foo is setting the badbit since the extraction fails. Really, you should be checking if the extraction succeeds directly:
if (cin >> i) { /* success */ }
On a code quality note, I suspect you're using using namespace std;. Please be aware that this can be harmful.

C++ istream operator>> bad-data handling

Every time I ask a question here on SO, it turns out to be some very dumb mistake (check my history if you don't believe me), so bear with me if you can here.
It feels like my question should be very popular, but I couldn't find anything about it and I've run out of ideas to try.
Anyway, without further ado:
I'm trying to overload the input operator>>. It's supposed to read one integer at a time from a file, skipping invalid data such as chars, floats, etc.
Naturally, I'm checking if(in >> inNum) to both get() the next token and check for successful get().
If successful, not much to say there.
If it fails, however, I assume that one of two things happened:
It stumbled upon a non-integer
It reached the eof
Here's how I tried to deal with it:
istream& operator>> (istream& in, SortSetArray& setB) {
bool eof = false;
int inNum = -1;
while(!eof) {
if(in >> inNum) {
cout << "DEBUG SUCCESS: inNum = " << inNum << endl;
setB.insert(inNum);
}
else {
// check eof, using peek()
// 1. clear all flags since peek() returns eof regardless of what
// flag is raised, even if it's not `eof`
in.clear();
cout << "DEBUG FAIL: inNum = " << inNum << endl;
// 2. then check eof with peek()
eof = (in.peek() == std::char_traits<char>::eof());
}
}
return in;
}
The file contains [1 2 3 4 a 5 6 7], and the program naturally goes into infinite loop.
Okay, easy guess, peek() doesn't consume the char 'a', and maybe in >> inNum also failed to consume it somehow. No biggie, I'll just try something that does.
And that's pretty much where I've been for the last 2 hours. I tried istream::ignore(), istream::get(), ios::rdstate to check eof, double and string instead of char in the file, just in case char is read numerically.
Nothing works and I'm desperate.
Weirdly enough, the approach above worked for a previous program where I had to read a triplet of data entries on a line of the format: string int int
The only difference is I used an ifstream object for that one, and an istream object for this one.
Bonus Question: inNum has the value of 0 when the hiccup occurs. I'm guessing it's something that istream::operator>> does?
Implementation description
try to read an int
if successful;
insert the read value to setB
next iteration
else;
clear error flags
check so that we haven't reached the end of the file
still more data? next iteration.
The above is the logic description of your function, but there's something missing...
In case we try to read a value, but fail, std::istream's handle these cases by setting the approriate error flags, but it will not discard any data.
The problem with your implementation is that upon trying to read invalid data, you will just try to read the same invalid data again.. over, and over, and over, inf.
Solution
After clearing the error flags you can use std::istream::ignore to discard any data from the stream.
The function's 1st argument is the max number of potential chars to ignore, and the 2nd is the "if you hit this char, don't ignore any more*.
Let's ignore the maximum amount of characters, or until we hit ' ' (space):
#include <limits> // std::numeric_limits
in.ignore (std::numeric_limits<std::streamsize>::max(), ' ');