C语言实现学生管理系统

近些天有上机实验,所以要完成学生管理系统,以前只用python写过,这一次用链表和文件操作实现具有记忆功能的学生管理系统。

# include <stdio.h>
# include <stdlib.h>
# include <malloc.h>
# include <string.h>
typedef struct
{
    char name[20];
    long num;  // 学号
    float subjectScore[3];  // math Chinese English
    float sum;  //总分
}Stu;


struct Node
{
    Stu data;  // 数据域
    struct Node* next;
};



// 储存结构:链表
// 1.创建链表
struct Node* createList()
{
    struct Node* headNode = (struct Node*)malloc(sizeof(struct Node));
    headNode->next = NULL;
    return headNode;
}

// 2.创建节点
struct Node* createNode(Stu data)
{
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;

}

// 3.打印数据
void printList(struct Node* headNode)
{
    struct Node* pMove = headNode->next;
    printf("******************************************\n");
    printf("name\tnum\tmath\tChinese\tEnglish\n");
    while (pMove)
    {
        printf("%s\t%ld\t%5.1f\t%5.1f\t%5.1f\n", pMove->data.name, pMove->data.num, pMove->data.subjectScore[0],pMove->data.subjectScore[1], pMove->data.subjectScore[2]);
        pMove = pMove->next;
    }
    printf("******************************************\n");
    printf("\n");

}

// 4.1插入节点(头插法),插入哪一个链表,插入数据
void insertNodeByHead(struct Node* headNode, Stu data)
{
    // 1.创建插入节点
    struct Node* newNode = createNode(data);
    newNode->next = headNode->next;
    headNode->next = newNode;

}

// 4.2插入节点(尾插法)
void insertNodeByTail(struct Node* headNode, Stu data)
{
    struct Node* newNode = createNode(data);
    struct Node* t = createNode(data);  // 转换量
    for(t = headNode; t->next; t=t->next); //结束时t指向尾节点
    newNode->next = NULL; //进行插入
    t->next = newNode;

}

// 5.删除节点
void deleteNodeByAppoinNum(struct Node* headNode)
{
    long num;
    printf("请输入要删除的学号:\n");
    scanf("%ld", &num);
    struct Node* posNode = headNode->next;
    struct Node* posNodeFront = headNode;
    if (posNode == NULL)
    {
        printf("无法删除链表为空\n");
    }
    else
    {
        while (posNode->data.num != num)
        {
            posNodeFront = posNode;
            posNode = posNodeFront->next;
            if (posNode == NULL)
            {
                printf("未找到指定位置,无法删除\n");
                return;
            }
        }
        posNodeFront->next = posNode->next;
        free(posNode);
        printf("已删除!\n");

    }


}


// 菜单功能
// 1.信息输入
void input (struct Node* headNode)
{
    Stu info;
    printf("请输入学生姓名:\n");
    scanf("%s", info.name);
    printf("请输入学号:\n");
    scanf("%ld", &info.num);
    printf("请输入数学成绩:\n");
    scanf("%f", &info.subjectScore[0]);
    printf("请输入语文成绩:\n");
    scanf("%f", &info.subjectScore[1]);
    printf("请输入英语成绩:\n");
    scanf("%f", &info.subjectScore[2]);
    insertNodeByHead(headNode, info);
    printf("已经添加成功!\n");
    printList(headNode);
}

// 2.总分统计
void count(struct Node* headNode)
{
    struct Node* pMove = headNode->next;
    while(pMove)
    {
        pMove->data.sum = pMove->data.subjectScore[0] + pMove->data.subjectScore[1] + pMove->data.subjectScore[2];
        pMove = pMove->next;
    }
    pMove = headNode->next;
    printf("已统计完成,如下:\n");
    printf("******************************************\n");
    printf("name\tsum\n");
    while (pMove)
    {
        printf("%s\t%5.1f\n", pMove->data.name, pMove->data.sum);
        pMove = pMove->next;

    }
    printf("******************************************\n");
    printf("\n");
}
// 3.总分排序
void sort(struct Node* headNode)
{
    Stu temp;
    struct Node* pMove1 = headNode->next;    // 冒泡
    struct Node* pMove2 = headNode->next;
    while (pMove1)
    {
        while(pMove2->next)
        {
            if (pMove2->data.sum < pMove2->next->data.sum)
            {
                temp = pMove2->data;
                pMove2->data = pMove2->next->data;
                pMove2->next->data = temp;
            }
            pMove2 = pMove2->next;
        }
        pMove1 = pMove1->next;
        pMove2 = headNode->next;
    }
    pMove1 = headNode->next;
    printf("已排序完成,如下:\n");
    printf("******************************************\n");
    printf("name\tsum\n");
    while (pMove1)
    {
        printf("%s\t%5.1f\n", pMove1->data.name, pMove1->data.sum);
        pMove1 = pMove1->next;

    }
    printf("******************************************\n");
    printf("\n");

}

// 4.用学号查询学生
void query1(struct Node* headNode)
{
    long num;
    struct Node* pMove = headNode->next;
    printf("请输入学号:");
    scanf("%ld", &num);
    while (pMove)
    {
        if (pMove->data.num == num)
        {
            printf("******************************************\n");
            printf("name\tnum\tmath\tChinese\tEnglish\n");
            printf("%s\t%ld\t%5.1f\t%5.1f\t%5.1f\n", pMove->data.name, pMove->data.num, pMove->data.subjectScore[0],pMove->data.subjectScore[1], pMove->data.subjectScore[2]);
            printf("******************************************\n");
            return;
        }
        pMove = pMove->next;
    }
    printf("没有此同学!\n");

}



