A problem with creating an output file.

Hi, so I've got a HW and am little stuck.
The gold is "Write a program that reads students’ names followed by their test scores from an input file. The program should output to a file, output.txt, each student’s name followed by their test score and the relevant grade."

Here's my code

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

using namespace std;

struct StudentType
{
	string studentFName;
	string studentLName;
	int testScore;
	char grade;
};
int loadData(StudentType students[], int nStudents);
void outputData(StudentType students[], int nStudents);
char letGrades(int grade);
void calGrades(StudentType students[], int nStudents);

int main()
{
	int studentCount = 0;
	StudentType students[20];
	calGrades(students, studentCount);
	studentCount = loadData(students, studentCount );
	if (studentCount >= 20)
	{
		cout << "Sorry, you can't put any more students." << endl;
		studentCount++;
	}	
	system("pause");
	return 0;
}

void calGrades(StudentType students[], const int nStudents)
{
	int i;
	for (i = 0; i < nStudents; i++)
	{
		students[i].grade = letGrades(students[i].testScore);
	}
}

char letGrades(int grade)
{
	char charGrades;
	if (grade >= 90)
	{
		charGrades = 'A';
	}
	else if (grade >= 80)
	{
		charGrades = 'B';
	}
	else if (grade >= 70)
	{
		charGrades = 'C';
	}
	else if (grade >= 60)
	{
		charGrades = 'D';
	}
	else
	{
		charGrades = 'F';
	}
	return charGrades;
}

int loadData(StudentType students[], int nStudents)
{
	int studentCount = 0;
	ifstream input;
	input.open("studentTest.txt");
	while (!input.eof())
	{
		input >> students[studentCount].studentFName;
		input >> students[studentCount].studentLName;
		input >> students[studentCount].testScore;
		studentCount++;
	}
	input.close();
	return studentCount;
}

void outputData(StudentType students[], int nStudents)
{
	ofstream output;
	output.open("studentTestScore.txt");
	for (int i = 0; i < nStudents; i++)
	{
		output << left << endl;
		output << setw(5) << "Name: " << students[i].studentLName << ", " << students[i].studentFName << endl;
		output << setw(5) << "Score: " << students[i].testScore << endl;
		output << setw(5) << "Grade: " << students[i].grade << endl << endl;
	}
	output.close();
}


Why it doesn't create an output file? help!
Last edited on
I don't think you ever called the outputData() function. So the code never runs hence the file is never created.

also I believe that you didnt use the parameter nStudents in loadData() I'd assume the variable is to have the size of the class so that you can loop inputingData the number of times there are students,and loadData() should be a void function that doesnt need to return number of students.
Last edited on
So I've changed loadData as a void function and called the outputData function.
but this time it doesn't output anything.

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

using namespace std;

struct StudentType
{
	string studentFName;
	string studentLName;
	int testScore;
	char grade;
};
void loadData(StudentType students[], int nStudents);
void outputData(StudentType students[], int nStudents);
char letGrades(int grade);
void calGrades(StudentType students[], int nStudents);

int main()
{
	ifstream input;
	ofstream output;
	int studentCount = 0;
	StudentType students[20];
	calGrades(students, studentCount);
	if (studentCount >= 20)
	{
		cout << "Sorry, you can't put any more students." << endl;
		studentCount++;
	}
	outputData(students, studentCount);
	system("pause");
	return 0;
}

void calGrades(StudentType students[], const int nStudents)
{
	int i;
	for (i = 0; i < nStudents; i++)
	{
		students[i].grade = letGrades(students[i].testScore);
	}
}

char letGrades(int grade)
{
	char charGrades;
	if (grade >= 90)
	{
		charGrades = 'A';
	}
	else if (grade >= 80)
	{
		charGrades = 'B';
	}
	else if (grade >= 70)
	{
		charGrades = 'C';
	}
	else if (grade >= 60)
	{
		charGrades = 'D';
	}
	else
	{
		charGrades = 'F';
	}
	return charGrades;
}

