美文网首页
[C/C++] _ 结构体,链表,文件应用-简单学生成绩管理系统

[C/C++] _ 结构体,链表,文件应用-简单学生成绩管理系统

作者: 葛木小舍先生丶 | 来源:发表于2019-12-30 19:44 被阅读0次

    简单复习下C语言基础知识,使用单链表,结构体嵌套,文件读写信息,实现控制台简单学生成绩管理系统.

    源码

    • 枚举类型
    #include<stdio.h>
    #include <stdlib.h>
    #include <string>
    
    enum CONMMAND
    {
        SAVEANDQUIT, ADD, MODIFY, INUIRY, DELETE, BROWSE
    };
    
    
    • 相关结构体与单链表结构体
    struct Results
    {
        int math;
        int language;
        int english;
        int computer;
    };
    struct Student
    {
        char s_StuId[10]; // 学号
        char s_Name[10]; // 姓名
        char s_IDcard[20]; // 身份证号
        char s_DateBirth[20]; // 出生日期
        int s_Age; // 年龄
        char s_Gender[3]; // 性别
        Results re; // 各科成绩
        float s_result; // 成绩
        int s_rank = 1; // 排名
        char s_Finalassess[10] = ""; // 最终评价
    };
    struct StudentLinklist
    {
        Student stu; // 数据域
        StudentLinklist* next;  // 指针域
    };
    
    
    • 全局操作指令与文件路径
    int nConmmand;
    const char* file = "E:\\student\\saveLinklist.bin";
    
    • 简单的显示菜单,以及录入信息函数
    // 菜单
    void  MenuFirst(int* nConmmand) {
        printf("\n\n\n\t\t\t\t++#@%=================学生成绩管理系统=================%@#++\n\n\n");
        printf("\t\t\t\t\t1.添加学生成绩信息\t2.修改学生成绩信息\n\t\t\t\t\t3.查询学生成绩信息\t4.删除学生成绩信息\n\t\t\t\t\t5.浏览学生成绩信息\t0.保存并退出系统\n");
        printf("\n\n\t\t\t\t++#@%=================学生成绩管理系统=================%@#++\n");
        printf("请输入你的指令(0-6):\n");
        scanf_s("%d", nConmmand);
    }
    // 录入学生信息.
    Student mScanfstudent() {
        Student stu;
        printf("请输入学生基本信息:\n");
        printf("学号\t姓名\t身份证号\t出生日期\t年龄\t性别\n");
        scanf("%s\t%s\t%s\t%s\t%d\t%s", stu.s_StuId, stu.s_Name, stu.s_IDcard, stu.s_DateBirth, &stu.s_Age, stu.s_Gender);
        printf("请输入学生基本成绩信息:\n");
        printf("数学\t语文\t英语\t计算机课程设计\n");
        scanf("%d\t%d\t%d\t%d", &stu.re.math, &stu.re.language, &stu.re.english, &stu.re.computer);
        stu.s_result = (stu.re.computer + stu.re.english + stu.re.language + stu.re.math) / 4;
        return stu;
    }
    
    • 链表的各种操作函数
    // 创建节点
    StudentLinklist* mcretelink() {
        StudentLinklist* H = (StudentLinklist*)malloc(sizeof(StudentLinklist));
        if (!H)
        {
            printf("创建失败");
            getchar();
            exit(0);
        }
        else { // 初始化
            H->next = NULL;
        }
        return H;
    }
    
    // 遍历返回链表长度
    int mGetLinklist(StudentLinklist* stulink) {
        StudentLinklist* temp = stulink;
        int nLen = 0;
        while (temp)
        {
            temp = temp->next;
            nLen++;
        }
        return nLen;
    }
    
    // 在尾部插入stu信息.
    void minsertend(StudentLinklist* stulink, Student stu) {
        StudentLinklist* temp = stulink;
        while (temp->next != NULL)
        {
            temp=temp->next;
        }
        StudentLinklist* s = mcretelink();
        s->stu = stu;
        s->next = temp->next;
        temp->next = s;
    }
    
    
    • 链表遍历操作函数(各种增,删,改,查等操作)
    // 遍历输出链表
    void mPrintlinklist(StudentLinklist* stulink) {
        StudentLinklist* temp = stulink->next;
        Student stu;
        printf("学号\t姓名\t身份证号\t\t出生日期\t年龄\t性别\t综合成绩\t排名\t总评\n");
        while (temp!= NULL)
        {
            stu = temp->stu;
            printf("%s\t%s\t%s\t%s\t%d\t%s\t%.1f\t\t%d\t%s\n", stu.s_StuId, stu.s_Name, stu.s_IDcard, stu.s_DateBirth, stu.s_Age, stu.s_Gender, stu.s_result, stu.s_rank, stu.s_Finalassess);
            temp = temp->next;
        }
    }
    
    //遍历设置总评成绩
    bool mSetFinalassess(StudentLinklist* stulnk) {
        StudentLinklist* temp = stulnk;
        if (temp == NULL)
        {
            return 0;
        }
        while (temp)
        {
            if (60.0 <= temp->stu.s_result && temp->stu.s_result < 70.0)
            {
                strcpy(temp->stu.s_Finalassess, "合格");
            }
            else if (70.0 <= temp->stu.s_result && temp->stu.s_result< 90.0) {
                strcpy(temp->stu.s_Finalassess, "优良");
            }
            else if (90.0 <= temp->stu.s_result) {
                strcpy(temp->stu.s_Finalassess, "优秀");
            }
            else {
                strcpy(temp->stu.s_Finalassess, "不合格");
            }
            temp = temp->next;
        }
    }
    // 遍历排序.
    void mSort(StudentLinklist* stulinklist) {
        StudentLinklist* temp = stulinklist->next;
        Student p;
        if (!temp) {
            printf("信息为空\n");
        }
        else {
            while (temp->next != NULL)
            {
                if (temp->stu.s_result < temp->next->stu.s_result)
                {
                    p = temp->stu;
                    temp->stu = temp->next->stu;
                    temp->next->stu = p;
                }
                temp = temp->next;
            }
        }
    }
    // 遍历设置排名
    void mSetrank(StudentLinklist* stulinklist) {
        StudentLinklist* temp = stulinklist;
        int i = 0;
        while (temp)
        {
            temp->stu.s_rank = i;
            i++;
            temp = temp->next;
        }
    }
    //遍历查询通过学号
    Student mInquire(StudentLinklist* stulinklist,char* stuid) {
        StudentLinklist* temp = stulinklist;
        Student stu;
        while (temp)
        {
            if (strcmp(temp->stu.s_StuId,stuid)==0)
                break;
            else
            temp = temp->next;
        }
        stu = temp->stu;
        return stu;
    }
    // 删除指定元素
    bool mDelete(StudentLinklist* stulinklist,char* stuid){
        StudentLinklist* temp=stulinklist;
        while (temp->next)
        {
            if (strcmp(temp->next->stu.s_StuId, stuid) == 0)
                break;
            else
                temp = temp->next;
        }
        // 创建一个新节点
        StudentLinklist* s = mcretelink();
        // 使s指向第i个位置(要删除的位置)
        s = temp->next;
        //用stu参数暂时保存即将删除的数据.
        //让temp.next指向i后面的一位.
        temp->next = s->next;
        //删除节点,释放掉s指向的第i个位置的节点空间
        free(s);
        return 1; //删除成功
    }
    // 修改指定元素
    bool mModify(StudentLinklist* stulinklist,char* stuid,Student stu){
        StudentLinklist* temp = stulinklist;
        while (temp)
        {
            if (strcmp(temp->stu.s_StuId, stuid) == 0)
                break;
            else
                temp = temp->next;
        }
        temp->stu = stu;
        return 1;
    }
    
    • 文件读写函数(将链表数据写入文件,与将文件的数据读入到链表中).
      读写模式采用覆盖,所有数据只存入一条链表.
    // 文件是无法保存一个链表指针域的.只能按数据块来保存.所以需要单独将链表
    // 的数据域存进文件,读取的时候再创建链表初始化即可.
    // 将链表数据写入文件..
    bool mWriteLinklist(const char* file,StudentLinklist* stulinklist) {
        FILE* fp;
        StudentLinklist* temp = stulinklist->next;
        fp = fopen(file, "rb+");
        if (!fp)
        {
            return 0;
        }
        else {
            // 将链表中的所有节点的数据域存放进文件中
            while (temp)
            {
                fwrite(&temp->stu, sizeof(Student), 1, fp);
                temp = temp->next;
            }
            return 1;
        }
    }
    
    // 读取文件中的数据到linklist中
    bool mReadlinklist(const char* file,StudentLinklist* stulinklist) {
        FILE* fp;
        Student stu;
        fp = fopen(file, "rb+");
        if (!fp)
        {
            printf("打开失败");
            exit(1);
            return 0;
        }
        else {
    
            while (fread(&stu,sizeof(Student),1,fp))
            {
                StudentLinklist* s = mcretelink();
                s->stu = stu;
                s->next =stulinklist ->next;
                stulinklist->next = s;
            }
            return 1;
        }
    }
    
    
    • 主函数
    int main()
    {
        // 先读取文件,将链表取出.
        StudentLinklist* stulinklist = mcretelink(); // 全局链表,只对它操作.
        if (!mReadlinklist(file, stulinklist))
        {
            printf("读取文件失败");
        }
        char stuid[10]; //学号
        Student stu; // 学生
        char a;
    
        while (1) {
            MenuFirst(&nConmmand);
            switch (nConmmand)
            {
            case ADD: // 添加
                stu = mScanfstudent();
                minsertend(stulinklist,stu);
                system("cls");
                break;
            case MODIFY: // 修改
                printf("请输入要修改的学生的学号:");
                scanf("%s", stuid);
                 stu = mScanfstudent();
                if (mModify(stulinklist, stuid, stu))
                {
                    printf("修改成功");
                }           
                system("cls");
                break;
            case INUIRY: // 查询
                printf("请输入查询学号:");
                scanf("%s", stuid);
                stu = mInquire(stulinklist, stuid); 
                printf("%s\t%s\t%s\t%s\t%d\t%s\t%.1f\t\t%d\t%s\n", stu.s_StuId, stu.s_Name, stu.s_IDcard, stu.s_DateBirth, stu.s_Age, stu.s_Gender, stu.s_result, stu.s_rank, stu.s_Finalassess);       
                system("cls");
                break;
            case DELETE: // 删除
                printf("请输入要删除学生的学号:");
                scanf("%s", stuid);
                if (mDelete(stulinklist, stuid)) {
                    printf("删除成功");
                }
                system("cls");
                break;
            case BROWSE: // 浏览
                mSetFinalassess(stulinklist); // 设置总评
                mSort(stulinklist); // 遍历判断,按成绩排序
                mSetrank(stulinklist); // 遍历设置排名
                mPrintlinklist(stulinklist); // 遍历输出链表.
                break;
            case SAVEANDQUIT:  // 保存
                mSetFinalassess(stulinklist); //设置总评
                mSort(stulinklist); // 遍历判断,按成绩排序
                mSetrank(stulinklist);  //遍历设置排名
                if (mWriteLinklist(file, stulinklist)) //判断写入是否成功,并退出程序.
                {
                    printf("保存成功");
                }
                exit(0);
                break;
            default:
                break;
            };
        }
    }
    

    图片.png 图片.png

    当然,时间仓促,系统很简陋,还有很多可以完善和改进的地方.只是重点回顾了一下指针,链表,结构体,文件的一些常用操作.至于读写excel表格文件(格式化存储),实现条件判断自动分发邮件(网络编程,sokect套接字,smtp协议).等技术,之后有时间再写吧.


    2019.12.30日.

    相关文章

      网友评论

          本文标题:[C/C++] _ 结构体,链表,文件应用-简单学生成绩管理系统

          本文链接:https://www.haomeiwen.com/subject/ayomoctx.html