• 学生管理系统(C 大一期末作业)


    头文件

    #ifndef __studentSystem_h__
    #define __studentSystem_h__
    
    #include<stdio.h>
    #include<conio.h>
    #include<stdlib.h>
    #include<string.h>
    
    //定义学生信息的结构体
    typedef struct _student
    {
        char name[20]; //姓名
        int age; // 年龄
        int ID; //学号
        int score; //分数
    
    } Student;
    //定义指向学生数据节点的指针结构体
    typedef struct _node
    {
        Student stu; //结构体中的结构体
        struct _node* pnext; // 指向下一个结构体的指针
    } Node;
    
    //定义头指针
    Node* phead = NULL;
    
    void welcome(void);
    void inputStudent(void);
    void printStudent(void);
    void saveStudent(void);
    void readStudent(void);
    void countStudent(void);
    Node* findStudent(void);
    void modifyStudent(void);
    void deleteStudent(void);
    
    
    #endif

    代码部分

    #include"studentSystem.h"
    
    int main(void)
    {
        //做一个死循环
        while (1)
        {
            //调用了welcome函数
            welcome();
            //这里getch,只要输入一个字符就可以,并不需要按回车
            char ch = _getch();
            //根据不同的数字,来选则不同的程序
            switch (ch)
            {
                //录入学生信息
            case '1':
                inputStudent();
                break;
                //打印学生信息
            case '2':
                printStudent();
                break;
                //保存学生信息
            case '3':
                saveStudent();
                break;
                //读取学生信息
            case '4':
                readStudent();
                break;
                //统计所有学生人数
            case '5':
                countStudent();
                break;
                //查找学生人数
            case '6':
            {
                //函数的返回值是一个指针
                Node* p = findStudent();
                if (p == NULL)
                {
                    printf("没有找到!
    ");
                }
                else
                {
                    system("cls"); // 清屏
                    //如果返回值不为空,那么打印节点的信息
                    printf("学号:	%d	姓名:	%s	年龄:	%d	成绩:	%d	
    ", p->stu.ID, p->stu.name, p->stu.age, p->stu.score);
                }
                system("pause"); //暂停
                system("cls"); // 清屏
    
                break;
            }    //修改学生人数
            case '7':
                modifyStudent();
                break;
                //删除学生信息
            case '8':
                deleteStudent();
                break;
                //退出系统
            case '9':
            {
                printf("感谢适用本系统
    ");
                system("pause"); //暂停
                system("cls"); // 清屏
    
                //这里就直接返回到了main函数
                return 0;
            }
            default:
                //如果用户输入的是乱七八糟的字符
            {
                printf("请重新输入
    ");
                system("pause"); //暂停
                system("cls"); // 清屏
                break;
            }
    
            }
        }
        return 0;
    }
    
    
    void welcome()
    {
        printf("************************************
    ");
        printf("		欢迎使用学生管理系统		
    ");
        printf("*************************************
    ");
        printf("		请选择功能列表		
    ");
        printf("***************************************
    ");
        printf("*		1、录入学生信息		*
    ");
        printf("*		2、打印学生信息		*
    ");
        printf("*		3、保存学生信息		*
    ");
        printf("*		4、读取学生信息		*
    ");
        printf("*		5、统计所有学生人数	*
    ");
        printf("*		6、查找学生信息		*
    ");
        printf("*		7、修改学生信息		*
    ");
        printf("*		8、删除学生信息		*
    ");
        printf("*		9、退出系统		*
    ");
        printf("***************************************
    ");
    
    }
    
    void inputStudent()
    {
        //创建一个新节点
        Node* pnewNode = (Node*)malloc(sizeof(Node));
        pnewNode->pnext = NULL; //将节点内部的指针设置为空
    
        //输入基本的信息,注意这里的scanf 是scanf_s,这是最新的表示方法。
        printf("请输入姓名:
    ");
        scanf_s("%s", pnewNode->stu.name, 20); //输入姓名
        printf("请输入学生的年龄:
    ");
        scanf_s("%d", &pnewNode->stu.age); //输入年龄,注意这里要输入&
        printf("请输入学生的学号:
    ");
        scanf_s("%d", &pnewNode->stu.ID); //输入学生的序号
        printf("请输入学生的成绩:
    ");
        scanf_s("%d", &pnewNode->stu.score); // 输入学生的成绩
    
        printf("学生信息录入成功
    ");
        system("pause"); //暂停
        system("cls"); // 清屏
    
    
    
    
    
        //将头文件中的做为全局变量的头节点,连接到这个新创建的节点
        if (phead == NULL)
        {
            //将新节点连接到头结点
            phead = pnewNode;
        }
        else
        {
            //注意: 这里是不断的在头结点往前插入新的节点,同以前的方法不一样
            pnewNode->pnext = phead; //将新节点插在头结点的前面
            phead = pnewNode; //移动头结点到最前面
    
        }
    
    
    }
    
    //打印学生信息
    void printStudent()
    {
        //首先清楚前面的关于表格的基本信息
        system("cls");
        //打印头部的基本信息
        printf("***************************************
    ");
        printf("*	学号	*	姓名	*	年龄	*	成绩	*
    ");
        printf("***************************************
    ");
        //遍历链表
        //首先定义一个新的指针,这个指针同头指针是一样的。
        Node* p = phead;
        //通过循环遍历链表
        while (p != NULL)
        {
            printf("*	%d	*	%s	*	%d	*	%d	*
    ", p->stu.ID, p->stu.name, p->stu.age, p->stu.score);
            //将p指针往后挪一个位置,一直到最后一个指针位置,因为最后一个节点的包含的指针为空。
            p = p->pnext;
    
        }
        system("pause"); //暂停
        system("cls"); // 清屏
    
    
    }
    
    //保存学生信息
    void saveStudent()
    {
    
        //打开文件,注意当使用fopen_s时这么写
        FILE* fp;
        //定义了一个返回的int类型,当文件打开正确时,返回1,否则返回0
        int nu;
        //注意这里的fopen_s 里面的指正前面带有取地址符号,而在fopen函数中,则没有取地址符号
        nu = fopen_s(&fp, "C:\users\mike1\desktop\studentInformation.dat", "w");
        //在c语言中0代表成功,非0代表错误。
        if (nu == 1)
        {
            printf("打开文件失败!
    ");
        }
        //创建一个与头结点一样的节点
        Node* pp = phead;
        //一直从头结点开始遍历,直到遍历完整个列表
        while (pp != NULL)
        {
            fwrite(&pp->stu, 1, sizeof(Student), fp);
            //向下移动头结点
            pp = pp->pnext;
    
        }
    
        //关闭文件
        fclose(fp);
        printf("保存文件成功!
    ");
        system("pause"); //暂停
        system("cls"); // 清屏
    }
    
    void readStudent()
    {
        //首先定义一个文件指针
        FILE* fp;
        int er;
        //这是打开文件的新的写法,er 返回0或者1
        //但是实际情况是,当文件打不开时,根本不会进行到if语句。
        er = fopen_s(&fp, "C:\users\mike1\desktop\studentInformation.dat", "rb");
        if (er == 1)
        {
            printf("打开文件失败!
    ");
            return;
        }
        //读取文件,如果打开的没有到最后.
        //这是判断文件是否是空文件的另一种方式,先判断能不能正确读取所需要的字节,如果不可以,则不执行此循环
        //首先定义了一个节点
        Student stu1;
        //然后将内容先存放在前面的节点中,因为新节点是后定义的,所以如果直接将内容放在新节点,会出现,没有定义。
        while (fread(&stu1, 1, sizeof(Student), fp)) //里面的函数会返回读取的字节数
        {
            //   int c;
               //c = fgetc(fp);
               ////注意此时,当feof返回1时,表示错误,即文件是空文件,这和while的逻辑正好相反。
               //if (feof(fp))
               //{
               //    break;
               //}
    
               //创建一个新的节点,并且将读到的数据保存在新节点中,并由此创建一个链表
            Node* pp = (Node*)malloc(sizeof(Node));
    
            //将stu里面的内容复制给新创造的节点,后面表示复制的字节数
            memcpy(&pp->stu, &stu1, sizeof(Student));
            //将新节点的指针设置为空
            pp->pnext = NULL;
    
            //将头文件中的做为全局变量的头节点,连接到这个新创建的节点,这是在构建一个链表
            if (phead == NULL)
            {
                //将新节点连接到头结点
                phead = pp;
            }
            else
            {
                //注意: 这里是不断的在头结点往前插入新的节点,同以前的方法不一样
                pp->pnext = phead; //将新节点插在头结点的前面
                phead = pp; //移动头结点到最前面
    
            }
    
    
        }
    
        fclose(fp);
        printf("数据加载成功!
    ");
        system("pause"); //暂停
        system("cls"); // 清屏
    }
    
    //统计所有学生人数
    void countStudent()
    {
        //这里用的是全局变量的头结点
        //初始化学生总数
    
        int count = 0;
        //一个与头结点一样的节点
        Node* pp = phead;
        //不断遍历节点
        while (pp != NULL)
        {
    
            count++;
            pp = pp->pnext;
        }
        //打印学生总人数
        printf("学生总人数为:%d
    ", count);
        system("pause"); //暂停
        system("cls"); // 清屏
    
    }
    
    //查找学生信息
    Node* findStudent()
    {
        //定义基本变量
        char stuName[10];
        int stuNum;
        printf("请输入要查找的学生姓名:
    ");
        //在输入字节时,用最细的scanf表示方法
        scanf_s("%s", stuName, 10);
        printf("请输入要查找到的学生的学号:
    ");
        scanf_s("%d", &stuNum);
        //定义一个与头结点相同的指针
        Node* p = phead;
        //循环遍历节点
        while (p != NULL)
        {
            //strcmp 表示比较两个字符串,如果相同则返回0, 不相同则返回1
            if (stuNum == p->stu.age || 0 == strcmp(p->stu.name, stuName))
            {
                //返回这个节点
                return p;
            }
            p = p->pnext;
        }
        //此时p为空节点
        return p;
    }
    
    //修改学生信息
    void modifyStudent()
    {
        //定义基本的变量
        int nu;
        printf("请输入要修改的学生的学号:
    ");
        scanf_s("%d", &nu);
    
        //定义一个与头结点相同的指针
        Node* p = phead;
        //循环遍历节点
        while (p != NULL)
        {
            //如果找到了这个节点
            if (nu == p->stu.ID)
            {
    
                printf("请输入要修改的 姓名 年龄 成绩
    ");
                //实验证明可以这么连着写
                scanf_s("%s%d%d", p->stu.name, 20, &p->stu.age, &p->stu.score);
    
                printf("修改成功
    ");
                break;
    
            }
            p = p->pnext;
        }
    
        if (p == NULL)
        {
            printf("没有找到此节点
    ");
        }
        system("pause"); //暂停
        system("cls"); // 清屏
    
    }
    
    //删除头结点
    void deleteStudent()
    {
        //定义要删除的学号
        int num;
        printf("请输入要删除的学生的学号:
    ");
        scanf_s("%d", &num);
        //如果要删除的节点是头结点
        //定义一个用于删除节点的指针
        Node* pd;
        if (phead->stu.ID == num)
        {
            pd = phead;
            //将头结点向后移动一个节点
            phead = phead->pnext;
            //删除头结点
            free(pd);
            //产生结果
            printf("删除成功
    ");
    
            system("pause"); //暂停
            system("cls"); // 清屏
    
            return;
        }
    
        //如果要删除的节点不是头结点
        //重新定义一个节点,用于删除指定的节点,并且这里重复利用了上面定义的节点
        Node* pd1;
        //让pd去寻找需要的节点,这里头节点并不动
        pd = phead;
        //注意这个循环同样适用于两个节点的链表
        while (pd->pnext != NULL)
        {
            //如果找到了这个节点
            if (pd->pnext->stu.ID == num)
            {
                //这里利用到了pd1
                pd1 = pd->pnext;
                //将前后两个节点相连
                pd->pnext = pd->pnext->pnext;
                //删除目标节点
                free(pd1);
                //返回信息
                printf("节点删除成功
    ");
                system("pause"); //暂停
                system("cls"); // 清屏
                return;
    
            }
    
    
            //将节点向后移动一个位置用于寻找
            pd = pd->pnext;
        }
        //如果没有找到目标节点
        if (pd->pnext == NULL)
        {
            //返回信息
            printf("没有找到要删除的节点
    ");
            return;
    
        }
    
    }
  • 相关阅读:
    百度地图拾取坐标
    调参到脱发(百度大脑)
    git上传到GitHub
    Google搜索
    网络搜索引擎
    函数(函数的分类)
    adb的安装及环境配置
    三大流行数据库(MongoDB、PostgreSQL和Harper)大比拼
    《写给大家看的设计书》,推荐给想了解设计的程序员
    单元测试
  • 原文地址:https://www.cnblogs.com/zijidefengge/p/13756285.html
Copyright © 2020-2023  润新知