void loadData(StudentType students[], int nStudents)
{
	int studentCount = 0;
	ifstream input;
	input.open("studentTest.txt");
	while (!input.eof())
	{
		input >> students[studentCount].studentFName;
		input >> students[studentCount].studentLName;
		input >> students[studentCount].testScore;
		studentCount++;
	}
	input.close();
}

void outputData(StudentType students[], int nStudents)
{
	ofstream output;
	output.open("studentTestScore.txt");
	for (int i = 0; i < nStudents; i++)
	{
		output << left << endl;
		output << setw(5) << "Name: " << students[i].studentLName << ", " << students[i].studentFName << endl;
		output << setw(5) << "Score: " << students[i].testScore << endl;
		output << setw(5) << "Grade: " << students[i].grade << endl << endl;
	}
	output.close();
}
Last edited on
To be fair, it doesn't input anything either, because function loadData() is never called.
I'd start with calling that from main(), and then check how many students were read.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void loadData(StudentType students[], int & nStudents);

const int MAXSIZE = 20;

int main()
{
    int studentCount = 0;
    StudentType students[MAXSIZE];
    loadData(students, studentCount);
	
    cout << "Number of students: " << studentCount << '\n';

    return 0;
}

Note the & here int & nStudents, it means the parameter is passed by reference so its value may be modified inside the function.

Inside function loadData() there are a number of changes needed.
1. use the parameter nStudents instead of a separate variable
2. don't loop on eof(), it is unreliable and can lead to unexpected errors.
3. take care that MAXSIZE is not exceeded
4. check that the file access was successful before adding 1 to the count nStudents

For both 2 and 4 simply test the condition (input), for example if (input) or while (input)
see: http://www.cplusplus.com/reference/ios/ios/operator_bool/
Last edited on
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
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>

using namespace std;

struct StudentType
{
	string studentFName;
	string studentLName;
	int testScore;
	char grade;
};
const int MAXSIZE = 20;
void loadData(StudentType students[], int & nStudents);
void outputData(StudentType students[], int nStudents);
char letGrades(int grade);
void calGrades(StudentType students[], int nStudents);

int main()
{
	ifstream input;
	ofstream output;
	int studentCount = 0;
	StudentType students[MAXSIZE];
	loadData(students, studentCount);
	calGrades(students, studentCount);
	cout << "Number of students: " << studentCount << '\n';
	if (studentCount >= MAXSIZE)
	{
		cout << "Sorry, you can't put any more students." << endl;
	}
	outputData(students, studentCount);
	system("pause");
	return 0;
}

void calGrades(StudentType students[], const int nStudents)
{
	int i;
	for (i = 0; i < nStudents; i++)
	{
		students[i].grade = letGrades(students[i].testScore);
	}
}

char letGrades(int grade)
{
	char charGrades;
	if (grade >= 90)
	{
		charGrades = 'A';
	}
	else if (grade >= 80)
	{
		charGrades = 'B';
	}
	else if (grade >= 70)
	{
		charGrades = 'C';
	}
	else if (grade >= 60)
	{
		charGrades = 'D';
	}
	else
	{
		charGrades = 'F';
	}
	return charGrades;
}

void loadData(StudentType students[], int & nStudents)
{
	
	ifstream input;
	input.open("studentTest.txt");
	while (!input.eof())
	{
		input >> students[nStudents].studentFName;
		input >> students[nStudents].studentLName;
		input >> students[nStudents].testScore;
	}
	input.close();
}

void outputData(StudentType students[], int nStudents)
{
	ofstream output;
	output.open("studentTestScore.txt");
	for (int i = 0; i < nStudents; i++)
	{
		output << left << endl;
		output << setw(5) << "Name: " << students[i].studentLName << ", " << students[i].studentFName << endl;
		output << setw(5) << "Score: " << students[i].testScore << endl;
		output << setw(5) << "Grade: " << students[i].grade << endl << endl;
	}
	output.close();
}

Still outputs nothing..could u be more specific?
Last edited on
In: loadData

You only read into a single element.
You do not increase the element count to indicate any thing has been read (which is why the subsequent function calls depending on studentCount to be accurate do nothing.)
Looping on eof like you're doing is wrong.
Topic archived. No new replies allowed.