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

Time:10-19

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.

  •  Tags:  
  • c
  • Related