C语言大作业——学生成绩管理系统(题目+完整代码)

一、题目内容

数据存储要求:

        要求至少能够存储学生的学号、姓名、班级、实验1成绩、实验2成绩、实验3成绩,总分;也可以根据个人理解增加其他需要存储的信息。

基本功能:

1、学生名单管理:

        ①添加学生信息:录入学生的学号、姓名和班级;录入前先检测学生学号,如果学号已存在则提示学生已存在,输入新的学生信息。

        ②删除学生信息:先按照学生学号进行查找,找到,则删除学生信息(如果学生已有实验成绩,则实验成绩和总分也删除);找不到,给出提示信息。

        ③修改学生信息,先按照学生学号进行查找,找到对应的学生,先显示学生所有信息再选择修改姓名或者班级;找不到,给出提示信息。

        ④根据学号或姓名查询学生的信息,要求输出学号、姓名、班级。

        ⑤显示所有学生信息。

2、实验成绩管理:

        ①录入实验成绩,先输入要录入的学生学号,再选择录入实验1、实验2或者实验3成绩;如果学生学号不存在,则提示不存在。

        ②删除实验成绩,删除某个学生某一次实验的成绩。

        ③修改修改成绩,修改某个学生某一次实验的成绩。

        ④查找某个学生的成绩,根据学号进行查找,找到,则显示该生的姓名、学号、班级、实验1成绩、实验2成绩和实验3成绩;找不到,则给出提示信息。

        ⑤输出每个实验排名前三的学生学号和姓名;

        ⑥输出每个班级每次实验的平均分,输入如下信息:班级、实验1平均分、实验2平均分、实验3平均分。

        ⑦按照总分对于学生成绩进行降序排列,并输出学生成绩表,成绩表包含学号、姓名、班级和总分。

3、扩展功能:

        ①输出有一次实验不及格的学生信息;2次实验不及格的学生。

        ②可以用文件获取数据,每次程序运行开始时,把文件中存储的学生信息读入内存;程序退出时,先把内存中存储的学生信息保存在文件中,然后再结束程序。

        ③可自己定义其他功能需求,使系统功能更加完善。

二、程序代码

#define _CRT_SECURE_NO_WARNINGS
#define MAX_STUDENTS 100
#define MAX_NAME_LENGTH 50
#define MAX_CLASS_LENGTH 20
#define MAX_EXPERIMENTS 3
#define PASSING_SCORE 60

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>

struct student
{
    int student_id; 
    char student_name[MAX_NAME_LENGTH];
    char student_class[MAX_CLASS_LENGTH];
    double experiment_scores[3];
    double total_score;
};

struct student students[MAX_STUDENTS];
int num_students = 0;

//声明函数,以便于函数的调用
void read_student_data();

void add_student();
void delete_student();
void modify_student();
void search_student();
void display_all_students();

void enter_student_scores();
void delete_student_score();
void modify_student_score();
void find_student_by_id();
void display_top_three(int experiment_index);
void calculate_class_average();
void display_student_scores();
void display_failed_students(int num_failures);

