Sorting an array of structs

I'm writing a program that sorts an array of student records based on what option the user enters. It works fine for sorting names, but gives me a junky response when I try to sort by student number or gpa. Part of stu.out looks like:

Sorted by student number:

ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌTyme Justin -858993460-925596313

The rest of the output is normal (and sorted correctly).

I'm assuming it's not my read_array function, as the name works fine. Here's the call and definition of sort_on_number:

1
2
3
4
5
6
		case '2': sort_on_number(s,n);	// Sorts array numerically by student number
				  cout << "\nSorted by student number:\n\n";
				  write_array_of_struct(cout,s,n);	// Write sorted array to screen
				  fout << "\nSorted by student number:\n\n";
				  write_array_of_struct(fout,s,n);	// Write sorted array to output file
				  break;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void sort_on_number(student s[], int n)
{
	student temp;	// Local variable used to swap records

	for(int i=0; i<n; i++)
	{
		for(int i=0; i<n; i++)
		{
			// If s[i].student_number is greater than s[i+1].student_number, swap the records
			if(s[i].student_number > s[i+1].student_number)
			{
				temp = s[i];
				s[i] = s[i+1];
				s[i+1] = temp;
			}
		}
	}
}


Any idea as to what I'm doing wrong?
Last edited on
Entire 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
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
#include<iostream>	// Provides cout, etc.
#include<fstream>	// Provides open(), etc.
#include<cstring>	// Provides strcpy(), etc.
#include<cctype>	// Provides toupper()
using namespace std;

const int MAXNAMESIZE = 27;		// Allows for 26 characters in name and null character '\o'
const int MAXCLASSSIZE = 50;	// Maximum of 50 students in class
const char QUIT = 'Q';			// Allows user to quit program

struct student
{
	char name[MAXNAMESIZE];	// Name of student
	int student_number;		// Student number of student
	double gpa;				// Grade point average of student
};

void explain_program(ostream& os);
// Program is explained in output stream os

void decimal_format(ostream& os);
// Decimals are formatted nicely in output stream os

void read_array_of_struct(istream& is, student s[], int& n, int capacity);
// Postcondition: n records have been read into s[] from input stream, and n<=capacity. 

void write_array_of_struct(ostream& os, const student s[], int n);
// Precondition: s[] has n valid records
// Postcondition: The field values of these records are written to output stream os

void print_menu();
// Postcondition: The menu of options is printed to the screen

char get_choice();
// Postcondition: The users choice is returned

void sort_on_name(student s[], int n);
// Precondition: s[] has n valid records
// Postcondition: These records are sorted alphabetically

void sort_on_number(student s[], int n);
// Precondition: s[] has n valid records
// Postcondition: These records are sorted numerically by student number

void sort_on_gpa(student s[], int n);
// Precondition: s[] has n valid records
// Postcondition: These records are sorted numerically by GPA

double get_av(const student s[], int n);
// Precondition: s[] has n valid values
// Postcondition: The average GPA is returned

void write_av(ostream& os, double average);
// Precondition: gpa_av has a valid value
// Postcondition: gpa_av is written to output stream os

int main()
{
	student s[MAXCLASSSIZE];	// Creates array elements s[0], s[1], s[MAXCLASSSIZE-1] of type student

	int n;			// Number of records read
	char choice;	// Menu choice from user
	double gpa_av;	// Average GPA of all students

	ofstream fout;	// Internal name for output file
	ifstream fin;	// Internal name for input file

	explain_program(cout);	// Explains program to user on the screen

	// Open output file. If there is an error, exit the program
	fout.open("stu.out");
	if(fout.fail())
	{
		cout << "There was an error opening the output file.";
		exit(1);	// Exits the program
	}

	// Open input file. If there is an error, exit the program
	fin.open("stu.in");
	if(fin.fail())
	{
		cout << "There was an error opening the input file.";
		exit(1);	// Exits the program
	}

	// Format decimals on screen and in output file
	decimal_format(cout);
	decimal_format(fout);

	// Document output file
	fout << "Michael Sproul		SMSV010388";
	explain_program(fout);

	// Read from input file stu.in into the array s[]
	read_array_of_struct(fin,s,n,MAXCLASSSIZE);

	// Print menu to the screen
	print_menu();

	// Get user choice for menu
	choice = get_choice();

	// Process until QUIT is entered
	while(toupper(choice) != QUIT)
	{
		switch(toupper(choice))
		{
		case '0': print_menu();	// Prints menu to screen
				  break;

		case '1': sort_on_name(s,n);	// Sorts array alphabetically
				  cout << "\nSorted by name:\n\n";
				  write_array_of_struct(cout,s,n);	// Write sorted array to screen
				  fout << "\nSorted by name:\n\n";
				  write_array_of_struct(fout,s,n);	// Write sorted array to output file
				  break;

		case '2': sort_on_number(s,n);	// Sorts array numerically by student number
				  cout << "\nSorted by student number:\n\n";
				  write_array_of_struct(cout,s,n);	// Write sorted array to screen
				  fout << "\nSorted by student number:\n\n";
				  write_array_of_struct(fout,s,n);	// Write sorted array to output file
				  break;

		case '3': sort_on_gpa(s,n);	// Sorts array numerically by student number
				  cout << "\nSorted by GPA:\n\n";
				  write_array_of_struct(cout,s,n);	// Write sorted array to screen
				  fout << "\nSorted by GPA:\n\n";
				  write_array_of_struct(fout,s,n);	// Write sorted array to output file
				  break;

		case '4': gpa_av = get_av(s,n);		// Gets average of all GPA's
				  write_av(cout,gpa_av);	// Writes average of all GPA's to screen
				  write_av(fout,gpa_av);	// Writes average of all GPA's to output file
				  break;

		default:  // Inform user of invalid choice
				  cout << "\nSorry, " << choice << " is not a valid option";
				  cout << "\nPlease try again.\n";
		}

	// Get next choice from user
	choice = get_choice();

	}

	// Close output and input files
	fout.close();
	fin.close();

	return 0;
}