// 5.查询分数段学生
void query2(struct Node* headNode)
{
    char subjectName[20];
    struct Node* pMove = headNode->next;
    float begin, end;
    printf("请输入要查询的课程名(math or Chinese or English):\n");
    getchar();
    gets(subjectName);
    printf("请输入要查询的分数段(xx,xx):\n");
    setbuf(stdin, NULL);  // 清楚缓存,处理跳步
    scanf("%f,%f", &begin, &end);
    if (!strcmp("math", subjectName))
    {
        printf("******************************************\n");
        printf("name\tmath\n");
         while(pMove)
        {

            if (pMove->data.subjectScore[0]>=begin && pMove->data.subjectScore[0] <= end)
            {
                printf("%s\t%5.1f\n", pMove->data.name, pMove->data.subjectScore[0]);
            }
            pMove = pMove->next;
        }
        printf("******************************************\n");
    }
    else if (!strcmp("Chinese", subjectName))
    {
        printf("******************************************\n");
         printf("name\tChinese\n");
         while(pMove)
        {
            if (pMove->data.subjectScore[1]>=begin && pMove->data.subjectScore[1] <= end)
            {
                printf("%s\t%5.1f\n", pMove->data.name, pMove->data.subjectScore[1]);
            }
            pMove = pMove->next;
        }
        printf("******************************************\n");
    }
    else if (!strcmp("English", subjectName))
    {
        printf("******************************************\n");
        printf("name\tEnglish\n");
         while(pMove)
        {
            if (pMove->data.subjectScore[2]>=begin && pMove->data.subjectScore[2] <= end)
            {
                printf("%s\t%5.1f\n", pMove->data.name, pMove->data.subjectScore[2]);
            }
            pMove = pMove->next;
        }
        printf("******************************************\n");
    }
    else
    {
        printf("您的科目名称输入有误!\n");
    }

}

// 8.保存链表信息到文件中
void saveStuData(struct Node* headNode)
{
    struct Node* pMove = headNode->next;
    FILE* fp;
    if((fp=fopen("D:/student.txt","w"))==NULL)// 以可写的方式打开当前目录下的.txt
    {
        printf("不能打开此文件,请按任意键退出\n");
        exit(1);  //异常退出
    }
    while (pMove)
    {
        fprintf(fp, "%s %ld %5.1f %5.1f %5.1f\n",pMove->data.name, pMove->data.num, pMove->data.subjectScore[0], pMove->data.subjectScore[1], pMove->data.subjectScore[2]);
        pMove = pMove->next;
    }
    printf("保存成功!\n");
    fclose(fp);

}

 //运行前把文件内容读取到链表中
void readStuData(struct Node* headNode)
{
    Stu stu1;
    FILE *fp;
    fp = fopen("D:/student.txt","r");
    if (fp == NULL)
    {
        printf("文件不存在!\n");
        exit(0);
    }
    // 判断文件是否为空
    getc(fp);  // 让光标移动一个字符
    if (feof(fp))
    {
        fclose(fp);
        return;
    }
    else
    {
        rewind(fp); // 使光标初始化在开头
        while (!feof(fp))
        {
            fscanf(fp, "%s %ld %f %f %f\n",stu1.name, &stu1.num, &stu1.subjectScore[0], &stu1.subjectScore[1], &stu1.subjectScore[2]);
            // 尾插法插入数据
            insertNodeByTail(headNode, stu1);
        }
    }
    fclose(fp);
}
int main()
{
    char choice = 'a';
    struct Node* list = createList();
//    Stu info = {"Tom",1001, {20,60,10}};
    readStuData(list);
    while (choice != '0')
    {
        printf("--------------成绩管理系统----------------\n");
        printf("(1):信息输入(INPUT)\n");
        printf("(2):总分统计(COUNT)\n");
        printf("(3):总分排序(SORT)\n");
        printf("(4):查询(QUERY)\n");
        printf("(5):课程分数段查询(QUERY)\n");
        printf("(6):删除学生信息(DELETE)\n");
        printf("(7):显示全部(SHOWALL)\n");
        printf("(8):保存当前学生信息(SAVEDATA)\n");
        printf("------------------------------------------------\n");
        printf("说明 :请先完成统计再进行排序\n");
        printf("(0):退出(EXIT)\n");
        printf("请选择<0~8>:\n");
        scanf(" %c", &choice);
        switch (choice)
        {
           case '1':
                input(list);
                break;
           case '2':
               count(list);
               break;
           case '3':
             sort(list);
             break;
           case '4':
             query1(list);
             break;
           case '5':
             query2(list);
             break;
           case '6':
            deleteNodeByAppoinNum(list);
           case '7':
            printList(list);
            break;
           case '8':
            saveStuData(list);
            break;
            break;
           default:
             break;
        };
    }
    return 0;

}

其中最让我难忘的是文件操作和循环输入scanf输入单个字符, 这两个废了不少时间,文件操作先不说,scanf循环时有跳步现象,然后加上setbuf(stdin,NULL)关闭缓存区后,再输入字符串,字符串是中文时会出现个别字体消失现象,看了网上的许多博客用fflush清楚缓存并没有好的解决,最后看了以为大神的博客,只需要不加setbuf,使前面的scanf括号中的“%c”百分号前面加一个空格即可,即scanf(" %c", choice),详细请看代码。

好了,本人实属入门级C语言的大学生,如有不对之处,欢迎留言批正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖色的杯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值