int main()
{
    read_student_data();
    int choice;
    do {
        printf("\n======= 实验成绩统计系统 =======\n");
        printf("1. 学生名单管理\n");
        printf("2. 实验成绩管理\n");
        printf("3. 扩展功能\n");
        printf("0. 退出\n");
        printf("请选择功能:");
        scanf("%d", &choice);

        switch (choice) {
        case 1:
            printf("\n======= 学生名单管理 =======\n");
            printf("1. 添加学生信息\n");
            printf("2. 删除学生信息\n");
            printf("3. 修改学生信息\n");
            printf("4. 根据学号或姓名查询学生信息\n");
            printf("5. 显示所有学生信息\n");
            printf("请选择功能:");
            scanf("%d", &choice);
            switch (choice) {
            case 1:
                add_student();
                break;
            case 2:
                delete_student();
                break;
            case 3:
                modify_student();
                break;
            case 4:
                printf("请输入要查询的学生姓名或学号:");
                char keyword[50];
                scanf("%s", keyword);
                search_student(keyword);
                break;
            case 5:
                display_all_students();
                break;
            default:
                printf("无效的选项,请重新选择。\n");
            }
            break;
        case 2:
            printf("\n======= 实验成绩管理 =======\n");
            printf("1. 录入实验成绩\n");
            printf("2. 删除实验成绩\n");
            printf("3. 修改实验成绩\n");
            printf("4. 根据学号查询实验成绩\n");
            printf("5. 输出每个实验排名前三的学生\n");
            printf("6. 输出每个班级每次实验的平均分\n");
            printf("7. 按照总分降序排列学生成绩制表\n");
            printf("请选择功能:");
            scanf("%d", &choice);
            switch (choice) {
            case 1:
                enter_student_scores();
                break;
            case 2:
                delete_student_score();
                break;
            case 3:
                modify_student_score();
                break;
            case 4:
                find_student_by_id();
                break;
            case 5:
                // 输出每个实验排名前三的学生学号和姓名
                for (int i = 0; i < 3; i++) {
                    display_top_three(i);
                }
                break;
            case 6:
                calculate_class_average();
                break;
            case 7:
                display_student_scores();
                break;
            default:
                printf("无效的选项,请重新选择。\n");
            }
            break;
        case 3:
            printf("\n======= 扩展功能 =======\n");
            printf("1. 输出有一次实验不及格的学生信息\n");
            printf("2. 输出两次实验不及格的学生信息\n");
            printf("请选择功能:");
            scanf("%d", &choice);
            switch (choice) {
            case 1:
                display_failed_students(1);
                break;
            case 2:
                display_failed_students(2);
                break;
            default:
                printf("无效的选项,请重新选择。\n");
            }
            break;
        case 0:
            printf("感谢使用,再见!\n");
            break;
        default:
            printf("无效的选项,请重新选择。\n");
        }
    } while (choice != 0);

    return 0;
}


//一、学生名单管理
//1、添加学生信息
void add_student()
{
    //检测存储是否已满
    if (num_students >= MAX_STUDENTS)
    {
        printf("学生信息已满,无法添加。\n");
        printf("如果希望添加更多的学生,请修改 MAX_STUDENTS 的值");
        return;
    }

    // 检查学号是否已存在
    for (int i = 0; i < num_students; i++) {
        printf("请输入学生信息:\n");
        printf("学号:");
        int new_id;
        scanf("%d", &new_id);
        if (students[i].student_id == new_id) {
            printf("该学生已存在,请重新输入。\n");
        }
        else {
            break;
        }
    }

    //对结构体数组进行赋值
    printf("请再确认学号:");
    scanf("%d", &students[num_students].student_id);
    printf("姓名:");
    scanf("%s", &students[num_students].student_name);
    printf("班级:");
    scanf("%s", &students[num_students].student_class);
    students[num_students].experiment_scores[0] = 0.0;
    students[num_students].experiment_scores[1] = 0.0;
    students[num_students].experiment_scores[2] = 0.0;
    students[num_students].total_score = 0.0;
    num_students++;

    //将结构体数组完全再一次存入文件中
    FILE* file = fopen("D:/students.txt", "w");
    if (file == NULL)
    {
        printf("无法打开文件进行写入。\n");
        return;
    }
    for (int i = 0; i < num_students; i++)
    {
        fprintf(file, "%d %s %s %.2f %.2f %.2f %.2f\n",
            students[i].student_id,
            students[i].student_name,
            students[i].student_class,
            students[i].experiment_scores[0],
            students[i].experiment_scores[1],
            students[i].experiment_scores[2],
            students[i].total_score);
    }
    fflush(file);
    printf("学生信息添加成功。\n");
}

