学生信息组合排序

前言

NWAFU 2021阶段二 D


一、题目描述

题目描述

从二进制文件Student.dic中读取指定序号范围的学生信息并存储到结构体数组中,要求对这些学生信息按照成绩及出生日期排序后输出,其中成绩是降序,而出生日期是升序,且仅在成绩相同时才比较出生日期。学生的出生日期由其身份证的第6-13位(从第0位开始计位)确定。学生结构体定义如下:

typedef struct {
      char Sno[10];   /* 学号 */
      char Name[20];  /* 姓名 */
      char Id[18];    /* 身份证号 */
      float Score;    /* 成绩 */
      int Ranking;    /* 排名位次 */
} Student, *PStudent;

    排序函数原型规定为: void OrderStu(PStudent stu_array, int len); 
其中stu_array是指向要排序的学生结构体数组的指针,len是参与排序的学生人数。
    比较函数原型规定为:int Compare(const void *a, const void *b);
其中a和b分别是指向要参与比较的两个学生结构体变量的指针。比较的办法是,按学生成绩及其出生日期比较。如果两个学生成绩相等,再判断出生日期,此时若前者的出生日期小于后者,则函数返回负数,反之为正数。成绩不相等时,如果前者的成绩大于后者,则函数返回负数,反之返回正数。

程序主体已经完成,但其中包含几处错误,请在不改变程序主体的前提下修改源代码中的错误,并完成排序和比较函数的编写。
二进制文件Student.dic请使用wget从这里获取,含有错误的程序代码请从这里获取。提交时注意不提交main()函数结束前的内容

#include 
#include 
#include 

#define FileName "Student.dic"

typedef struct StuInfo
{
    char Sno[12];
    char Name[20];
    char Id[20];
    float Score;
    int Ranking;
} Student, *PStudent;

int Compare(const void *, const void *);
void OrderStu(PStudent stu_array, int len);
int ReadFile(PStudent a,int start, int end);
void Print(PStudent stu_array, int len);

int main()
{
    PStudent a;
    int len;
    int start, end;

    scanf("%d%d", &start, &end);
    len = end - start + 1;
    a=(PStudent)malloc(len * sizeof(Student));
    len = ReadFile(a, start, end);
    OrderStu(a,len);
    Print(a, len);
    free(a);
    return 0;
}

/* 以上代码中不包含错误,在提交时不要包含在内。 */

int ReadFile(PStudent a,int start, int end)
{
    FILE *fp;
    PStudent t;
    int i, len;

    fp=fopen(FileName, "w");
    while(i < start) {
        fread(&t, sizeof(Student), 1, fp);
        i++;
        }
    len = fread(&a, sizeof(Student), end - start + 1, fp);
    fclose(fp);
    return len;
}

void Print(PStudent a, int len)
{
    int i;

    /* 请不要修改输出格式相关的内容 */
    printf("   学号   |  姓名  |       身份证     | 成绩 |排名\n");
    printf("----------------------------------------------------\n");
    for(i=0;i < len;i++)
        printf("%10s|%-8s|%18s|%6.2f|%3d\n",a[i]->Sno, a[i]->Name, a[i]->Id, a[i]->Score, a[i]->Ranking);
    printf("----------------------------------------------------\n");
}
输入

两个正整数,表示从文件中要读取的学生信息的序号范围。

输出

按成绩和出生日期排序后的学生信息。

样例输入
3 5
样例输出
   学号   |  姓名  |       身份证     | 成绩 |排名
----------------------------------------------------
2021999013|李元华  |411302196603042095| 99.00|  3
2021999015|尤子越  |133000197402029470| 92.00| 35
2021999014|陈心洁  |511826200012061797| 91.00| 57
----------------------------------------------------
提示

使用qsort()函数可实现快速排序。

二、设计步骤

这个问题由纠错与排序函数的编写两部分组成。Print函数显然没有错误,因此第一部分主要考察ReadFile函数中文件操作相关语句。首先是变量的问题,结构体指针 t 没有指向有效的内存空间,而作为循环变量的 i 在进入while循环之前显然没有赋0。其次是函数的问题,题设条件是二进制文件,因此fopen()函数的mode应当为 "rb" ,fread()函数的第一个参数是文件指针,因而在调用时应当传入指针,而非指针的地址。(PS:ReadFile函数返回值的意义小于其对文件指针位移的作用,因为在file正确的情况下,len = start - end + 1,或许后期优化可以利用这一点进行检查)(PS里的内容不重要)

至于函数的编写,题目中明目张胆地提示:使用qsort()函数可实现快速排序。

那就用呗 熟悉qsort()的朋友都知道,我们之所以喜欢泡泡就是因为qsort()的第四个参数太过复杂,然而熟悉qsort()的朋友会发现:其中a和b分别是指向要参与比较的两个学生结构体变量的指针。比较的办法是,按学生成绩及其出生日期比较。如果两个学生成绩相等,再判断出生日期,此时若前者的出生日期小于后者,则函数返回负数,反之为正数。成绩不相等时,如果前者的成绩大于后者,则函数返回负数,反之返回正数。

这不妥妥的cmp函数么!那还等什么,直接按照题目的保姆式教程使用qsort(),然后将Compare函数作为cmp参数传入qsort()。

代码实现:

int ReadFile(PStudent a, int start, int end)
{
 
    FILE *fp;
    PStudent t = (PStudent)malloc(1*sizeof(Student));
    int i = 0, len;
 
    fp = fopen(FileName, "rb");
    while (i < start) {
 
        fread(t, sizeof(Student), 1, fp);
        i++;
    }
    len = fread(a, sizeof(Student), end - start + 1, fp);
    //    fread(a,sizeof(Student),len,fp);
    fclose(fp);
    return len;
}
 
void Print(PStudent a, int len)
{
 
    int i;
 
    /* 请不要修改输出格式相关的内容 */
    printf("   学号   | 姓名 |       身份证     | 成绩 |排名\n");
    printf("----------------------------------------------------\n");
    for (i = 0; i < len; i++)
      printf("%10s|%-8s|%18s|%6.2f|%3d\n", a[i].Sno, a[i].Name,
                a[i].Id, a[i].Score, a[i].Ranking);
    printf("----------------------------------------------------\n");
}
int Compare(const void * a, const void * b){
    int i;
    //强制类型转换
    PStudent x = (PStudent)a;
    PStudent y = (PStudent)b;
    if(x->Score == y->Score)            //成绩相等,比较日期
    {
        for(i = 6;i <= 13;i++)
        {
            if(x->Id[i] > y->Id[i])
            {
                return 1;
            }
            else if(x->Id[i] < y->Id[i])
            {
                return -1;
            }
            else
                return 0;
        }
    }
    else{                               //比较成绩
        if(x->Score > y->Score)
        {
            return -1;
        }
        else
        {
            return 1;
        }
    }
}

void OrderStu(PStudent stu_array, int len){
    qsort(stu_array,len,sizeof(stu_array[0]),Compare);
}

总结

NWAFU 2021阶段二 D

你可能感兴趣的:(2021阶段2,c语言,学习方法)