last pair in my input file printing twice.

I have made a program that overloads operators effecting rational numbers including input and output. it reduces to lowest form, moves negatives to the correct places, flags 0's in the denominator as "error" and returns whole numbers. everything seems to be working correctly except, for some reason it's printing my last pair twice. any help would be great. if you notice any other errors feel free to point them out. I'm still learning.


driver program
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
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;
#include "classRats.h"

int main()
{
	ofstream outf("program5.ot");
	outf << "Rational number class testing program" << endl;

	outf << "step 1a and 1b declare objects x and y with the constructors" << endl;
	ratNum x, y(2, 7);
	outf << "here is the data for x:: " << endl << x.getNum()
		<< "/" << x.getDen() << endl;
	outf << "here is the data for y:: " << endl << y.getNum()
		<< "/" << y.getDen() << endl;

	//step 1b and 1c use sets to change x, and printEM using new values
	outf << endl << endl << "step 1b and 1c use sets to change x, and printem using new values for object x" << endl;
	x.setNum(4);
	x.setDen(11);
	x.printEm(outf);
	outf << endl << endl;
	//step 1d test
	int numTest, denTest;

	//step 1d test addition
	outf << "step 1d test addition" << endl;
	numTest = (x.getNum() * y.getDen()) + (y.getNum() * x.getDen());
	denTest = x.getDen() * y.getDen();
	outf << x.getNum() << "/" << x.getDen() << " + " << y.getNum() << "/" << y.getDen() << " = "
		<< numTest << "/" << denTest << endl << endl;

	//step 1d test subtraction
	outf << "step 1d test subtraction" << endl;
	numTest = (x.getNum() * y.getDen()) - (y.getNum() * x.getDen());
	denTest = x.getDen() * y.getDen();
	outf << x.getNum() << "/" << x.getDen() << " - " << y.getNum() << "/" << y.getDen() << " = "
		<< numTest << "/" << denTest << endl << endl;

	//step 1d test Multiplication
	outf << "step 1d test multiplication" << endl;
	numTest = x.getNum() * y.getNum();
	denTest = x.getDen() * y.getDen();
	outf << x.getNum() << "/" << x.getDen() << " * " << y.getNum() << "/" << y.getDen() << " = "
		<< numTest << "/" << denTest << endl << endl;

	//step 1d test Division
	outf << "step 1d test division" << endl;
	numTest = x.getNum() * y.getDen();
	denTest = x.getDen() * y.getNum();
	outf << x.getNum() << "/" << x.getDen() << " / " << y.getNum() << "/" << y.getDen() << " = "
		<< numTest << "/" << denTest << endl << endl;

	
	//step 2 read in a list of rational number pairs and test the overloaded operator functions
	outf << "step 2 read in a list of rational number pairs and test the overloaded operator functions." << endl;
	ifstream inf("program5.dat");
	while (!inf.eof())
	{
		inf >> x >> y;
		outf << "Rational number a. = " << x << " and rational number b. = " << y << endl;
		outf << x << " + " << y << " = " << x + y << endl;
		outf << x << " - " << y << " = " << x - y << endl;
		outf << x << " * " << y << " = " << x * y << endl;
		outf << x << " / " << y << " = " << x / y << endl;
		outf << endl << endl;
	}
	
	system("pause");
	return 0;
}


header
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
#pragma once
//step 1 create class for rational numbers
class ratNum
{
private:
	int num, den;
public:
	ratNum();
	ratNum(int inNum, int inDen);
	int getNum();
	int getDen();
	void setNum(int inNum);
	void setDen(int inDen);
	void printEm(ofstream& outf);
	friend ratNum operator +(ratNum a, ratNum b);
	friend ratNum operator -(ratNum a, ratNum b);
	friend ratNum operator *(ratNum a, ratNum b);
	friend ratNum operator /(ratNum a, ratNum b);
	friend ostream& operator <<(ostream& ostr, ratNum c);
	friend istream& operator >>(istream& istr, ratNum &c);
	void reduceEm(int &num, int &den, ratNum &c);
	int getMin(int x, int y);
};
ratNum operator +(ratNum a, ratNum b);
ratNum operator -(ratNum a, ratNum b);
ratNum operator *(ratNum a, ratNum b);
ratNum operator /(ratNum a, ratNum b);
ostream& operator <<(ostream& ostr, ratNum c);
istream& operator >>(istream& istr, ratNum& c);



implementation file
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include<fstream>
#include<iomanip>
#include<string>
using namespace std;
#include"classRats.h"

ratNum::ratNum()
{
	//step 1a. create default constructors 0/1
	num = 0;
	den = 1;
}

ratNum::ratNum(int inNum, int inDen)
{
	//step 1a. create user supplied crusntructors using private members num and den
	num = inNum;
	den = inDen;
}

void ratNum::setNum(int inNum)
{
	//step 1b. set num
	num = inNum;
}

void ratNum::setDen(int inDen)
{
	//step 1b. set den
	den = inDen;
}

int ratNum::getNum()
{
	//step 1b. get num
	return num;
}

int ratNum::getDen()
{
	//step 1b. get den
	return den;
}

void ratNum::printEm(ofstream& outf)
{
	//step 1c. create printEm method
	outf << "step 1 C" << endl;
	outf << "Numerator = " << num << " Denminator = " << den << endl;
}

ratNum operator +(ratNum a, ratNum b)
{
	ratNum c;
	c.num = (a.num * b.den) + (b.num * a.den);
	c.den = a.den * b.den;
	c.reduceEm(c.num, c.den, c);
	return c;
}

ratNum operator -(ratNum a, ratNum b)
{
	ratNum c;
	c.num = (a.num * b.den) - (b.num * a.den);
	c.den = a.den * b.den;
	c.reduceEm(c.num, c.den, c);

	return c;
}