void explain_program(ostream& os)
{
	os << "\n\nThis program gives a menu of choices, allowing you to sort by name,"
	   << "student number, or grade point average, and allows you to see the "
	   << "average GPA.\n\n";
}

void decimal_format(ostream& os)
{
	os.setf(ios::fixed);
	os.setf(ios::showpoint);
	os.precision(2);
}

void read_array_of_struct(istream& is, student s[], int& n, int capacity)
{
	char temp[MAXNAMESIZE],		// Temporary storage for student name
		 ch;	// Local variable used to read eoln character

	n = 0;	// Initiliazes n to a value of 0, as no records have been read
	
	is.get(temp,MAXNAMESIZE);
	while((!is.eof()) && (n < MAXNAMESIZE))
	{
		strcpy_s(s[n].name,temp);	// Copy temp into s[n].name
		is >> s[n].student_number;	// Read student number
		is >> s[n].gpa;				// Read student GPA
		is.get(ch);		// Read eoln character

		n++;		// Add 1 to student count

		is.get(temp,MAXNAMESIZE);	// Read next name, if there is one
	}

	// Warn user if not all data was read from input file
	if(!is.eof())
	{
		cout << "Warning - not all data was read."
			 << "Last record read was " << s[capacity-1].name << endl;
	}
}

void write_array_of_struct(ostream& os, const student s[], int n)
{
	for(int i=0; i<n; i++)
	{
		os << s[i].name;			// Prints student name
		os.width(10);				// Right justify by width of 10
		os << s[i].student_number;	// Prints student number
		os.width(10);				// Right justify by width of 10
		os << s[i].gpa << endl;		// Prints GPA
	}
}

void print_menu()
{
	cout << "\n0 - See menu again"
		 << "\n1 - Sort by name"
		 << "\n2 - Sort by student number"
		 << "\n3 - Sort by GPA"
		 << "\n4 - Find average GPA"
		 << "\n" << QUIT << " - Quit this program\n\n";
}

char get_choice()
{
	char c;		// Local variable to store user choice

	// Get choice from user
	cout << "\nPlease enter a choice (0 to see menu):";
	cin >> c;

	return c;
}

void sort_on_name(student s[], int n)
{
	student temp;	// Local variable used to swap records

	for(int i=0; i<n; i++)
	{
		for(int i=0; i<n; i++)
		{
			// If s[i].name is later in alphabet than s[i+1].name, swap the two records
			if(strcmp(s[i].name,s[i+1].name) > 0)
			{
				temp = s[i];
				s[i] = s[i+1];
				s[i+1] = temp;
			}
		}
	}
}

void sort_on_number(student s[], int n)
{
	student temp;	// Local variable used to swap records

	for(int i=0; i<n; i++)
	{
		for(int i=0; i<n; i++)
		{
			// If s[i].student_number is greater than s[i+1].student_number, swap the records
			if(s[i].student_number > s[i+1].student_number)
			{
				temp = s[i];
				s[i] = s[i+1];
				s[i+1] = temp;
			}
		}
	}
}

void sort_on_gpa(student s[], int n)
{
	student temp;	// Local variable used to swap records

	for(int i=0; i<n; i++)
	{
		for(int i=0; i<n; i++)
		{
			// If s[i].gpa is greater than s[i+1].gpa, swap the records
			if(s[i].gpa > s[i+1].gpa)
			{
				temp = s[i];
				s[i] = s[i+1];
				s[i+1] = temp;
			}
		}
	}
}

double get_av(const student s[], int n)
{
	double av,			// Local variable used to store average
		   sum = 0;		// Sum of all GPA's

	// Return value of 0 if no data is found
	if(n == 0)
	{
		return 0;
	}

	for(int i=0; i<n; i++)
	{
		// Add GPA to sum of GPA's
		sum = sum + s[i].gpa;
	}

	// Calculate the average GPA
	av = sum / n;

	return av;
}

void write_av(ostream& os, double average)
{
	os << "The average GPA is " << average << endl << endl;
}
Topic archived. No new replies allowed.