Su Xiaohong's C Language Programming (Third Edition) Series Experimental Questions: Student Performance Management System V5.0

github: https://github.com/Jackie0Feng/SAMS
#System requirements description

There are no more than 30 people in a class (the specific number is entered by keyboard) to participate in the final exam, and the exam subjects are no more than 6 (the specific number is entered by keyboard). Define the structure type, use the structure array as the function parameter programming to realize the following menu-driven student performance management system:
(1) Enter each student's student number, name and test scores of each subject;
(2) Calculate the total score of each course
(3) Calculate the total score and average score of each student (
4) Arrange the ranking table according to the total score of each student from high to low;
(5) According to the total score of each student from low to high (6) Arrange the grade table
according to the student number from small to large;
(7) Arrange the grade table according to the dictionary order of the name;
(8) Query the student ranking and the test scores of each subject according to the student number;
(9) Press Query the ranking of students by name and their test scores in various subjects;
(10) According to excellent (90-100), good (80-89), medium (70-79), pass (60-69), fail (0-59) 5 categories, count the number of people and the percentage of each category for each course;
(11) Output each student's student number, name, test scores of each subject, total score, average score, and the score of each course Total score and average score.
It is required to display the following menu after the program runs, and prompt the user to input options:
1.Input record
2.Caculate total and average score of every course
3.Caculate total and average score of every student
4.Sort in descending order by total score of every student
5.Sort in ascending order by total score of every student
6.Sort in ascending order by number
7.Sort in dictionary order by name
8.Search by number
9.serch by name
10.Statistic analysis
11.List record
0.Exit
Please enter your choice:
Perform corresponding operations according to the options entered by the user

Purpose of the experiment: Based on the student management system V4.0, by adding task requirements, getting familiar with structure types, using structure arrays as function parameters , modular programming, and realizing the application of structure types instead of ordinary array types to realize data management Superiority .
#top-level design
The biggest change in this upgrade is to form a student structure of various types of data that were originally scattered and separated, which greatly makes the formal parameters of the function more concise, the code is more readable, and it is not easy to operate in practice. It's not difficult, the refactoring process is considered a physical effort.

/*程序功能:   学生成绩管理
编码者:   JackieFeng
日期:  13/11/2021
版本号:5.0
备注:
某班有最多不超过30人(具体人数由键盘输入)参加期末考试,考试科目最多不超过6门(具体门数由键盘输入)。
定义结构体类型,用结构体数组作函数参数编程实现如下菜单驱动的学生成绩管理系统:
(1)录入每个学生的学号,姓名和各科考试成绩;
(2)计算每门课程的总分和平均分;
(3)计算每个学生的总分和平均分
(4)按每个学生的总分由高到低排出名次表;
(5)按每个学生的总分由低到高排出名次表;
(6)按学号由小到大排出成绩表;
(7)按姓名的字典顺序排出成绩表;
(8)按学号查询学生排名及其各科考试成绩;
(9)按姓名查询学生排名及其各科考试成绩;
(10)按优秀(90- 100)、良好(80- 89)、中等(70-79)、及格(60- 69)、不及格(0-59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比;
(11)输出每个学生的学号、姓名,各科考试成绩,总分,平均分,以及每门课程的总分和平均分。*/
#include <stdio.h>
#include "SAMS.h"
#include <string.h>
#include <stdlib.h>
//#pragma warning(disable : 4996)

