Why the eof is never recognized?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <vector>

using namespace std;

struct Point
{
	double x, y;

	Point(double ix, double ypsilon)
		: x(ix), y(ypsilon) {}
	Point () {}
};

ostream& operator<< (ostream& os, const Point& p)
{
	os << '(' << p.x << ',' << p.y << ')';
	return os;
}

istream& operator>> (istream& is, Point& p)
{
	char a, b, c;
	is >> a >> p.x >> b >> p.y >> c;
	if ( a!='(' || b!=',' || c!=')' ) {
		is.clear(ios_base::failbit);
		return is;
	}
	return is;
}

int main()
{
	vector<Point> original_points(2);

	cout << "Insert 2 points (each is a pair of double numbers, form: (x,y)\n";
	for(unsigned u = 0; u<original_points.size(); u++) {
		cin >> original_points[u];
	}

	cout << "Your Points where:\n";
	for (unsigned u=0; u<original_points.size(); u++) {
		cout << original_points[u]<< endl;
	}

        // writes to a file
	string file_name = "mydata.txt";
	ofstream ostr(file_name.c_str());
	if(!ostr) throw runtime_error ("Error by opening file \"mydata.txt\"");
	for (unsigned u=0; u<original_points.size(); u++) {
		ostr << original_points[u];
	}
	ostr.close();

        // reads from file
	ifstream istr(file_name.c_str());
	if(!istr) throw runtime_error("Error by opening file \"mydata.txt\"");
	istr.exceptions(istr.exceptions() | ios_base::badbit);

	vector<Point> processed_points;
	Point p;
	while (istr >> p) {
		processed_points.push_back(p);
		cout << "ok ";
	}  // till eof

	if (istr.eof())  cout <<"eof-flag" <<endl;

	if (istr.fail()) {
		cout <<"fail-flag" <<endl;
		istr.clear(ios_base::failbit);
		istr.unget();
		char c;
		istr.get(c);
		cout << "Wrong character:" << int(c);
		throw runtime_error("Wrong file format!");
	}

	cout << "The readed points are:\n";
	for (unsigned u=0; u<processed_points.size(); u++) {
		cout << processed_points[u];
	}
	cout << endl;

}

If data is correct entered, the program should branch into line 69, a recognition of eof flag.
Instead, it always branch into line 71, the fail flag and i have no clue whats
wrong.
Did not read your code.

Be advised, eofbit is not set when you read the last element, instead is set after you tried and failed reading after the last element.
Even I have had some problems with fstream, especially eof(). I guess eof() works only after you try reading from a stream after a read operation has failed.

i.e. first read failure doesn't set eof() true but second read failure sets eof() true.

I once made a program which would read contents from a binary file and display it on a screen. I used eof() to detect end of file. This resulted in the last line being displayed twice. The above explanation is the only one I have come up with.
Even I have had some problems with fstream, especially eof(). I guess eof() works only after you try reading from a stream after a read operation has failed.

This makes no sense -at least the eofbit should be setten after an attempt to read something behind the stream end, but for some reason it isn't be set. Also, the setting of eofbit shouldn't affect the setting of the failbit. I looked at the table in http://www.cplusplus.com/reference/ios/ios/fail/
After successfully reading the second point from the file, your Point's operator>> is entered for the third time.

The first read operation done inside that operator>> (is >> a) fails because the file ended, there is nothing to put into a. This sets BOTH eofbit and failbit, as most input operations do in this case.

You're then looking at the values of a, b, and c, which are undefined since you never wrote anything into them, but whatever they are, they are unlikely to be exactly '(', ',' and ')', so your if branch is entered.

Then you CLEAR eofbit with this code is.clear(ios_base::failbit); (this clears eofbit and badbit, and sets failbit)

Then your main function tests eofbit, which is not set, then it tests the failbit, which is set.
Last edited on
I thank you so much, Cubbi, you made my day!
So its better if testing eofbit in Point's operator>>.
Last edited on
I would just return the stream, not checking any flags, like the standard operator>> does with complex numbers in C++.

Actually, you could just reuse it, since you're using the same formatting:

1
2
3
4
5
6
7
8
9
std::istream& operator>>(std::istream& is, Point& p)
{
    std::complex<double> c;
    if(is >> c) {
        p.x = c.real();
        p.y = c.imag();
    }
    return is;
}

Last edited on
Oh, what a hap! Thanks for this hint.
Now i tried the reading via your "complex" example.
Unfortunately, there is again a problem with the eofbit, i don't know whats now wrong:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <vector>
#include <complex>

using namespace std;

struct Point
{
	double x, y;
};

ostream& operator<< (ostream& os, const Point& p)
{
	complex<double> c(p.x,p.y);
	os << c;
	return os;
}

istream& operator>> (istream& is, Point& p)
{
	complex<double> c;
	if(is >> c) {
		p.x = c.real();
		p.y = c.imag();
	}
	return is;
}

int main()
{
	ifstream istr("mydata.txt");
	if(!istr) throw runtime_error("Error by opening file \"mydata.txt\"");
	istr.exceptions(istr.exceptions() | ios_base::badbit);

	vector<Point> processed_points;
	Point p;
	while (istr >> p) {
		processed_points.push_back(p);
		cout << "ok ";
	}  // till EOF

	if (istr.fail()) cout <<"fail-flag" <<endl;
	if (istr.eof())  cout <<"eof-flag"  <<endl;

	
	cout << "The readed points are:\n";
	for (unsigned u=0; u<processed_points.size(); u++)
		cout << processed_points[u];
}

Here will always set the failbit WITHOUT eofbit an there is no clear(...) in the code. Thanks for any hints.
On a sample input file I tried this with (holding the content "(1, 2) (3.14, -1)"), this program sets both flags as expected and prints
ok ok fail-flag
eof-flag
The readed points are:
(1,2)(3.14,-1)

What's in your file?
My file holds (1,2)(5,7) and the output is:
ok ok fail-flag
The readed points are:
(1,2)(5,7)


Also with your data i get no eof-flag :-/
Perhaps there is a bug in a library? I use the version 4.7 of gcc.
Last edited on
Tested with gcc 4.7.2 (linux and aix), clang 3.1 (linux), xlc 11.1 (aix), sun studio 12 (solaris), everyone sets both flags. What's your compiler/platform?
I have here gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2

So, i have checked that the code example here is truly the same as in my codefile, all is exactly the same.
Last edited on
Must be a bug in one of my librarys.
I could it only reproduce with complex numbers (all forms)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <complex>
#include <iostream>

using namespace std;

int main()
{
	complex <bool> c;

	// end with CTRL-D or CTRL-Z
	while (cin >>c) cout <<"new number: " <<c <<endl;

	if (cin.eof ()) cout <<"eofbit set ";
	if (cin.fail()) cout <<"failbit set";
}
huh? complex<bool> doesn't exist (it's unspecified behavior to use one).
Oh, i didn'd know this. My compiler hadn't given me a warning. I also had tested complex numbers of double, long double, int, unsigned and float.
Topic archived. No new replies allowed.