//2、删除学生信息
void delete_student()
{
    int found = 0;
    int student_id;
    printf("请输入要删除的学生学号:");
    scanf("%d", &student_id);

    for (int i = 0; i < num_students; i++) {
        if (students[i].student_id == student_id) {
            found = 1;
            // 将最后一个学生信息移到当前位置,然后减少学生数量
            students[i] = students[num_students - 1];
            num_students--;
            printf("学生信息删除成功。\n");
            break;
        }
    }
    if (!found) {
        printf("未找到学号为 %d 的学生信息。\n", student_id);
    }

    //将结构体数组完全再一次存入文件中
    FILE* file = fopen("D:/students.txt", "w");
    if (file == NULL) {
        printf("无法打开文件进行写入。\n");
        return;
    }
    for (int i = 0; i < num_students; i++)
    {
        fprintf(file, "%d %s %s %.2f %.2f %.2f %.2f\n",
            students[i].student_id,
            students[i].student_name,
            students[i].student_class,
            students[i].experiment_scores[0],
            students[i].experiment_scores[1],
            students[i].experiment_scores[2],
            students[i].total_score);
    }
    fflush(file);
    printf("学生信息删除成功。\n");
}

//3、修改学生信息
void modify_student()
{
    int found = 0;
    int student_id;
    printf("请输入要修改的学生学号:");
    scanf("%d", &student_id);

    for (int i = 0; i < num_students; i++) {
        if (students[i].student_id == student_id) {
            found = 1;
            printf("请输入新的学生信息:\n");
            printf("姓名:");
            scanf("%s", students[i].student_name);
            printf("班级:");
            scanf("%s", students[i].student_class);
            printf("学生信息修改成功。\n");
            break;
        }
    }
    if (!found) {
        printf("未找到学号为 %d 的学生信息。\n", student_id);
    }

    //将结构体数组完全再一次存入文件中
    FILE* file = fopen("D:/students.txt", "w");
    if (file == NULL) {
        printf("无法打开文件进行写入。\n");
        return;
    }
    for (int i = 0; i < num_students; i++)
    {
        fprintf(file, "%d %s %s %.2f %.2f %.2f %.2f\n",
            students[i].student_id,
            students[i].student_name,
            students[i].student_class,
            students[i].experiment_scores[0],
            students[i].experiment_scores[1],
            students[i].experiment_scores[2],
            students[i].total_score);
    }
    fflush(file);
    printf("学生信息修改成功。\n");
}

//4、以学号查询学生信息
void search_student(const char* keyword)
{
    int found = 0;
    for (int i = 0; i < num_students; i++)
    {
        //atoi函数将字符串转换成整型数据
        if (strcmp(students[i].student_name, keyword) == 0 || students[i].student_id == atoi(keyword))
        {
            found = 1;
            printf("学号:%d,姓名:%s,班级:%s\n",
                students[i].student_id, students[i].student_name, students[i].student_class);
            break;
        }
    }
    if (!found)
    {
        printf("未找到与关键词匹配的学生信息。\n");
    }
}

//5、显示所有学生信息
void display_all_students()
{
    //检测学生信息是否为空
    if (num_students == 0) {
        printf("学生信息为空。\n");
        return;
    }
    //打印学生信息
    printf("所有学生信息如下:\n");
    for (int i = 0; i < num_students; i++)
    {
        printf("学号:%d,姓名:%s,班级:%s\n",
            students[i].student_id, students[i].student_name, students[i].student_class);
    }
}