int main()
{
    int order = -1;//用户指令
    
    /*int n;
    long num[STU_NUM];
    float score[STU_NUM];*/
    //初始数据
    int n = 5;//学生人数
    int m = 3;//课程数

    long num[STU_NUM] = { 10001,10002,10003,10004,10005 };
    char name[][MAX_LEN] = { "tom","jack","bill","amy","jackie" };
    float score[STU_NUM] = { 20.0,80.0,50.0,66.0,95.0 };
    float score2[STU_NUM][COURSE_NUM] = { {20.0,80.0,50.0},//2表示二维
                                                                        {66.0,95.0,77.0},
                                                                        {63.0,77.0,81.0},
                                                                        {86.0,43.0,72.0},
                                                                        {96.0,95.0,89.0} };
    /*这次改变了一个字段,将一维的课程升级为了二维数组,
    又新增了一个功能统计每个学生所有课程的平均分和总分,
    所以需要新增两个一维数组sum[],aver[]存储一下此信息.*/
    float sum[STU_NUM] = { 0 };
    float aver[STU_NUM] = { 0 };
    //AverSumofEveryStudent(score2, sum, aver, n, m);

    //初始化结构体数组数据
    STU students[STU_NUM];
    for (int i = 0; i < n; i++)
    {
        students[i].num = num[i];
        strcpy_s(students[i].name, MAX_LEN, name[i]);
        for (int j = 0; j < m; j++)
        {
            students[i].score[j] = score2[i][j];
        }
    }
    AverSumofEveryStudent(students, n, m);

    Mean();//显示菜单
    //使用系统
    while (1)
    {
        printf("Please enter your choice : \n");
        scanf_s("%d", &order);
        getchar();//读走缓存里的回车符
        switch (order)
        {
        case 1://录入成绩
            //n = ReadScore(num, score, n);
            n = ReadScore(students, n, m);
            AverSumofEveryStudent(students, n, m);//每次录入结束后都得重新计算
            break;
        case 2://计算每门课程的总分和平均分;
            AverSumofEveryCourse(students, n, m);
            break;
        case 3://计算每个学生的总分和平均分
            AverSumofEveryStudent(students, n, m);
            printf("已经重新计算总分和平均分\n");
            break;
        case 4://按每个学生的总分由高到低排出名次表;
            SortbyScore(students, n, m, Descending);
            printf("Descendingly scorted by scores:\n");
            PrintScore(students, n, m);
            break;
        case 5://按每个学生的总分由低到高排出名次表;
            SortbyScore(students, n, m, Ascending);
            printf("Ascendingly scorted by scores:\n");
            PrintScore(students, n, m);
            break;
        case 6://按学号升序排名
            SortbyNum(students, n, m, Ascending);
            printf("Ascendingly scorted by num:\n");
            PrintScore(students, n, m);
            break;
        case 7://按姓名的字典顺序排出成绩表;
            SortbyName(students, n, m);
            printf("Dictionarily scorted by name:\n");
            PrintScore(students, n, m);
            break;
        case 8://按学号查询学生排名及其各科考试成绩;
            SearchbyNum(students, n, m);
            break;
        case 9://按姓名查询学生排名及其各科考试成绩;
            SearchbyName(students, n, m);
            break;
        case 10://按优秀(90- 100)、良好(80- 89)、中等(70-79)、及格(60- 69)、不及格(0-59)5个类别,
                   //统计每个类别的人数以及所占的百分比;
            StatistAnalysis(students, n, m);
            break;
        case 11://输出每个学生的学号、姓名,各科考试成绩,总分,平均分,以及每门课程的总分和平均分。
            PrintScore(students, n, m);
            AverSumofEveryCourse(students, n, m);
            break;
        case 0://退出系统
            printf("Good Bye!\n");
            exit(0);//建议main函数用exit(0)表示正常结束
        default:
            Mean();
            break;
        }
    }
}

head File

/*程序功能:   学生成绩管理
编码者:   JackieFeng
日期:  13/11/2021
版本号:5.0
备注:
某班有最多不超过30人(具体人数由键盘输入)参加期末考试,考试科目最多不超过6门(具体门数由键盘输入)。
定义结构体类型,用结构体数组作函数参数编程实现如下菜单驱动的学生成绩管理系统:
(1)录入每个学生的学号,姓名和各科考试成绩;
(2)计算每门课程的总分和平均分;
(3)计算每个学生的总分和平均分
(4)按每个学生的总分由高到低排出名次表;
(5)按每个学生的总分由低到高排出名次表;
(6)按学号由小到大排出成绩表;
(7)按姓名的字典顺序排出成绩表;
(8)按学号查询学生排名及其各科考试成绩;
(9)按姓名查询学生排名及其各科考试成绩;
(10)按优秀(90- 100)、良好(80- 89)、中等(70-79)、及格(60- 69)、不及格(0-59)5个类别,对每门课程分别统计每个类别的人数以及所占的百分比;
(11)输出每个学生的学号、姓名,各科考试成绩,总分,平均分,以及每门课程的总分和平均分。*/
#pragma once
#define STU_NUM 30      //最多人数
#define MAX_LEN 10      //名字最大长度
#define COURSE_NUM 6//课程数上限

