How to check for eof() without getline?

I'm currently trying to write a while loop that checks if the text file has read all the contents inside. I've tried using
 
while(!in.eof())

but as usual it executes my loop an extra iteration, printing my last output twice. I am reading my data in from a method inside a class, so I cannot use getline as my while test to check if the file has read input or not. Is there any way to force my loop to check if the end of file has been read before the eof() test is executed?
1
2
3
4
5
6
7
8
int i ;
double d ;

// while(!in.eof())
while( in >> i >> d ) 
{
    // ...
}
Don't believe that would solve my problem either as I'm reading my data using a read function inside of my class Rational. Here pieces of my code related to my issue.

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
Rational op1, op2, res; // objects of class Rational
char oper;
//.
//.
//.
while(!in.eof())  // <---- Problem is this, causing my last output to print twice
{
	op1.read(in); // read in first rational
	in >> oper; // read in the operation to be performed
	op2.read(in); // read in second rational
	switch(oper) // checks which operation to call depending on oper
	{
		case '+' : res = op1.add(op2);
		break;
		case '-' : res = op1.subtract(op2);
		break;
		case '*' : res = op1.multiply(op2);
		break;
		case '/' : res = op1.divide(op2);
		break;
		default: out << "No operator was found." << endl;
	}
	res.gcd(); // find greatest common divisor of result rational
	op1.print(out); // print first rational number 
	out << " " << oper << " "; // print operator used
	op2.print(out); // print second rational number
	out << " = ";
	res.print(out); // print resulting rational number
	out << endl;
}
//.
//.
//.
void Rational::read(ifstream& in)
{
	char d;
	in >> d >> num >> d >> denom >> d;
	if( denom == 0 ) // if rational denom read in is 0 print error and set to 0 / 1
	{
		cout << "Error ( " << num << " / " << denom << " ) not a legal value."
			 << " Rational changed to ( 0 / 1 )." << endl;
		num = 0;
		denom = 1;
	}	   
}
Last edited on
Why not turn that read() into an overload of operator>>() for Rational?
For this assignment I'm not allowed to use overloaded operators. My next assignment will be changing various parts of this program to use overloaded operators though.
Last edited on
I guess you could modify your Rational::read function slightly so that it returns true or false depending on whether the input succeeded.
Then it would just be a matter of doing
6
7
8
while (op1.read(in) && in >> oper && op2.read(in))
{
    // ... 

Alternatively, without changing Rational::read at all, you could try any one of these:
6
7
8
9
10
11
12
13
while (true)
{
    op1.read(in);
    in >> oper;
    op2.read(in);
    if (in.eof()) // Might be better to make it just 'if (!in)', but whatever...
        break;
    // ... 
6
7
8
while ( (op1.read(in), in) && in >> oper && (op2.read(in), in) )
{
    // ... 

EDIT: whoops, extra semicolon, good catch @Valandu
Last edited on
Okay I tried using your
 
while( (op1.read(in), in) && in >> oper && (op2.read(in), in) )

and it worked out, I had to remove the semicolon after in >> oper cause of a compiler error. But I'm not sure how it works in terms of how the following work.
 
(op1.read(in),in)

or
 
(op2.read(in), in)

What does the comma operator after op1.read(in) do exactly? Does it check if there are contents in the file or if the file is still open? If you could explain this to me that would be awesome.
 
in >> oper

Makes sense to me because it checks if there is a character read into oper. Thank you for your help.
Last edited on
The comma there basically turns two expressions into one expression, and AFAIK it returns the second one. Its being used here to first execute the read in and then returns the value of 'in' (true or false).
Wow, a good valid non-obscure usage of comma. A rare sight.
Very interesting, that is a really good use of the comma operator. Thank you @long double main for the exposure and @NT3 for the explanation.
Topic archived. No new replies allowed.