//二、实验成绩管理
//1、录入实验成绩
//因为我们在添加学生信息的时候,已经为学生成绩初始化赋值
//所以我们在录入实验成绩的时候,本质时修改学生成绩
//我们只需修改中文指引即可完成相应功能
void enter_student_scores()
{
    //检测有无学生信息
    if (num_students == 0) {
        printf("没有学生信息可供录入成绩。\n");
        return;
    }

    //录入学生成绩
    printf("请输入要录入成绩的学生学号:");
    int student_id;
    scanf("%d", &student_id);

    printf("请输入要录入的实验次数(1、2或3):");
    int experiment_number;
    scanf("%d", &experiment_number);

    int found = 0;
    for (int i = 0; i < num_students; i++)
    {
        if (students[i].student_id == student_id)
        {
            if (experiment_number >= 1 && experiment_number <= 3)
            {
                printf("请输入实验%d成绩:", experiment_number);
                scanf("%lf", &students[i].experiment_scores[experiment_number - 1]);

                // 更新总分
                students[i].total_score = students[i].experiment_scores[0] + students[i].experiment_scores[1] + students[i].experiment_scores[2];

                printf("学生 %s 的实验%d成绩已成功录入。\n", students[i].student_name, experiment_number);
                found = 1;
            }
            else {
                printf("请输入有效的实验次数(1、2或3)!\n");
            }
            break;
        }
    }
    if (!found) {
        printf("未找到学号为 %d 的学生信息。\n", student_id);
    }

    //将结构体数组完全再一次存入文件中
    FILE* file = fopen("D:/students.txt", "w");
    if (file == NULL) {
        printf("无法打开文件进行写入。\n");
        return;
    }
    for (int i = 0; i < num_students; i++)
    {
        fprintf(file, "%d %s %s %.2f %.2f %.2f %.2f\n",
            students[i].student_id,
            students[i].student_name,
            students[i].student_class,
            students[i].experiment_scores[0],
            students[i].experiment_scores[1],
            students[i].experiment_scores[2],
            students[i].total_score);
    }
    fflush(file);
    printf("学生成绩录入成功。\n");
}

//2、删除实验成绩
void delete_student_score() 
{
    //检测有无学生信息
    if (num_students == 0) {
        printf("没有学生信息可供删除成绩。\n");
        return;
    }

    //删除学生成绩
    printf("请输入要删除成绩的学生学号:");
    int student_id;
    scanf("%d", &student_id);

    printf("请输入要删除的实验次数(1、2或3):");
    int experiment_number;
    scanf("%d", &experiment_number);

    int found = 0;
    for (int i = 0; i < num_students; i++) {
        if (students[i].student_id == student_id) {
            if (experiment_number >= 1 && experiment_number <= 3) {
                students[i].experiment_scores[experiment_number - 1] = 0;
                printf("学生 %s 的实验%d成绩已成功删除。\n", students[i].student_name, experiment_number);
                found = 1;
                // 更新总分
                students[i].total_score = students[i].experiment_scores[0] + students[i].experiment_scores[1] + students[i].experiment_scores[2];
            }
            else {
                printf("请输入有效的实验次数(1、2或3)!\n");
            }
            break;
        }
    }
    if (!found) {
        printf("未找到学号为 %d 的学生信息。\n", student_id);
    }

    //将结构体数组完全再一次存入文件中
    FILE* file = fopen("D:/students.txt", "w");
    if (file == NULL) {
        printf("无法打开文件进行写入。\n");
        return;
    }
    for (int i = 0; i < num_students; i++)
    {
        fprintf(file, "%d %s %s %.2f %.2f %.2f %.2f\n",
            students[i].student_id,
            students[i].student_name,
            students[i].student_class,
            students[i].experiment_scores[0],
            students[i].experiment_scores[1],
            students[i].experiment_scores[2],
            students[i].total_score);
    }
    fflush(file);
    printf("学生成绩删除成功。\n");
}

