Sorting total and average score of the students and their ranks in ascending order

Hello!

The code below is horrible. I know that. But it's just my assignment and here is the help I seek:

The code itself should open a text file with 15 students' information on their names, scores for math and eng. It then counts total score (like 90 for math and 90 for eng out 100 is 180) and average, and it also shows what rank in the class are they (e.g first place is 198, the second is 195, etc.) I already did all of this and I have prepared text files of these 15 students.

Now, the problem I am facing is sorting their average total and rank in ascending order (each student has numbers 1-15 and now I need to completely ignore their assignment numbers and just focus on their rank order.)

Sorry for writing so boring. I need to clarify all things.
By the way, my professor actually gave a hint about what to do, but I've got no brains for coding, so I am humbly asking for help.
One last thing, the code below is not only a part of the big one (like opening file and pressing buttons, but the adding of hints should be in the part below)
Hint:


1
2
3
4
5
6
7
8
9
10
void cpyStudentScore(STUDENT_SCORE *d1, STUDENT_SCORE *d2){
	d1 ->number = d2->number;
	strcpy(d1->name,d2->name);
	d1->kor = d2->kor;
	d1->eng = d2->eng;
	d1->math = d2->math;
	d1->tot = d2->tot;
	d1->avg = d2->avg;
	d1->rnk = d2->rnk;
}

1
2
3
4
5
6
7
8
9
for(int i=0; i < stdNum-1; i++){
    	for(int j=0; j < stdNum-1-i; j++){
    		if(stdScore[j].tot < stdScore[j+1].tot){
    			cpyStudentScore(&tmp, &stdScore[j+1].tot);
    			cpyStudentScore(&stdScore[j], &stdScore[j+1]);
    			cpyStudentScore(&stdScore[j+1], &tmp);
			}
		}
	}



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
#include "MyInclude.h"

#define MAX_STUDENT_NUM 60

typedef struct{
	int number;
	TCHAR name[10];
	int kor;
	int math;
	int eng;
	int tot;
	float avg;
	int rnk;
	int *d1;
	int *d2;
}STUDENT_SCORE;

extern int readDataAsNum(HWND hSrc, int *data);
extern void writeNumToEdit(HWND hDst, int *data, int dataNum);

void writeScoreNameToEdit(HWND hDst, STUDENT_SCORE *stdScore, int stdNum);
BOOL readScoreNameFromEdit(HWND hSrc, STUDENT_SCORE *stdScore, int *rtnStdNum);

void scoreCalculator(HWND hwnd, HWND hSrc, HWND hDst){
	TCHAR buff[BUFF_SIZE];
	DWORD fileSize;
	char* tok;
	int MAX_COL_NUM = 5;
	int NUMPOS=0, KORPOS=1, MATHPOS=2, ENGPOS=3, TOTPOS=4;
	int stdScore[MAX_STUDENT_NUM][MAX_COL_NUM], stdNum;
	
	fileSize = GetWindowText(hSrc, buff, BUFF_SIZE);
	buff[fileSize+1] = NULL;
	stdNum = 0;
	tok = strtok(buff, "\r\n");
	while(tok != NULL){
		sscanf(tok,"%d %d %d %d\r\n",&stdScore[stdNum][NUMPOS],&stdScore[stdNum][KORPOS],
		                             &stdScore[stdNum][MATHPOS],&stdScore[stdNum][ENGPOS]);
		tok = strtok(NULL, "\r\n");
		stdNum++;
		
		if(stdNum >= MAX_PRIME_NUM){
			MessageBox(hwnd, "The number of students is out of the storage range.", "Arrangement grade processing.", MB_OK);
		    return;		
		}
	}
	
	for(int i=0; i<stdNum; i++){
		stdScore[i][TOTPOS] = stdScore[i][KORPOS]+stdScore[i][MATHPOS]+stdScore[i][ENGPOS];
	}
	 
	TCHAR str[MAX_DATA_NUM];
	sprintf(buff,"%-s\t%-s\t%-s\t%-s\t%-s\t\r\n","Number","Kor","Math","Eng", "Total");
	for(int i=0; i<stdNum; i++){
		sprintf(str,"%-d\t%-d\t%-d\t%-d\t%-d\t\r\n", stdScore[i][NUMPOS],stdScore[i][KORPOS],
	                stdScore[i][MATHPOS],stdScore[i][ENGPOS],stdScore[i][TOTPOS]);
	    strcat(buff,str);
	}
	
	strcat(buff,"\r\n");
	SetWindowText(hDst, buff);
	
}


