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:
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;
}
And
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 code itself
//calculator that sorts shows average, total and rank of the students
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);
}
CodePudding user response:
I don't really understand your whole code since some structs seem to miss like HWND
.
But according to your question/problem:
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.)
I think that you're looking for the qsort function of the stdlib, if you're allowed to use it. Otherwise you can implement any other sorting algorithm.
Anyhow, here's some half-pseudocode to give you an idea how to implement it:
int compare_students(const void* a, const void* b)
{
// I assume that the average value is gonna be stored as a float.
if (*(float*)a < *(float*)b)
return -1;
if (*(float*)a == *(float*)b)
return 0;
if (*(float*)a > *(float*)b)
return 1;
}
int main()
{
// get your array of students
float * student_average_total = malloc(<amount_student_average_total> * sizeof(float));
if (student_average_total == NULL)
// err handling
return 1;
// sort the students according to their average_total value (whatever that
// is)
qsort(student_average_total, <amount_student_average_total>, sizeof(float), compare_students);
// and print out the rankding with their average value
for (int rank=1; rank<<amount_student_average_total> 1; rank ) {
printf("Rank %d: Student-Average: %f\n", rank, student_average_total[rank - 1]);
}
free(student_average_total);
}
CodePudding user response:
Would you please try something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int number; // student number
char *name; // student name
int kor; // the score of kor
int math; // the score of math
int eng; // the score of eng
int tot; // sum of the scores
double avg; // average of the scores
int rnk; // rank
} STUDENT_SCORE;
/*
* compare structs with the value of "tot"
* as "tot" is an integer, the code can be simpler than comparing "avg"
*/
int
cmpscore(const void *a, const void *b)
{
STUDENT_SCORE *a1 = (STUDENT_SCORE *)a;
STUDENT_SCORE *b1 = (STUDENT_SCORE *)b;
return a1->tot - b1->tot;
}
int
main()
{
// the initialization below substitutes readScoreNameFromEdit() function
// just for the demonstration purpose
STUDENT_SCORE stdScore[] = {
{1, "Alice", 80, 95, 70, 0, 0, 0},
{2, "Bob", 95, 75, 91, 0, 0, 0},
{3, "Carol", 92, 73, 88, 0, 0, 0},
{4, "Dick", 90, 83, 92, 0, 0, 0}
};
int stdNum = sizeof stdScore / sizeof stdScore[0]; // number of students
int i;
// calculate total score and average for each student
for (i = 0; i < stdNum; i ) {
stdScore[i].tot = stdScore[i].kor stdScore[i].math stdScore[i].eng;
stdScore[i].avg = stdScore[i].tot / 3.;
}
// sort the array of struct "stdScore" by tot (equivalent to sorting by avg)
qsort(stdScore, stdNum, sizeof stdScore[0], cmpscore);
// see the sorted result
for (i = 0; i < stdNum; i ) {
stdScore[i].rnk = stdNum - i;
printf("%d %s %.2f\n", stdScore[i].rnk, stdScore[i].name, stdScore[i].avg);
}
}
Result of execution:
4 Alice 81.67
3 Carol 84.33
2 Bob 87.00
1 Dick 88.33
The code above does not correspond to your whole code but it will be
sufficient to demonstrate the usage of qsort()
function and to start with.