//学生结构体
//long num;
//char name[MAX_LEN];
//float score[COURSE_NUM];
//float sum;
//float aver;
typedef struct student
{
    long num;
    char name[MAX_LEN];
    float score[COURSE_NUM];
    float sum;
    float aver;
}STU;

/*
函数名称:   Mean
功能描述:   显示菜单页面,提示用户如何使用
参数:
返回:
备注:*/
int Mean(void);
/*
函数名称:   ReadScore
功能描述:   录入每个学生的学号和成绩,并返回总人数
参数:
    STU students:学生结构体数组
    n:实际总人数
    m:实际课程数
返回:变化后总人数
备注:*/
int ReadScore(STU students[], int n, int m);
/*
函数名称:   AverSumofEveryCourse
功能描述:   计算每门课程的总分和平均分
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
返回:
备注:*/
void AverSumofEveryCourse(STU students[], int n, int m);
/*
函数名称:   AverSumofEveryCourse
功能描述:   计算每个学生的总分和平均分
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
返回:
备注:*/
void AverSumofEveryStudent(STU students[], int n, int m);
/*
函数名称:   SortbyScore
功能描述:   按照学生总分排列名次表,使用函数指针表达升降序
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
    *compare:比较函数指针
返回:
备注:*/
void SortbyScore(STU students[], int n, int m, int (*compare)(int a, int b));
/*
函数名称:   SortbyNum
功能描述:   按照学号升序排列
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
    *compare:比较函数指针
返回:
备注:*/
void SortbyNum(STU students[], int n, int m, int (*compare)(int a, int b));
/*
函数名称:   SortbyName
功能描述:   按照姓名字典顺序排列
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
返回:
备注*/
void SortbyName(STU students[], int n, int m);
/*
函数名称:   SearchbyNum
功能描述:   按学号查询学生排名及其各科考试成绩;
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
返回:索引号
备注:*/
int SearchbyNum(STU students[], int n, int m);
/*
函数名称:   SearchbyName
功能描述:   按姓名查询学生排名及其各科考试成绩;
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
返回:索引号
备注:*/
int SearchbyName(STU students[], int n, int m);
/*
函数名称:   StatistAnalysis
功能描述:   按优秀(90- 100)、良好(80- 89)、中等(70-79)、及格(60- 69)、不及格(0-59)5个类别,
                 对每门课程分别统计每个类别的人数以及所占的百分比;
参数:
    STU students:学生结构体数组
    n:总人数
    m:总课程数
返回:
备注:*/
void StatistAnalysis(STU students[], int n, int m);
/*
函数名称:   PrintScore
功能描述:   打印每位学生的学号,姓名和成绩
参数:
    STU students:学生结构体数组
    n:总人数
    m:课程总数
返回:
备注:*/
void PrintScore(STU students[], int n, int m);
/*
函数名称:   FloatSwap
功能描述:   交换两个浮点型变量
参数:
    a:float型指针
    b:float型指针
返回:
备注:*/
void FloatSwap(float* a, float* b);
/*
函数名称:   LongSwap
功能描述:   交换两个长整型变量
参数:
    a:long型指针
    b:long型指针
返回:
备注:*/
void LongSwap(long* a, long* b);
/*
函数名称:   LongSwap
功能描述:   交换两个长整型变量
参数:
    a:long型指针
    b:long型指针
返回:
备注:*/
void CharSwap(char a[], char b[]);
/*
函数名称:   Ascending
功能描述:   升序比较函数
参数:
    a:比较数
    b:比较数
返回:a<b
备注:*/
int Ascending(int a, int b);
/*
函数名称:   Descending
功能描述:   降序比较函数
参数:
    a:比较数
    b:比较数
返回:a>b
备注:*/
int Descending(int a, int b);

#Implementation

int ReadScore(STU students[], int n, int m)
{
    printf("正在录入学生信息...\n");
    printf("学号录入-1时结束录入\n");
    int i = n - 1;
    do
    {
        i++;
        printf("正在录入第%d个学生的学号,姓名\n", i + 1);
        //scanf("%ld%s%f", &num[i], name[i], &score[i]);//数值类型与字符串类型交叉输入可用空格隔开
        scanf_s("%ld", &students[i].num);
        if (students[i].num == -1)//若用户输入完毕则退出输入
            break;
        scanf_s("%s", students[i].name, 10);//scanf_s函数在输入字符串时必须指定字符串长度
        getchar();//读走回车符
        printf("请连续按顺序输入第%d个学生%d课成绩\n", i + 1, m);
        for (int j = 0; j < m; j++)
        {
            scanf_s("%f", &students[i].score[j]);
        }
    } while (i <= 30);
    printf("录入完成总共录入%d人\n", i);
    return i;
}

