Alex ander bro 2024-06-08 23:25 采纳率: 0%
浏览 4

c语言学生学籍管理系统

我用c语言链表的知识编写了学生学籍管理系统,第一次运行一切正常,第二次运行执行的时候,加载文件后查询不到任何信息。以下是我的代码,希望有哪位好人帮忙看看,有源代码改进的更好了


```c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct StudentInfo {
    char name[50];
    int id;
    char sex[30];
    int age;
    char major[50];
    int sort;
    float grapoint;
};
struct Course {
    char name[20];
    float score;
    float credit;
    float DKgrapoint;
    int ismakeup;//用来区分补缓考
};
typedef  struct student
{
    struct StudentInfo  info;
    struct Course  courses[10];
}stu;
typedef struct  Lnode
{
    stu  data;
    struct Lnode* next;
}linklist;
void load(linklist*& L);
void showmenu(linklist*& L);
void search(linklist* L);
void add(linklist*& L);
void modify(linklist* L);
void remove(linklist* L);
void save(linklist*& L);
void initlist(linklist*& L);
void insert(linklist*& L, linklist* p);
float compute_DKgpa(float score);
float compute_gpa(linklist* newnode);
int sort_grap(linklist* p, linklist* L);
int main()
{
    linklist* L;
    initlist(L);
    load(L);
    while (1)
    {
        showmenu(L);
    }
    system("pause");
    return 0;
}
void showmenu(linklist*& L)
{
    int num;
    printf("\n\n");
    printf("————————————————————————————————————-\n");
    printf("**********************学生学籍管理系统**********************\n");
    printf("***********************系统功能菜单***************************\n");
    printf("*                      1.查询学生信息                        *\n");
    printf("*                      2.添加学生信息                        *\n");
    printf("*                      3.修改学生信息                        *\n");
    printf("*                      4.删除学生信息                        *\n");
    printf("*                      5.保存信息到文件中                    *\n");
    printf("*                      7.退出系统                            *\n");
    printf("—————————————————————————————————————\n");
    printf("请选择菜单的编号:");
    scanf_s("%d", &num);//输入各个功能对应的序号以此来实现相应的功能
    switch (num) {
    case 1:search(L);
        break;
    case 2:add(L);
        break;
    case 3:modify(L);
        break;
    case 4:remove(L);
        break;
    case 5:save(L);
        break;
    case 6:printf("退出程序成功!\n");
        exit(0);
    default:
        printf("请在1-6之间选择\n");
        system("pause");//提示完成之后显示按任意键继续
    }
}
void initlist(linklist*& L)
{
    L = (linklist*)malloc(sizeof(linklist));
    L->next = NULL;
}
void insert(linklist*& L, linklist* p)//尾插法插入节点
{
    linklist* q;
    q = L;
    while (q->next)
    {
        q = q->next;
    }
    p->next = NULL;
    q->next = p;
}
void add(linklist*& L)
{
    linklist* p;
    p = L;
    int num;
    printf("请输入该名学生的学号:");
    scanf_s("%d", &num);
    while (p->next)
    {
        if (p->data.info.id == num)
        {
            printf("该学生已存在\n");
            break;
        }
        p = p->next;
    }
    if (!p->next)
    {
        linklist* newnode = (linklist*)malloc(sizeof(linklist));
        newnode->data.info.id = num;
        printf("请输入学生名字:");
        scanf_s("%s", newnode->data.info.name, _countof(newnode->data.info.name));
        printf("性别:");
        scanf_s("%s", newnode->data.info.sex, _countof(newnode->data.info.sex));
        printf("年龄:");
        scanf_s("%d", &newnode->data.info.age);
        printf("专业:");
        scanf_s("%s", &newnode->data.info.major, _countof(newnode->data.info.major));
        for (int i = 0; i < 10; i++)
        {
            printf("请输入第%d学科的相关信息:", i + 1);
            printf("请输入该科的名称:");
            scanf_s("%s", newnode->data.courses[i].name, _countof(newnode->data.courses[i].name));
            printf("请输入该门课的考试状态,0代表正常考试,1代表补缓考:");
            scanf_s("%d", &newnode->data.courses[i].ismakeup);
            printf("请输入该门课的考试成绩:");
            scanf_s("%f", &newnode->data.courses[i].score);
            printf("请输入该门课程的学分:");
            scanf_s("%f", &newnode->data.courses[i].credit);
            if (newnode->data.courses[i].ismakeup && newnode->data.courses[i].score >= 60)
                newnode->data.courses[i].score = 60;
            if (newnode->data.courses[i].ismakeup && newnode->data.courses[i].score < 60)
                newnode->data.courses[i].score = 0;
            newnode->data.courses[i].DKgrapoint = compute_DKgpa(newnode->data.courses[i].score);//单科成绩转为绩点
        }
        newnode->data.info.grapoint = compute_gpa(newnode);
        newnode->data.info.sort = sort_grap(newnode, L);
        insert(L, newnode);
        printf("添加学生成功,别忘了保存学生信息!");
    }
}
float compute_DKgpa(float score)
{
    return((score / 10) - 5 + ((int)score % 10) * 0.1);
}
float compute_gpa(linklist* newnode)
{
    double sum1 = 0;
    double sum2 = 0;
    for (int i = 0; i < 10; i++)
    {
        sum1 = sum1 + newnode->data.courses[i].credit;//计算学分总和
        sum2 = sum2 + newnode->data.courses[i].credit * newnode->data.courses[i].DKgrapoint;
    }
    return sum2 / sum1;
}
int sort_grap(linklist* p, linklist* L)
{
    int count1 = 0;
    int count2 = 0;
    linklist* q = L;
    while (q)
    {
        if (p->data.info.grapoint > (q->data.info.grapoint))
            count1++;
        q = q->next;
        count2++;
    }
    return count2 - count1 + 1;
}
void modify(linklist* L)
{
    int num;
    int flag;
    int choice;
    linklist* p;
    p = L;
    printf("请输入您要修改的学生的学号:\n");
    scanf_s("%d", &num);
    while (p->next)
    {
        if (p->data.info.id == num)
        {
            flag = 1;
            printf("请输入您要修改的信息选项:0.学号 1.姓名 2.性别 3.年龄 4.专业 5.各学科6.绩点 7.绩点排名 \n");
            scanf_s("%d", &choice);
            switch (choice)
            {
            case 0:
                printf("请输入您要修改的学号:");
                scanf_s("%d", &num);
                printf("修改的学号为:%d\n", num);
                p->data.info.id = num;
                printf("修改学号成功!\n");
                break;
            case 1:
                char name[50];
                printf("修改后的名字为:\n");
                scanf_s("%s", name, 50);
                strcpy_s(p->data.info.name, name);
                break;
            case 2:
                char sex[50];
                printf("请输入您要修改的性别");
                scanf_s("%s", sex, 50);
                strcpy_s(p->data.info.sex, sex);
                printf("修改性别成功!\n");
                break;
            case 3:
                int age;
                printf("请输入您要修改的年龄:");
                scanf_s("%d", &age);
                p->data.info.age = age;
                printf("修改年龄成功!\n");
                break;
            case 4:
                char major[50];
                printf("请输入您要修改的专业:");
                scanf_s("%s", major, 50);
                strcpy_s(p->data.info.major, major);
                printf("修改专业成功!");
                break;
            case 5:
                char course[50];
                printf("请输入你想修改的课程:\n");
                scanf_s("%s", course, 50);
                for (int i = 0; i < 10; i++)
                {
                    if (course == p->data.info.major)
                    {
                        printf("请输入你想要修改的课程信息的相关选项:0表示课程名1表示学分2表示补缓考状态3表示成绩(包含单科绩点)\n");
                        int num2;
                        scanf_s("%d", &num2);
                        switch (num2)
                        {
                        case 0:
                            char name2[50];
                            printf("请输入你要重新修改的课程名:");
                            scanf_s("%s", name2, _countof(name2));
                            strcpy_s(p->data.courses[i].name, name2);
                            break;
                        case 1:
                            float credit;
                            printf("请输入你想修改的学分为:\n");
                            scanf_s("%f", &credit);
                            p->data.courses[i].credit = credit;
                            break;
                        case 2:
                            int ismakeup;
                            printf("请输入该门课程的补缓考状态,0表示正常,1表示补缓考:\n");
                            scanf_s("%d", &ismakeup);
                            p->data.courses[i].ismakeup = ismakeup;
                            break;
                        case 3:
                            float score;
                            printf("请重新输入该门课程的成绩:\n");
                            scanf_s("%f", &score);
                            p->data.courses[i].score = score;
                            p->data.courses[i].DKgrapoint = compute_DKgpa(score);
                            printf("该门课程的绩点已经自动修改!");
                            break;
                        default:
                            printf("输入错误,请重新进行修改:\n");
                            break;
                        }
                    }
                }
                break;
            case 6:p->data.info.grapoint = compute_gpa(p);
                printf("该名学生的绩点已经修改成功:\n");
                break;
            case 7:
                printf("请修改该名学生的绩点排名:\n");
                p->data.info.sort = sort_grap(p, L);
                printf("修改绩点排名成功:\n");
                break;
            default:printf("请输入正确的选项:\n");
                break;
            }
        }
        p = p->next;
    }
    if (flag != 0)
        printf("该学生不存在:\n");
}
void remove(linklist* L)
{
    int num;
    int flag;
    printf("请输入您要删除的学生的学号:");
    scanf_s("%d", &num);
    linklist* pre = L;
    linklist* p = pre->next;
    while (p)
    {
        if (p->data.info.id == num)
        {
            flag = 1;
            pre->next = p->next;
            free(p);
            printf("成功删除学生!\n");
            break;
        }
        pre = p;
        p = p->next;
    }
    if (flag != 0)
        printf("这个学生不存在!\n");
}
void search(linklist* L)
{
    int num;
    int flag;
    printf("1.按学号查询:\n");
    printf("2.按姓名查询:\n");
    printf("请输入查询方式:");
    scanf_s("%d", &flag);
    if (flag == 1)
    {
        printf("请输入该学生的学号:");
        scanf_s("%d", &num);
        linklist* p = L;
        while (p != NULL)
        {
            if (p->data.info.id == num)
            {
                printf("学号:%d\n", p->data.info.id);
                printf("姓名:%s\n", p->data.info.name);
                printf("性别:%s\n", p->data.info.sex);
                printf("年龄:%d\n", p->data.info.age);
                printf("绩点:%f\n", p->data.info.grapoint);
                printf("绩点排名:%d\n", p->data.info.sort);
                printf("专业:%s\n", p->data.info.major);
                for (int i = 0; i < 10; i++)
                    printf("%s:  %f   绩点:%f\n", p->data.courses[i].name, p->data.courses[i].score, p->data.courses[i].DKgrapoint);
                break;
            }
            p = p->next;
        }
        if (p == NULL)
            printf("该学生不存在\n");
    }
    else
    {
        char name[60];
        printf("请输入该学生的姓名:");
        scanf_s("%s", name, 60);
        linklist* q = L->next;
        while (q)
        {
            if (q->data.info.name == name)
            {
                printf("学号:%d\n", q->data.info.id);
                printf("姓名:%s\n", q->data.info.name);
                printf("性别:%s\n", q->data.info.sex);
                printf("年龄:%d\n", q->data.info.age);
                printf("绩点:%f\n", q->data.info.grapoint);
                printf("绩点排名:%d\n", q->data.info.sort);
                printf("专业:%s\n", q->data.info.major);
                for (int i = 0; i < 10; i++)
                    printf("%s:  %f   绩点:%f\n", q->data.courses[i].name, q->data.courses[i].score, q->data.courses[i].DKgrapoint);
                break;
            }
            q = q->next;
        }
        if (!q)
            printf("该学生不存在\n");
    }
}
void save(linklist*& L)
{
    FILE* fp;
    linklist* p = L->next;
    if ((fp = fopen("student.txt", "w")) == NULL)
    {
        printf("不能打开此文件,请按任意键退出\n");
        exit(1); //异常退出
    }
    while (p)
    {
        struct Course {
            char name[20];
            double score;
            double credit;
            double DKgrapoint;
            int ismakeup;//用来区分补缓考
        };
        fprintf(fp, "%d %s %s %d %f %d %s\n", p->data.info.id, p->data.info.name, p->data.info.sex, p->data.info.age, p->data.info.grapoint, p->data.info.sort, p->data.info.major);
        for (int i = 0; i < 10; i++)
            fprintf(fp, "%s %f %f %f %d\n", p->data.courses[i].name, p->data.courses[i].score, p->data.courses[i].credit, p->data.courses[i].DKgrapoint, p->data.courses[i].ismakeup);
        p = p->next;
    }
    printf("保存成功:\n");
    fclose(fp);
}
void load(linklist*& L) {
    FILE* file = fopen("student.txt", "r");
    if (file == NULL) {
        printf("Error opening file: student.txt\n");
        return;
    }

    linklist* current = L;
    linklist* new_node;

    while (!feof(file)) {
        stu temp_student;
        char line[200];

        // 读取一行,直到遇到换行符或文件结束
        if (fgets(line, sizeof(line), file) == NULL) {
            break; // 如果读取失败,跳出循环
        }

        // 如果读取的是空行,继续下一轮循环
        if (line[0] == '\n') {
            continue;
        }

        // 解析每一行数据
        sscanf(line, "%s %d %s %d %s %f",
            temp_student.info.name, &temp_student.info.id,
            temp_student.info.sex, &temp_student.info.age,
            temp_student.info.major, &temp_student.info.sort);

        // 继续解析课程信息
        for (int i = 0; i < 10 && !feof(file); ++i) {
            if (fgets(line, sizeof(line), file) == NULL) {
                break; // 如果读取失败,跳出循环
            }
            if (line[0] == '\n') {
                continue;
            }

            sscanf(line, "%s %f %f %f %d",
                temp_student.courses[i].name,
                &temp_student.courses[i].score,
                &temp_student.courses[i].credit,
                &temp_student.courses[i].DKgrapoint,
                &temp_student.courses[i].ismakeup);
        }

        // 创建新节点并将数据复制进去
        new_node = (linklist*)malloc(sizeof(linklist));
        if (new_node == NULL) {
            printf("Memory allocation failed.\n");
            fclose(file);
            return;
        }
        memcpy(&new_node->data, &temp_student, sizeof(stu));
        new_node->next = NULL; // 初始化next指针为NULL

        // 将新节点添加到链表中
        if (L == NULL) {
            L = new_node;
            current = L; // 将current指针也指向头节点
        }
        else {
            current->next = new_node;
            current = current->next; // 更新current指针
        }
    }

    fclose(file);
}

```

  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-06-08 23:26
    关注

    引自免费微信小程序:皆我百晓生

    经过分析您的代码,我发现了一个可能导致问题的原因:在load()函数中,当读取文件时,没有正确地处理多个学生的数据。每次读取完一个学生的信息后,你应该跳过剩余的空行,直到下一个学生的信息开始。此外,在读取课程信息时,也应该有一个判断条件来检查是否已经读取到了所有学生的数据。

    下面是修复这个问题的代码。我已经对load()函数进行了修改,并添加了一些注释来解释关键部分的改动:

    void load(linklist*& L) {
        FILE* file = fopen("student.txt", "r");
        if (file == NULL) {
            printf("Error opening file: student.txt\n");
            return;
        }
    
        linklist* current = L;
        linklist* new_node;
    
        while (!feof(file)) {
            stu temp_student;
            char line[200];
    
            // 读取一行,直到遇到换行符或文件结束
            if (fgets(line, sizeof(line), file) == NULL) {
                break; // 如果读取失败,跳出循环
            }
    
            // 检查是否读取到了一个新的学生信息的开头
            if (strlen(line) > 0 && line[0] != '\n') {
                // 解析学生基本信息
                sscanf(line, "%s %d %s %d %s %f",
                    temp_student.info.name, &temp_student.info.id,
                    temp_student.info.sex, &temp_student.info.age,
                    temp_student.info.major, &temp_student.info.sort);
    
                // 继续解析课程信息
                for (int i = 0; i < 10 && !feof(file); ++i) {
                    if (fgets(line, sizeof(line), file) == NULL) {
                        break; // 如果读取失败,跳出循环
                    }
    
                    // 检查是否到达了下一个学生信息的开始
                    if (strlen(line) > 0 && line[0] != '\n') {
                        break; // 如果是新的学生信息,跳出当前学生信息的循环
                    }
    
                    // 解析课程信息
                    sscanf(line, "%s %f %f %f %d",
                        temp_student.courses[i].name,
                        &temp_student.courses[i].score,
                        &temp_student.courses[i].credit,
                        &temp_student.courses[i].DKgrapoint,
                        &temp_student.courses[i].ismakeup);
                }
    
                // 创建新节点并将数据复制进去
                new_node = (linklist*)malloc(sizeof(linklist));
                if (new_node == NULL) {
                    printf("Memory allocation failed.\n");
                    fclose(file);
                    return;
                }
                memcpy(&new_node->data, &temp_student, sizeof(stu));
                new_node->next = NULL; // 初始化next指针为NULL
    
                // 将新节点添加到链表中
                if (L == NULL) {
                    L = new_node;
                    current = L; // 将current指针也指向头节点
                }
                else {
                    current->next = new_node;
                    current = current->next; // 更新current指针
                }
            }
        }
    
        fclose(file);
    }
    

    这段修改后的代码应该可以解决您第二次运行时无法查询到信息的问题。现在,load()函数会正确地跳过每个学生之间的空行,并且在读取课程信息时,一旦遇到下一个学生的信息,就会停止读取当前学生的课程信息,从而确保不会在同一个学生上读取其他学生的数据。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 6月8日