//3、修改学生成绩
void modify_student_score()
{
    //检测有无学生信息
    if (num_students == 0) {
        printf("没有学生信息可供修改成绩。\n");
        return;
    }

    //修改学生成绩
    printf("请输入要修改成绩的学生学号:");
    int student_id;
    scanf("%d", &student_id);

    printf("请输入要修改的实验次数(1、2或3):");
    int experiment_number;
    scanf("%d", &experiment_number);

    int found = 0;
    for (int i = 0; i < num_students; i++)
    {
        if (students[i].student_id == student_id)
        {
            if (experiment_number >= 1 && experiment_number <= 3)
            {
                printf("请输入新的实验%d成绩:", experiment_number);
                scanf("%lf", &students[i].experiment_scores[experiment_number - 1]);

                // 更新总分
                students[i].total_score = students[i].experiment_scores[0] + students[i].experiment_scores[1] + students[i].experiment_scores[2];

                printf("学生 %s 的实验%d成绩已成功修改。\n", students[i].student_name, experiment_number);
                found = 1;
            }
            else {
                printf("请输入有效的实验次数(1、2或3)!\n");
            }
            break;
        }
    }
    if (!found) {
        printf("未找到学号为 %d 的学生信息。\n", student_id);
    }

    //将结构体数组完全再一次存入文件中
    FILE* file = fopen("D:/students.txt", "w");
    if (file == NULL) {
        printf("无法打开文件进行写入。\n");
        return;
    }
    for (int i = 0; i < num_students; i++)
    {
        fprintf(file, "%d %s %s %.2f %.2f %.2f %.2f\n",
            students[i].student_id,
            students[i].student_name,
            students[i].student_class,
            students[i].experiment_scores[0],
            students[i].experiment_scores[1],
            students[i].experiment_scores[2],
            students[i].total_score);
    }
    fflush(file);
    printf("学生成绩修改成功。\n");
}