void AverSumofEveryCourse(STU students[], int n, int m)
{
    float sum[COURSE_NUM] = { 0 };
    float aver[COURSE_NUM] = { 0 };
    //i行j列,算课程总分,按列算总和
    for (int j = 0; j < m; j++)
    {
        for (int i = 0; i < n; i++)
        {
            sum[j] += students[i].score[j];
        }
        aver[j] = sum[j] / n;
        printf("科目%d的总分为%.2f,平均分为%.2f\n", j + 1, sum[j], aver[j]);
    }
}

void AverSumofEveryStudent(STU students[], int n, int m)
{
    for (int i = 0; i < n; i++)
    {
        students[i].sum = 0;//每次计算总和都得先初始化sum为0
        for (int j = 0; j < m; j++)
        {
            students[i].sum += students[i].score[j];
        }
        students[i].aver = students[i].sum / m;
    }
}

void SortbyScore(STU students[], int n, int m, int(*compare)(int a, int b))
{
    //选择排序,第一层循环整个数组,每次归一位
    for (int i = 0; i < n - 1; i++)
    {
        int cmp = i;//比较位索引值,初始为乱序区第一位
        //第二层循环乱序位,每次从乱序列中选择最大一位
        for (int j = i; j < n; j++)
        {
            if (compare(students[cmp].sum, students[j].sum))//比总分
            {
                cmp = j;
            }
        }
        //发生改变,交换
        if (i != cmp)
        {
            LongSwap(&students[i].num, &students[cmp].num);
            CharSwap(students[i].name, students[cmp].name);
            FloatSwap(&students[i].sum, &students[cmp].sum);
            FloatSwap(&students[i].aver, &students[cmp].aver);
            for (int j = 0; j < m; j++)
            {
                FloatSwap(&students[i].score[j], &students[cmp].score[j]);
            }
        }
    }
}

void SortbyNum(STU students[], int n, int m, int(*compare)(int a, int b))
{
    //选择排序,第一层循环整个数组,每次归一位
    for (int i = 0; i < n - 1; i++)
    {
        int cmp = i;//最大位索引值,初试为乱序区第一位
        //第二层循环乱序位,每次从乱序列中选择学号最小的一位
        for (int j = i + 1; j < n; j++)
        {
            if ((*compare)(students[cmp].num, students[j].num))
            {
                cmp = j;
            }
        }
        //发生改变,交换
        if (i != cmp)
        {
            LongSwap(&students[i].num, &students[cmp].num);
            CharSwap(students[i].name, students[cmp].name);
            FloatSwap(&students[i].sum, &students[cmp].sum);
            FloatSwap(&students[i].aver, &students[cmp].aver);
            for (int j = 0; j < m; j++)
            {
                FloatSwap(&students[i].score[j], &students[cmp].score[j]);
            }
        }
    }
}

void SortbyName(STU students[], int n, int m)
{
    //选择排序,第一层循环整个数组,每次归一位
    for (int i = 0; i < n - 1; i++)
    {
        int cmp = i;//最大位索引值,初试为乱序区第一位
        //第二层循环乱序位,每次从乱序列中选择字典顺序靠前的一位
        for (int j = i + 1; j < n; j++)
        {
            if (strcmp(students[cmp].name, students[j].name) > 0)//对比位比乱序位大,不行要换,保持对比位最小(升序)
            {
                cmp = j;
            }
        }
        //发生改变,交换
        if (i != cmp)
        {
            LongSwap(&students[i].num, &students[cmp].num);
            CharSwap(students[i].name, students[cmp].name);
            FloatSwap(&students[i].sum, &students[cmp].sum);
            FloatSwap(&students[i].aver, &students[cmp].aver);
            for (int j = 0; j < m; j++)
            {
                FloatSwap(&students[i].score[j], &students[cmp].score[j]);
            }
        }
    }
}

