What is wrong with my output file?

Trying to teach myself file I/O and I have two text files that are communicating with this program. The goal of the program is to take class rosters of 10 students with less than 10 quiz scores and average out the scores so that the deficit of scores makes up for 10. If a student has 7 scores that means they missed 3 exams and should be scored as 0. All scores will be averaged by 10. I know that the files are loading properly but my output file ends up getting through the first line and then repeating the last number for infinity. Can someone help me figure out what is going wrong, I have been looking at this problem for 7 hours.

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

void average(ifstream& fin, ofstream& fout);
void instructions(ofstream& fout);
void output(ifstream& fin, ofstream& fout);

void instructions(ofstream& fout)
{
	fout << "The results are: " << endl
		<< " Last Name, First Name, up to 10 quiz scores, last entry is the average" << endl;
	fout << endl << endl;
}

void average(ifstream& fin, ofstream& fout)
{
	char next;
	int quizScore;
	double ave;
	string first; 
	string last;
	while (!fin.eof())
	{
		int total = 0, count = 0;
		fin >> last;
		fout << setw(10) << last;
		fin >> first;
		fout << setw(10) << first << " ";
		do {
			fin >> quizScore;
			count++;
			fout << setw(5) << quizScore;
			total += quizScore;
			fin.get(next);
		} while (next != '/n' && (!fin.eof()));
		while (count < 10)
		{
			fout << setw(5) << 0;
			count++;
		}
		cout << "total:" << total << endl;
		ave = (double)total / 10;
		fout.setf(ios::fixed);
		fout.setf(ios::showpoint);
		fout.precision(2);
		cout << "Average:" << ave << endl;
		fout << setw(7) << ave << endl;
	}
}

void output(ifstream& fin, ofstream& fout)
{
	char next;
	int count = 0;
	fin.get(next);
	cout << next;
	do
	{
		do
		{
			fout << next;
			cout << next;
			fin.get(next);
		} while (next != '\n');
		fout << next;
		fin.get(next);
	} while (next != '\n');
	fout << next;
	string last; 
	string first;
	int listOfScores[10];
	double average;
	do
	{
		fin >> last;
		fout << setw(10) << last;
		fin >> first;
		fout << setw(10) << first;
		for (int i = 0; i < 10; i++)
		{
			fin >> listOfScores[i];
			fout << setw(5) << listOfScores[i];
		}
		fin >> average;
		fout.setf(ios::fixed);
		fout.setf(ios::showpoint);
		fout.precision(2);
		fout << setw(7) << average << endl;
	} while (!fin.eof());
}

int main()
{
	string inputFile;
	string outputFile;
	cout << "Enter input file: ";
	cin >> inputFile;
	cout << "Enter output file: ";
	cin >> outputFile;
	ifstream fin;
	ofstream fout;
	fin.open(inputFile.c_str());
	if (fin.fail())
	{
		cout << "File not Found";
		exit(1);
	}
	fout.open(outputFile.c_str());
	instructions(fout);
	average(fin, fout);
	fin.close();
	fout.close();
	fin.open(outputFile.c_str());
	fout.open(inputFile.c_str());
	output(fin, fout);
	fin.close();
	fout.close();
	system("pause");
	return 0;
}

 
how does the input file look like?
Hello bmakloski,

Based on the input file I made this is how I changed the code to work. Read the comments I made and notice what part I commented out.

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
void average(ifstream& fin, ofstream& fout)
{
        //  Initalize all variables.
	char next{ ' ' };
	int quizScore{ 0 };
	double ave{ 0.0 };
	string first{ "" };
	string last{ "" };

	while (fin >> last)  // <--- Eliminates the need for "eof" checking. When the read fails the while loop fails.
	{
		int count = 0;
		int total = 0;

		fout << setw(10) << last;
		fin >> first;
		fout << setw(10) << first << " ";
		std::cout << " " << first << " " << last << std::endl;

		//fin >> quizScore;
		
		//do {
		//	count++;
		//	fout << setw(5) << quizScore;
		//	total += quizScore;
		//} while (next != '/n' && (!fin.eof()));
		
		while (fin >> quizScore)  // <--- Changes to while loop to detect eof properly,
		{
			count++;
			fout << setw(5) << quizScore;
			total += quizScore;
		} 

		fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // Used to clear the \n from the input buffer.

		while (count < 10)
		{
			fout << setw(5) << 0;
			count++;
		}

		cout << "total:" << total << endl;
		ave = (double)total / 10;
		fout.setf(ios::fixed);
		fout.setf(ios::showpoint);
		fout.precision(2);
		cout << "Average:" << ave << endl;
		fout << setw(7) << ave << endl;
		fin.clear();  // <--- Added to clear the bad/fail bits. Not sure why the input failed yet.

	}
}


The do while loop checks for "fin.eof()". Not a good idea because "eof" does not work the way you think it does. A good example of this is in the "output" function where it prints the last line twice before it detects "eof" and moves on. In the do while loop the read fails and sets the "eof" bit, but process the the last information left in the variables before the while condition checks and finds "eof". The same problem is there in the "output" function.

Another alternative is to use while (std::getline(fin,line) where line is defined as a std::string. Inside the loop put line in a stringstream and extract the data from that. The stringstream can be cleared before the next use and the while loop will fail when it tries to read past "eof".

Before the "output" function is called the only change I made is in the file name for "fout". As you have it the input file name becomes the output file name and this will overwrite the input file making the program good for one use before having to rebuild the input file for another use. So, I changed the file name on line 118 to create a second output file.

BTW if your compiler is C++11 or better compliant you do not need the ".c_str()" a std::string will work.

I have not worked on the "output" function yet, but the "average" function should give you ideas on how to fix it.

Hope that helps,

Andy
Topic archived. No new replies allowed.