Differences between eof and fail - c++

I know, there was hundreds questions about fail and eof, but no one was able to answered my question.
In this example, only eof bit will be set:
while (!Ifstream.eof()){
Ifstream >> Buffer;
cout << Buffer << endl;
}
But in this example, eof bit as well as fail bit will be set:
while (!Ifstream.fail()){
Ifstream >> Buffer;
cout << Buffer << endl;
}
What is the reason of this two differences? .I consider only situation, when stream reach end of file.

The difference is very slight.
The first piece of code, tries reading as long as it doesn't hit EOF condition. Then it breaks. But, if for some reason an error occurrs (i.e. failure to convert data through << operator), this piece of code will loop indefinitely, since FAIL will be set on error, reading will stop, and EOF will never be hit.
The second piece of code works with a small trick. It reads as long as it can and stops when error occurs. Ok, logical. However, when hittin an end-of-file, but IIRC the EOF condition will not be set yet. So, the loop will run once more, try to read at EOF state, and that will rise the FAIL flag and break the loop. But that also means that you will get one processing ( cout<
The right way to do is to check immediatelly whether READING succeeded:
while (true){
if(!(Ifstream >> Buffer))
break;
cout << Buffer << endl;
}
only that will guarantee you that the loop will stop as soon as read fails, be it EOF or FAIL or other cause.
As MatsPetersson and πάντα ῥεῖ have suggested, the above snippet may be "squashed" to form:
while (Ifstream >> Buffer)
cout << Buffer << endl;
and that's the usual way to write it. No fail/good/eof checks needed. The value returned from operator>> is the stream itself (like in operator<<) and stream is testable for "truthness", so it's just as simple as that. When talking about fail/good/eof differences, I like to write the longer form to emphasize that .. you shouldn't use fail/good/eof in the while-condition at all, and that you should check the state of the stream only after actually trying to read from it. while(true) shows the point very clearly.

fail is different from eof in that it covers various other error conditions than "file reached its end".
For example, if Buffer is int Buffer then the second will stop on reading ABC, where the first one will loop forever (not making any progress, as ABC is not numeric input).
Of course, the CORRECT thing to do is:
while(Ifstream >> Buffer)
{
cout << Buffer << endl;
}
that will stop both on EOF and invalid input (if applicable), as well as not performing the cout << Buffer << endl; when the fail or eof condition happens.
[Note that the while(!eof()) solution is valid in for example Pascal, because in Pascal, the input is "pre-read", so that the current read knows if "the next read will result in EOF" before you actually TRY to read it. C and C++ doesn't mark EOF until you actually READ past the end of the file.

Programically,
'EOF in read' and 'fail of read' is described differently.
EOF indicates End Of File.
So, programmer knows when they have to stop reading file.
But 'fail' is indicates 'not successfully'
It means some process ends with wrong state or exception has been occurred when execute the process.

Related

C++ Why diff EOF checks recommended for text vs numeric?

My textbook recommends using the member accessor method iStreamVar.eof() when dealing with textual data and while (iStreamVar) when dealing with numeric data.
Can someone please explain why it would matter?
Quote from book:
Using the function eof to determine the end-of-file status works best if the input is text. The earlier method of determining the end-of-file status works best if the input consists of numeric data.
That is the only thing mentioned on the topic. After this, it just explains how the process works.
Which method you use for determining the end of data depends on how you use it. My guess is, both methods which your textbook mentions are used wrong, so they fail in different situations. That's why it recommends using different methods in different situations.
The correct method is not trivial, and it depends on how important error resilience is for you.
If you want to read a space-delimited stream with numbers in it, and you are sure the file contains no errors, the code is simplest:
int value;
while (iStreamVar >> value)
{
...
}
Note that it's not any of the two original options.
If your file contains space-delimited textual data, and you are sure there are no errors, use the same code (but declare the temporary variable as string instead of int).
If you want to detect and recover from errors, use more elaborate code. But I cannot recommend you any specific code structure - it depends on what exactly you want to do in case of errors. Also:
Are text records delimited by space or newline?
What if the input text-file contains an empty line?
Numbers - floating-point or not?
Numbers - if there is a stray character like a among number data, what to do?
So there is no single correct recipe for doing proper input with error resilience.
Unless there is something significant in the context that isn't shown in the question, that quote is nonsense.
The way to read from a file and check for success is to read from the file:
int data;
if (std::cin >> data)
std::cout << "read succeeded, value is " << data << '\n';
std::string data;
if (std::cin >> data)
std::cout << "read succeeded, value is " << data << '\n';
std::string data;
if (std::getline(std::cin, data)
std::cout << "read succeeded, value is " << data << '\n';
If an attempted read fails you can call .eof() to find out whether the failure was because the input was at the end of the file. Contrary to what some beginners expect (and what some languages do), if .eof() returns false it does not mean that there is data remaining in the input stream. The stream might be at the end of the file after a successful read consumed the remaining input. .eof() will return false, but the next attempted read will fail, and after that, .eof() will return true.
std::stringstream input("1234");
int data;
input >> data; // succeeds
std::cout << input.eof() << '\n'; // outputs 0, no failure
input >> data; // fails, no more input
std::cout << input.eof() << '\n'; // outputs 1, failed because at end of file

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.

Proper use of EOF (can it be used multiple times in a program?)

In my intro to programming course (c++), the instructor told us to:
"Write a program that inputs an unspecified number of integer ("int")
values and then outputs the minimum value and the maximum value that
were entered. At least one value will always be input. (read all input
until EOF). For extra credit make your program also work when the user
doesn't enter any ints at all (just the EOF.)"
I wanted to get fancy, so, in my solution, when just EOF is entered, the program responds with "Oops! You didn't enter anything. Please try again, this time entering at least one integer: " and prompts for input again.
My instructor is saying that this answer is wrong because
After the EOF, there should be no more input to a program (neither
expected by the user nor the program) — using the EOF to switch from
“one mode” of input to another mode of input isn’t supporting the
standards.
Every definition of EOF I've found on the internet doesn't seem to support my professor's definition. EOF, from what I can tell, is simply defined as the end of the current file. It seems perfectly valid to accept input from a user until EOF, do something with that input, and then ask for additional input until EOF again.
Because this is an online course, I was able to review everything we learned relating to EOF and we were only told that EOF meant "End of File" and could be 'used to signal an end to user input' (important, because, even if my professor was wrong, one could argue that I should have adopted his standards if he had specifically told us to. But he didn't tell us to).
What is the proper way to use EOF with user input? Is my professor's statement that "After the EOF, there should be no more input to a program" the standard
and expected way to use EOF? If a program accepts a variable amount of input, does something with it, and then accepts more variable input, is it not acceptable to use EOF with those inputs (aka don't use while(cin >> user_input) in that scenerio)? If so, is there a standard for what should be used to signal end of input in a scenario where you're accepting variable input multiple times?
My exact solution to the assignment is below. My solution to the main assignment "Write a program that inputs an unspecified number of integer ("int") values and then outputs the minimum value and the maximum value that were entered" was considered correct, by the second part of the assignment "make your program also work when the user doesn't enter any ints at all (just the EOF.)" was deemed incorrect ("make the program also work" is the only prompt we were given).
Thanks so much for any feedback!! Obviously, I'm skeptical of my professors feedback / decision, but, in general, I'm just trying to get a sense of C++ community standards.
#include <iostream>
#include <iomanip>
#include <string>
#include <stdlib.h>
using namespace std;
int main(){
string user_input;
int int_input, min_user_input, max_user_input;
bool do_it = true;
cout << "Hi John," << endl;
cout << "Please enter a few integers (signal EOF when finished): ";
while(do_it) {
cin.clear();
cin >> user_input;
if (user_input.empty()) {
cout << endl;
cout << "Oops! You didn't enter anything. Please try again, this time entering at least one integer: ";
}
else {
try {
int_input = atoi( user_input.c_str() );
min_user_input = int_input;
max_user_input = int_input;
while(cin >> int_input) {
if (min_user_input > int_input) {
min_user_input = int_input;
}
if (max_user_input < int_input) {
max_user_input = int_input;
}
}
cout << endl;
cout << "The max user input was: " << max_user_input << endl;
cout << "The min user input was: " << min_user_input << endl;
do_it = false;
}
catch (std::invalid_argument) {
cout << endl;
cout << "Oops! You didn't enter an integer. Please try again, this time only entering integers: ";
do_it = true;
}
}
}
return 0;
}
Note: additional feedback I got on this submission was: to not use c libraries (apparently stdlib.h is one) and that, on some computers (though, apparently, not mine), #include <stdexcept> will be needed to compile.
Answer
Short answer: my instructor is correct. When used with cin, no additional user input should follow an EOF signal. Apparently, in some cases the program won't let you enter more information, but, as #hvd points out
Although your system may let you continue reading from the same file
in the specific case that it is coming from a TTY, due to EOF being
faked there, you shouldn't generally rely on that.
Aka, because I'm using a terminal to enter user input, the program happens to work. In general, it won't work though.
As #RSahu answers, EOF just shouldn't be used to signal the end of variable length cin multiple times in a program. Importantly
There is no standard means, or commonly practiced coding standard, of
indicating when user input has ended for the time being. You'll have
to come up with your own mechanism. For example, if the user enters
"end", you can use it to deduce that the user has ended input for the
time being. However, you have to indicate to the user that that's what
they need to enter. Of course, you have to write code to deal with
such input.
Because this assignment required the use of EOF, what I was attempting to accomplish was, unintentionally, prohibited (aka receive input, check it, possibly receive more input).
Proper use of EOF (can it be used multiple times in a program?)
There is no single EOF. There is EOF associated with every input stream.
If you are reading from a file, you can reset the state of the std::ifstream when it reaches EOF to allow you to read the contents of the file again.
However, if you are reading data from std::cin, once EOF is reached, you can't read from std::cin any more.
In the context of your program, your professor is right. They are most likely talking about reading from std::cin.
EOF, from what I can tell, is simply defined as the end of the current file.
It is. Note that in particular, what it doesn't mean is the automatic start of a new file.
Although your system may let you continue reading from the same file in the specific case that it is coming from a TTY, due to EOF being faked there, you shouldn't generally rely on that. Try program </dev/null and see happens when you try to automate your program.

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(), ' ');

C++ file handling (structures)

Following code, when compiled and run with g++,
prints '1' twice, whereas I expect '1' to be printed
only once, since I am dumping a single structure to
the file, but while reading back it seems to be
reading two structures. Why?
#include <iostream.h>
#include <fstream.h>
int main(){
struct student
{
int rollNo;
};
struct student stud1;
stud1.rollNo = 1;
ofstream fout;
fout.open("stu1.dat");
fout.write((char*)&stud1,sizeof(stud1));
fout.close();
ifstream filin("stu1.dat");
struct student tmpStu;
while(!filin.eof())
{
filin.read((char*)&tmpStu,sizeof(tmpStu));
cout << tmpStu.rollNo << endl;
}
filin.close();
}
eof only gets set after a read fails, so the read runs twice, and the second time, it doesn't modify the buffer.
Try this:
while(filin.read((char*)&tmpStu,sizeof(tmpStu)))
{
cout << tmpStu.rollNo << endl;
}
Or
while(!filin.read((char*)&tmpStu,sizeof(tmpStu)).eof())
{
cout << tmpStu.rollNo << endl;
}
Read returns a reference to filin when called, which will evaluate to true if the stream is still good. When read fails to read any more data, the reference will evaluate to false, which will prevent it from entering the loop.
Your while loop is executing twice because the EOF condition is not true until the first attempt to read beyond the end of the file. So the cout is executed twice.
This prints 1 twice because of the exact way eof and read work. If you are at the very end of a file, read will fail, then calls to eof after that return true. If you have not attempted to read past the end of the file, eof will return false because the stream is not in the EOF state, even though there is no more data left to read.
To summarize, your calls look like this:
eof - false (at beginning of file)
read (at beginning of file)
eof - false (now at end of file, but EOF not set)
read (at end of file. fails and sets EOF state internally)
eof - true (EOF state set)
A better strategy would be to check eof right after the read call.
I believe it is because you are checking for filin.eof() and that won't be true until the second time you read.
See here. It notes that eofbit is set "...The end of the source of characters is reached before n characters have been read ...". In your case you won't hit EOF until the second read.
Cool.
Another way (courtesy of experts-exchange, I asked the same question there :-))
while(filin.peek() != EOF)
{
filin.read((char*)&tmpStu,sizeof(tmpStu));
cout << tmpStu.rollNo << endl;
}