int SearchbyNum(STU students[], int n, int m)
{
    int rank = -1;//学生排名
    int x;//被查询学号
    while (true)
    {
        printf("Please enter the student ID queried\n");
        scanf_s("%d", &x);
        SortbyScore(students, n, m, Descending);//先排序
        //顺序查找
        for (int i = 0; i < n; i++)
        {
            if (x == students[i].num)
            {
                printf("name:%-10s rank:%-10d", students[i].name, i + 1);//索引+1为排名
                for (int j = 0; j < m; j++)
                {
                    printf("科目%d:%-10.1f", j + 1, students[i].score[j]);
                }
                printf("\n");
                return i;
            }
        }
        printf("Can't find,please checkout again.\n");
    }
}

int SearchbyName(STU students[], int n, int m)
{
    int rank = -1;//学生排名
    char x[MAX_LEN];//被查询姓名
    while (true)
    {
        printf("Please enter the student name queried\n");
        gets_s(x, MAX_LEN);
        SortbyScore(students, n, m, Descending);//先排序
        //顺序查找
        for (int i = 0; i < n; i++)
        {
            if (strcmp(x, students[i].name) == 0)
            {
                printf("name:%-10s rank:%-10d", students[i].name, i + 1);//索引+1为排名
                for (int j = 0; j < m; j++)
                {
                    printf("科目%d:%-10.1f", j + 1, students[i].score[j]);
                }
                printf("\n");
                return i;
            }
        }
        printf("Can't find,please checkout again.\n");
    }
}

void StatistAnalysis(STU students[], int n, int m)
{
    for (int j = 0; j < m; j++)//统计每门课
    {
        printf("科目%d情况如下:\n", j + 1);

        int ranks[5] = { 0 };// 各种档次的人数,首位赋值为0,后续位补充为0
        for (int i = 0; i < n; i++)//遍历整个成绩,统计数据
        {
            if (students[i].score[j] < 60)
            {
                ranks[0]++;
            }
            else if (students[i].score[j] < 70 && students[i].score[j] >= 60)
            {
                ranks[1]++;
            }
            else if (students[i].score[j] < 80 && students[i].score[j] >= 70)
            {
                ranks[2]++;
            }
            else if (students[i].score[j] < 90 && students[i].score[j] >= 80)
            {
                ranks[3]++;
            }
            else//90到100档
            {
                ranks[4]++;
            }
        }
        //输出统计数据
        printf("%-10s%-10s%-10s\n", "rank ", "amount", "percent");
        printf("%-10s%-10d%.0f%%\n", "0-59 ", ranks[0], ranks[0] / (float)n * 100);
        printf("%-10s%-10d%.0f%%\n", "60-69", ranks[1], ranks[1] / (float)n * 100);
        printf("%-10s%-10d%.0f%%\n", "70-79", ranks[2], ranks[2] / (float)n * 100);
        printf("%-10s%-10d%.0f%%\n", "80-89", ranks[3], ranks[3] / (float)n * 100);
        printf("%-10s%-10d%.0f%%\n", "90-100", ranks[4], ranks[4] / (float)n * 100);
    }
}

void PrintScore(STU students[], int n, int m)
{
    printf("%-10s%-10s", "学号", "姓名");
    for (int j = 0; j < m; j++)
    {
        printf("%-4s%-6d", "科目", j + 1);//汉字一个字算两个width
    }
    printf("%-10s%-10s\n", "总分", "平均分");

    for (int i = 0; i < n; i++)
    {
        printf("%-10d%-10s", students[i].num, students[i].name);
        for (int j = 0; j < m; j++)
        {
            printf("%-10.1f", students[i].score[j]);
        }
        printf("%-10.1f%-10.1f", students[i].sum, students[i].aver);
        printf("\n");
    }
}

void FloatSwap(float* a, float* b)
{
    float tmp = *a;
    *a = *b;
    *b = tmp;
}

void LongSwap(long* a, long* b)
{
    long tmp = *a;
    *a = *b;
    *b = tmp;
}

void CharSwap(char a[], char b[])
{
    char tmp[MAX_LEN];
    strcpy_s(tmp, MAX_LEN, a);
    strcpy_s(a, MAX_LEN, b);
    strcpy_s(b, MAX_LEN, tmp);
}

int Ascending(int a, int b)
{
    return a > b;
}

int Descending(int a, int b)
{
    return a < b;
}

Guess you like

Origin blog.csdn.net/weixin_43231912/article/details/122284255