//4、查找学生的成绩
void find_student_by_id()
{
    //检测有无学生信息
    if (num_students == 0) {
        printf("没有学生信息可供查找成绩。\n");
        return;
    }

    //查找学生信息
    printf("请输入要查找成绩的学生学号:");
    int student_id;
    scanf("%d", &student_id);

    int found = 0;
    for (int i = 0; i < num_students; i++) {
        if (students[i].student_id == student_id) {
            printf("姓名:%s\n", students[i].student_name);
            printf("学号:%d\n", students[i].student_id);
            printf("班级:%s\n", students[i].student_class);
            printf("实验1成绩:%.2f\n", students[i].experiment_scores[0]);
            printf("实验2成绩:%.2f\n", students[i].experiment_scores[1]);
            printf("实验3成绩:%.2f\n", students[i].experiment_scores[2]);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("未找到学号为 %d 的学生信息。\n", student_id);
    }
}

//5、输出每班实验前三的学生学号和姓名
void display_top_three(int experiment_index)
{
    // 对特定实验成绩进行排序
    for (int i = 0; i < num_students - 1; i++)
    {
        for (int j = 0; j < num_students - i - 1; j++)
        {
            if (students[j].experiment_scores[experiment_index] < students[j + 1].experiment_scores[experiment_index])
            {
                // 交换学生信息
                struct student temp;
                temp = students[j];
                students[j] = students[j + 1];
                students[j + 1] = temp;
            }
        }
    }

    // 输出排名前三的学生学号和姓名
    printf("实验%d排名前三的学生信息如下:\n", experiment_index + 1);
    for (int i = 0; i < num_students && i < 3; i++)
    {
        printf("排名%d: 学号: %d, 姓名: %s, 成绩: %.2f\n", i + 1, students[i].student_id,
            students[i].student_name, students[i].experiment_scores[experiment_index]);
    }
}

//6、输出每个班级每次实验的平均分
void calculate_class_average() 
{
    int class_printed[MAX_STUDENTS] = { 0 }; // 记录每个班级是否已经输出过

    // 遍历所有班级
    for (int i = 0; i < num_students; i++) {
        if (!class_printed[i]) { // 如果该班级未输出过
            char current_class[MAX_CLASS_LENGTH];
            strcpy(current_class, students[i].student_class);

            double total_score[MAX_EXPERIMENTS] = { 0 };
            int count[MAX_EXPERIMENTS] = { 0 };

            // 遍历所有学生
            for (int j = 0; j < num_students; j++) {
                // 如果班级匹配,则计算总分
                if (strcmp(students[j].student_class, current_class) == 0) {
                    for (int k = 0; k < MAX_EXPERIMENTS; k++) {
                        total_score[k] += students[j].experiment_scores[k];
                        if (students[j].experiment_scores[k] != -1) { // -1表示该学生没有参加该次实验
                            count[k]++;
                        }
                    }
                }
            }

            // 输出每个班级每次实验的平均分
            printf("班级:%s\n", current_class);
            for (int k = 0; k < MAX_EXPERIMENTS; k++) 
            {
                if (count[k] != 0) 
                { // 避免除以0
                    double average_score = total_score[k] / count[k];
                    printf("实验%d平均分:%.2f\n", k + 1, average_score);
                }
                else 
                {
                    printf("实验%d平均分:暂无数据\n", k + 1);
                }
            }
            printf("\n");

            // 标记该班级已经输出过
            for (int j = 0; j < num_students; j++) 
            {
                if (strcmp(students[j].student_class, current_class) == 0)
                {
                    class_printed[j] = 1;
                }
            }
        }
    }
}

//7、对学生成绩进行降序排列
void display_student_scores()
{
    for (int i = 0; i < num_students - 1; i++)
    {
        for (int j = 0; j < num_students - i - 1; j++)
        {
            if (students[j].total_score < students[j + 1].total_score)
            {
                // 交换位置
                struct student temp;
                temp = students[j];
                students[j] = students[j + 1];
                students[j + 1] = temp;
            }
        }
    }

    printf("学号\t\t姓名\t班级\t总分\n");
    for (int i = 0; i < num_students; i++)
    {
        printf("%d\t%s\t%s\t%.2lf\n",
            students[i].student_id, students[i].student_name, students[i].student_class, students[i].total_score);
    }
}


//三、扩展内容
//1、查找实验不及格学生信息
void display_failed_students(int num_failures)
{
    printf("以下是%d次实验不及格的学生信息:\n", num_failures);
    printf("学号\t\t姓名\t班级\n");
    for (int i = 0; i < num_students; i++)
    {
        int num_fails = 0;
        for (int j = 0; j < MAX_EXPERIMENTS; j++)
        {
            if (students[i].experiment_scores[j] < PASSING_SCORE)
            {
                num_fails++;
            }
        }
        if (num_fails == num_failures)
        {
            printf("%d\t%s\t%s\n", students[i].student_id, students[i].student_name, students[i].student_class);
        }
    }
}

//2、将文件信息读取到内存
void read_student_data()
{
    FILE* file = fopen("D:/students.txt", "r");
    if (file == NULL) {
        printf("无法打开文件\n");
        return;
    }
    //读取文件的时候,我们要将文件编码格式改为ANSI保存,才能正常读取中文
    while (fscanf(file, "%d %s %s %lf %lf %lf %lf",
        &students[num_students].student_id,
        &students[num_students].student_name,
        &students[num_students].student_class,
        &students[num_students].experiment_scores[0],
        &students[num_students].experiment_scores[1],
        &students[num_students].experiment_scores[2],
        &students[num_students].total_score) == 7) {
        printf("学生信息:%d %s %s %.2lf %.2lf %.2lf %.2lf\n",
            students[num_students].student_id,
            students[num_students].student_name,
            students[num_students].student_class,
            students[num_students].experiment_scores[0],
            students[num_students].experiment_scores[1],
            students[num_students].experiment_scores[2],
            students[num_students].total_score);
        num_students++;
        if (num_students >= MAX_STUDENTS) {
            printf("学生数量超过最大限制\n");
            break;
        }
    }
    fclose(file);
}

三、注意事项

        1、该程序使用文本文档读取与存储数据,需要在D盘底下创建一个students.txt文件。

        2、students.txt文件的编码方式要从默认的UTF-8转换为ANSI;否则会乱码。具体如何转换,下一篇文章会作详细介绍。

        3、学号使用int类型变量存储,int的取值范围是“-2147483648 ~ 2147483647”,学号不要超过这个范围。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值