While loop executes one too many times (I believe)

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
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;


int main ()
{
	double mCount=0, fCount=0, ccCount=0, unCount=0, score;
	string inputPathName, name, line, collegeType;
	double avgScore, mAverage, fAverage, ccAverage, unAverage, totalAverage;
	double fTotalScore = 0.0, mTotalScore = 0.0, ccTotalScore = 0.0, unTotalScore = 0, totalScore = 0.0;
	ifstream dataIn;
	char gender = '\0';
	
	cout << fixed << showpoint << setprecision(2);

	//Prompt user to input file name. Open file. If an invalid file re-prompt user.
	do {
		cout << "Please enter input path name: ";
		cin >> inputPathName;
		dataIn.open(inputPathName);
		if (!dataIn.is_open()) {
			cout << "File input failed" << endl;
		}
	} while (!dataIn.is_open());

	//Echo file
	while (dataIn.peek() != EOF) 
		{
		getline(dataIn, line);
		cout << line << endl;
		}
	cout << endl << "End of file reached." << endl;
	
	//Clear and rewind.
	dataIn.clear();
	dataIn.seekg(0);


	//Read the information and determine averages for: males, females, community college students, university students,
	//and the total average score for the survey.
	while (!dataIn.eof()) {

		dataIn >> name >> gender >> collegeType >> score;
	    
	
		if(gender =='M')
		{
			mCount++;
			mTotalScore = mTotalScore + score;
			
		}
		else
		{
		   fCount++;
		   fTotalScore = fTotalScore + score;
		  
		}
		if(collegeType == "CC")
		{
			ccCount++;
			ccTotalScore = ccTotalScore + score;
			
		}
		else 
		{
			unCount++;
			unTotalScore = unTotalScore + score;
			
		}
	mAverage = (mTotalScore / mCount);
	 fAverage = (fTotalScore / fCount);
	ccAverage = (ccTotalScore / ccCount);
	unAverage = (unTotalScore / unCount);
totalAverage =  (fTotalScore + mTotalScore)/(mCount + fCount);
		
		
	}
	
	//cout<<"# of Men = "<<mCount<<endl;
	//cout<<"Men total = " << mTotalScore<<endl;
	cout<<"Men average = "<< mAverage<<endl;
	//cout<<"# of Female = "<<fCount<<endl;
	cout<<"Female total = " << fTotalScore<<endl;
	cout<<"Female average = "<< fAverage<<endl;
	cout<<fCount<<endl;

	//cout << "# of CC students = " <<ccCount << endl;
	//cout << "# of UN students = " <<unCount << endl;
	cout<<"CC average = "<< ccAverage<<endl;
	cout<<"UNtotal = " << unTotalScore<<endl;
	cout<<"UN average = "<< unAverage<<endl;
	cout<<unCount<<endl;
	cout<<"Total average = "<< totalAverage<<endl;

	char reply;
	cout << "press q and enter to quit: ";
	cin >> reply;

	dataIn.close();
	system("pause");
	return 0;
}




I have to calculate averages for males, females, university students, community college students, and a total average for all students involved:

Sample input file:
Bailey M CC 68
Harrison F CC 71
Grant M UN 75
Peterson F UN 69
Hsu M UN 79
Bowles M CC 75
Anderson F UN 64
Nguyen F CC 68
Sharp F CC 75
Jones M UN 75
McMillan F UN 80
Gabriel F UN 62

For some reason, the else portion of the if else statements seem to execute one extra time, causing my totals to be approximately one score higher, and for my count to increment one extra integer. This throws off the average in the case of both female students and university students, as well as the total (which i personally have calculated by adding together the numbers [both count and total] for females and for males, this could alternatively be achieved through adding together the figures for community college students with those for university students). Why it does this I do not know. I do know that the output is correct for males and for community college students. Any insight would be greatly appreciated. Thank you.
Last edited on
When you are checking for EOF, it isn't set yet. Once you have read the last row in the file, the EOF is still not set. Not until the next read is the EOF set. To fix you can do
1
2
3
4
5
6
7
8
9
10
// Solution 1
// This is like what you did above
while (dataIn.peek() != EOF) {
   dataIn >> name >> gender >> collegeType >> score;
   // etc...

// Solution 2
while (dataIn >> name >> gender >> collegeType >> score) { 
   // etc...
I dont think you even need the != EOF in line 3 there, peek() fails, thus breaking the loop.
closed account (4z0M4iN6)
I remember something about peek() and I remember there was something like a bug about it. But I can't remember which one and why. I also had implemented something similar.

Maybe it was something like peek was not reset, when rewinding the stream pointer.

Maybe you should avoid to use peek()?
Last edited on
I think Peek() is the issue here, It is not reset. If you reset it then rewind you should be okay.
I dont think you even need the != EOF in line 3 there, peek() fails, thus breaking the loop.


If peek() 'fails' it returns EOF, so you most assuredly do need it in that particular case.

The OP did not use peek(). peek() is not the issue.

1
2
3
// Solution 2
while (dataIn >> name >> gender >> collegeType >> score) { 
   // etc... 


is the more robust solution.
Topic archived. No new replies allowed.