美文网首页
[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