#include <iostream>
#include <fstream>
#include <stdexcept>
#include <vector>
usingnamespace 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.
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.
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:
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?
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>
usingnamespace 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";
}