Alex ander bro 2024-06-09 20:37 采纳率: 0%
浏览 7

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->next;
        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);
}
char name1[50];
int id;
char sex[30];
int age;
char major[50];
int sort;
float grapoint;
char name2[20];
float score;
float credit;
float DKgrapoint;
int ismakeup;//用来区分补缓考
void load(linklist*& L) {
    FILE* file = fopen("student.txt", "r");
    if (file == NULL) {
        printf("Error opening file: student.txt\n");
        return;
    }
    int i = 0;
    int j = 0;
    while (!feof(file))
    {
        char name1[50];
        int id;
        char sex[30];
        int age;
        char major[50];
        int sort;
        float grapoint;
        char name2[20];
        float score;
        float credit;
        float DKgrapoint;
        int ismakeup;//用来区分补缓考
        fscanf(file, "%s %d %s %d %s %d %f", name1, &id, sex, &age, major, &sort, &grapoint);
        for (i = 0; i < 10; i++)
        {
            fscanf(file, "%s %f %f %f %d", name2, &score, &credit, &DKgrapoint, &ismakeup);
        }
        j++;
    }
    fclose(file);
    FILE* fp;
    fp= fopen("student.txt", "w");
    int a = j- 1;
    int k = 1;
    while (!feof(fp))
    {
        fscanf(file, "%s %d %s %d %s %d %f", name1, &id, sex, &age, major, &sort, &grapoint);
        for (i = 0; i < 10; i++)
        {
            fscanf(file, "%s %f %f %f %d", name2, &score, &credit, &DKgrapoint, &ismakeup);
        }
        linklist*p= (linklist*)malloc(sizeof(linklist));
        p->data.info.id = id;
            strcpy(p->data.info.name ,name1);
            strcpy(p->data.info.sex, sex);
            p->data.info.age = age;
        p->data.info.grapoint = grapoint;
        p->data.info.sort = sort;
        strcpy(p->data.info.major, major);
        for (i = 0; i < 10; i++)
        {
            strcpy(p->data.courses[i].name, name2);
            p->data.courses[i].score = score;
            p->data.courses[i].credit = credit;
            p->data.courses[i].DKgrapoint = DKgrapoint;
            p->data.courses[i].ismakeup = ismakeup;
        }
        insert(L, p);
        p = p->next;
        if (k == a)
            break;
        k++;
    }
    fclose(fp);
}


  • 写回答

2条回答 默认 最新

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

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

    从你提供的代码来看,主要的问题在于load函数的实现有误,以及数据结构和文件读写处理上的一些不当之处。下面我会详细分析并提供修正方案。

    load函数问题解析与修正

    原始问题

    你的load函数在尝试从文件中读取数据时,存在几个关键问题:

    1. 文件读取循环条件设置不正确,使用!feof(file)通常不是一个好的实践,因为feof仅在调用读取函数失败或到达文件末尾后才返回非零值。
    2. 在循环中,你重复定义了多个局部变量,这会导致每次循环都覆盖前一次的数据,最终只读取文件的最后一行数据。
    3. 尝试在load函数内部同时读写文件,这不仅逻辑混乱,而且文件fp未被正确初始化就用于读取,导致后续操作无效。

    修改建议

    首先,将读取和写入分开,确保在load函数中只专注于读取数据,并且在文件读取过程中使用更可靠的方法检测文件结束,如检查fscanf的返回值。然后,在读取数据后,使用这些数据创建新的stu对象,并将其插入链表。

    修改代码

    void load(linklist*& L) {
        FILE* file = fopen("student.txt", "r");
        if (file == NULL) {
            printf("Error opening file: student.txt\n");
            return;
        }
    
        // 清空链表
        while (L->next) {
            linklist* temp = L->next;
            L->next = temp->next;
            free(temp);
        }
    
        while (fscanf(file, "%d %[^ ] %[^ ] %d %[^ ] %d %f", 
                      &id, name1, sex, &age, major, &sort, &grapoint) == 7) {
            linklist* newNode = (linklist*)malloc(sizeof(linklist));
            newNode->data.info.id = id;
            strcpy(newNode->data.info.name, name1);
            strcpy(newNode->data.info.sex, sex);
            newNode->data.info.age = age;
            newNode->data.info.grapoint = grapoint;
            newNode->data.info.sort = sort;
            strcpy(newNode->data.info.major, major);
    
            for (int i = 0; i < 10; i++) {
                if (fscanf(file, "%[^ ] %f %f %f %d", 
                           name2, &score, &credit, &DKgrapoint, &ismakeup) == 5) {
                    strcpy(newNode->data.courses[i].name, name2);
                    newNode->data.courses[i].score = score;
                    newNode->data.courses[i].credit = credit;
                    newNode->data.courses[i].DKgrapoint = DKgrapoint;
                    newNode->data.courses[i].ismakeup = ismakeup;
                } else {
                    // Error reading course data, handle appropriately
                    break;
                }
            }
            insert(L, newNode);
        }
    
        fclose(file);
    }
    

    其他注意事项

    1. 内存泄漏:在add函数中,insert函数调用后未释放p指针指向的空间,可能导致内存泄漏。
    2. 字符串比较:在search函数中,使用==比较字符串是不正确的,应使用strcmp函数。
    3. 文件读写save函数中的fprintf语句格式化字符串可能需要调整,以匹配实际数据类型。

    通过以上修改,你的程序应该能更稳定地处理数据存储和检索。如果你还有其他具体问题,欢迎继续询问。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 6月9日