void scoreCalculatorWithName(HWND hwnd, HWND hSrc, HWND hDst){
	int stdNum;
	STUDENT_SCORE stdScore[MAX_STUDENT_NUM];
	
	if(readScoreNameFromEdit(hSrc, stdScore, &stdNum) == FALSE){
		MessageBox(hwnd, "The number of students is out of the storage range.", "Structure grade processing.", MB_OK);
		return;		
	};
	
	for(int i=0; i<stdNum; i++){
		stdScore[i].tot = stdScore[i].kor+stdScore[i].math+stdScore[i].eng;
		stdScore[i].avg = (float)stdScore[i].tot/3;		
    }
    
    for(int i=0; i<stdNum; i++){
    	stdScore[i].rnk = 1;
    	for(int j=0; j<stdNum; j++){
    		if(stdScore[i].tot < stdScore[j].tot)stdScore[i].rnk++;
		}
	}
    writeScoreNameToEdit(hDst, stdScore, stdNum);
}

BOOL readScoreNameFromEdit(HWND hSrc, STUDENT_SCORE *stdScore, int *rtnStdNum){
	TCHAR buff[BUFF_SIZE];
	DWORD fileSize;
	char *tok;
	int stdNum = 0;
	
	fileSize = GetWindowText(hSrc, buff, BUFF_SIZE);
	buff[fileSize+1] = NULL;
	tok = strtok(buff, "\r\n");
	while(tok != NULL){
		sscanf(tok,"%d %s %d %d %d\r\n", &stdScore[stdNum].number,&stdScore[stdNum].name,
		                              &stdScore[stdNum].kor,&stdScore[stdNum].math,&stdScore[stdNum].eng);
		tok = strtok(NULL, "\r\n");
		stdNum++;
		if(stdNum >= MAX_STUDENT_NUM){
			return FALSE;
		}
	}
	*rtnStdNum = stdNum;
	return TRUE;
}

void writeScoreNameToEdit(HWND hDst, STUDENT_SCORE *stdScore, int stdNum){

	TCHAR buff[BUFF_SIZE];
	TCHAR str[MAX_DATA_NUM];
	
	sprintf(buff,"%-s\t%-s\t%-s\t%-s\t%-s\t%-s\t%-s\t %-s \r\n",
	        "Number","name","Kor","Math","Eng","Total","Average","Rank");
	for(int i=0; i<stdNum; i++){
		sprintf(str,"%-d\t%-s\t%-d\t%-d\t%-d\t%-d\t%-.1f\t%-d\r\n",
		            stdScore[i].number, stdScore[i].name,
		            stdScore[i].kor, stdScore[i].math,stdScore[i].eng,
		            stdScore[i].tot, stdScore[i].avg,stdScore[i].rnk);
		strcat(buff,str);	
	}
	strcat	(buff,"\r\n");
	SetWindowText(hDst, buff);	
}
Last edited on
If you look on the right there is a Format: tool bar. It will help if you go back and edit your post, select your code and then place code tags around it by using the <> button.
Thank you! I just did that
@fiadrad
Excellent work with the code tags.

It might be a good idea to post some sample data - just enough to show us so we can conduct a test. Such a .txt file needs to be tagged with the 'Program Output' tag button alonside the <> button.

Also, if it's only the standard includes "MyInclude.h" isn't necessary but otherwise it needs to be posted.
Last edited on
Despite that and the fact that the code is C rather than C++ ... lets look at the "hint":
1
2
3
4
5
6
7
8
9
for(int i=0; i < stdNum-1; i++){
    	for(int j=0; j < stdNum-1-i; j++){
    		if(stdScore[j].tot < stdScore[j+1].tot){
    			cpyStudentScore(&tmp, &stdScore[j+1].tot);
    			cpyStudentScore(&stdScore[j], &stdScore[j+1]);
    			cpyStudentScore(&stdScore[j+1], &tmp);
		}
	}
}

The logical operation done by
1
2
3
cpyStudentScore(&tmp, &stdScore[j+1].tot);
cpyStudentScore(&stdScore[j], &stdScore[j+1]);
cpyStudentScore(&stdScore[j+1], &tmp);

is to swap values of two elements (stdScore[j] and stdScore[j+1])

When are they swapped? When condition stdScore[j].tot < stdScore[j+1].tot shows that they are not in correct order.

We can see that this condition compares the .tot.
We can see that order is incorrect, when tot of j is smaller than tot of j+1. In other words the desired order is descending by the .tot.

If you want ascending order, then you have to change the relation operator (or use NOT).
If you want to sort by other property than .tot, then you adjust the condition accordingly.

The stackoverflow answers show qsort(). C++ has std::sort(). Both take the condition as functor. Both will swap elements with copy/move assignments (although C++ can override swap for custom type).

1
2
3
4
5
STUDENT_SCORE x;
STUDENT_SCORE y;
// fill x and y with data

x = y; // is this copy assignment safe? If not, why? 
Topic archived. No new replies allowed.