ratNum operator *(ratNum a, ratNum b)
{
	ratNum c;
	c.num = a.num * b.num;
	c.den = a.den * b.den;
	c.reduceEm(c.num, c.den, c);
	
	return c;
}

ratNum operator /(ratNum a, ratNum b)
{
	ratNum c;
	c.num = a.num * b.den;
	c.den = a.den * b.num;
	c.reduceEm(c.num, c.den, c);

	return c;
}

//step 1e. overloaded operators for input and output in format num/den
ostream& operator <<(ostream& ostr, ratNum c)
{
	
	if(c.den == 1)
	{
		ostr << c.num;
	}
	else
		if(c.den == 0)
		{
			ostr << "error can't divide by 0" << endl;
		}
		else
	{
		ostr << c.num << "/" << c.den;
	}
	return ostr;
}

istream& operator >>(istream& istr, ratNum &c)
{
	char ch;
	istr >> ch >> c.num >> ch >> c.den >> ch;
	return istr;
}

//step 1f. created reducem function to reduce fractions to lowest form, and properly place -'s
void ratNum::reduceEm(int &num, int &den, ratNum &c)
{
	int gcf = abs(c.num) * abs(c.den);
	for (gcf; gcf > 1; gcf--)
	{
		if ((abs(c.den) % gcf == 0) && (abs(c.num) % gcf == 0))
		{
			c.den /= gcf;
			c.num /= gcf;
		}
	}
	if (c.den < 0)
	{
		c.num *= -1;
		c.den *= -1;
	}
	if (c.num == 0)
	{
		c.den = 1;
	}
	

}



input
1
2
3
4
5
(3/4) (1/4)
(-5/3) (2/3)
(6/-4) (0/1)
(12/35) (3/25)
(1/5) (-2/10)



output
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
Rational number class testing program
step 1a and 1b declare objects x and y with the constructors
here is the data for x:: 
0/1
here is the data for y:: 
2/7


step 1b and 1c use sets to change x, and printem using new values for object x
step 1 C
Numerator = 4 Denminator = 11


step 1d test addition
4/11 + 2/7 = 50/77

step 1d test subtraction
4/11 - 2/7 = 6/77

step 1d test multiplication
4/11 * 2/7 = 8/77

step 1d test division
4/11 / 2/7 = 28/22

step 2 read in a list of rational number pairs and test the overloaded operator functions.
Rational number a. = 3/4 and rational number b. = 1/4
3/4 + 1/4 = 1
3/4 - 1/4 = 1/2
3/4 * 1/4 = 3/16
3/4 / 1/4 = 3


Rational number a. = -5/3 and rational number b. = 2/3
-5/3 + 2/3 = -1
-5/3 - 2/3 = -7/3
-5/3 * 2/3 = -10/9
-5/3 / 2/3 = -5/2


Rational number a. = 6/-4 and rational number b. = 0
6/-4 + 0 = -3/2
6/-4 - 0 = -3/2
6/-4 * 0 = 0
6/-4 / 0 = error can't divide by 0



Rational number a. = 12/35 and rational number b. = 3/25
12/35 + 3/25 = 81/175
12/35 - 3/25 = 39/175
12/35 * 3/25 = 36/875
12/35 / 3/25 = 20/7


Rational number a. = 1/5 and rational number b. = -2/10
1/5 + -2/10 = 0
1/5 - -2/10 = 2/5
1/5 * -2/10 = -1/25
1/5 / -2/10 = -1


Rational number a. = 1/5 and rational number b. = -2/10
1/5 + -2/10 = 0
1/5 - -2/10 = 2/5
1/5 * -2/10 = -1/25
1/5 / -2/10 = -1

 

Your problem is probably being caused by line 62 of the driver file. Using eof() is usually the wrong way to control a file read loop. You should be using the actual read of the file instead.

1
2
3
4
	while( inf >> x >> y)
	{
		... //inf >> x >> y;
		


The problem is that eof() is not set until after you try to read the file, which means that your current loop will run the loop with "bad" data for the last iteration because you read after you check. By using the read operation itself you check at the time of the read and stop processing at the first read error.


you the man! i'm not gonna tell my proff she's wrong but that totally makes sense. fixed it immedietly, thank you!!
Hello TheJast,
i'm not gonna tell my proff she's wrong
Why not?

She may not be wrong about telling you about the ".eof()" function, but is wrong ro at least lacking in not saying how to use it properly.

To use what you have you would need to do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
inf >> x >> y;

while (!inf.eof())
{
	outf << "Rational number a. = " << x << " and rational number b. = " << y << endl;
	outf << x << " + " << y << " = " << x + y << endl;
	outf << x << " - " << y << " = " << x - y << endl;
	outf << x << " * " << y << " = " << x * y << endl;
	outf << x << " / " << y << " = " << x / y << endl;
	outf << endl << endl;

	inf >> x >> y;
}

The first read will either read something or set the "eof" bit. Making the last line of the while loop your next read if the "eof" bit is set the condition will catch this at the proper time.

jlb's solution is the most common way to read a file of unknown length. This is actually checking the status of the "good" bit which can be changed by any of the other bits being set. You can think of this as being a more universal way of checking the status and not limiting this to one single bit check which may not always be the problem.

Hope that helps to explain this,

Andy
Last edited on
The first read will either read something or set the "eof" bit.

What happens if there is a read error? Hint: There is a difference between eof() and fail(). eof() is not the only fail flag (like you hinted at in the second paragraph), and your loop only responds to eof(), none of the other possible failures of the stream.


Topic archived. No new replies allowed.