美文网首页
懒猫老师-C语言-链表作业1:学生管理系统(链表练习,链表应用)

懒猫老师-C语言-链表作业1:学生管理系统(链表练习,链表应用)

作者: heiqimingren | 来源:发表于2020-11-26 10:52 被阅读0次

    https://www.bilibili.com/video/av77591213

    ==================


    image.png
    image.png
    image.png
    image.png
    image.png
    image.png
    image.png
    image.png
    image.png
    image.png
    image.png

    我测试了一下,就有一个函数不能用,其余的都是正常的,学到了不少东西啊

    还有,判断2个字符串,是否相同,得用strcmp函数,而不是 ==

    
    //============================================================================
    // Name        : LinkBlank.cpp
    // Author      :
    // Version     :
    // Copyright   : Your copyright notice
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <stdio.h>
    #include<string.h>
    #include<malloc.h>
    #include<stdlib.h>
    #include<stdbool.h>
    
    #define NO_LENGTH  20
    #define NAME_LENGTH 11
    
    /* 定义学生结构体的数据结构 */
    typedef struct Student{
        char studentNo[NO_LENGTH];
        char studentName[NAME_LENGTH];
    }st;
    
    /* 定义每条记录或节点的数据结构 */
    typedef struct node
    {
        struct Student data; //数据域
        struct node *next; //指针域
    }Node, *Link;  //Node为node类型的别名,Link为node类型的指针别名
    
    //定义提示菜单
    void myMenu(){
        printf(" * * * * * * * * * 菜     单 * * * * * * * * * *\n");
        printf("     1 增加学生记录            2 删除学生记录                     \n");
        printf("     3 查找学生记录            4 修改学生记录                     \n");
        printf("     5 统计学生人数            6 显示学生记录                     \n");
        printf("     7 退出系统                                     \n");
        printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
    }
    
    void inputStudent(Link l){
        printf("请输入学生学号:");
        scanf("%s", l->data.studentNo);
        printf("请输入学生的姓名:");
        scanf("%s", l->data.studentName);
    
        //每个新创建的节点的next域都初始化为NULL
        l->next = NULL;
    }
    //这个是干嘛的???
    void inputStudentNo(char s[], char no[]){        //数组名当做函数形参
        printf("请输入要%s的学生学号:", s);          //char s中的s,代表 修改  查询,删除,等字样
        scanf("%s", no);
    }
    
    
    //作业内容,我自己编写的
    void displayNode(Link head){
        // 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
        Link p;
        p = head->next;
        while (p!=NULL)
        {
            printf("学生的学号是:%s \n", p->data.studentNo);
            printf("学生的姓名是:%s \n", p->data.studentName);
            p = p->next;
        }
    }
    
    
    
    
    /* 增加学生记录 */
    bool addNode(Link head){
        Link p, q;   //p,q两个节点一前一后
        Link node;  //node指针指向新创建的节点
        node = (Link)malloc(sizeof(Node));
        inputStudent(node);     //传入一个节点,手动输入学生学号和学生姓名这2个数据,传入到结点node当中!,有意思的操作!
    
        q = head;
        p = head->next;  //q指向head后面的第一个有效节点
        if (head->next == NULL)
            //链表为空时
            head->next = node;
        else {  //当链表不为空,说明链表本身就有数据的时候,执行下段代码。。
            //循环访问链表中的所有节点
            while (p != NULL){
                if (node->data.studentNo < p->data.studentNo){
                    //如果node节点的学号比p节点的学号小,则插在p的前面,完成插入后,提前退出子程序
                    q->next = node;
                    node->next = p;
                    return true;
                }
                else{
                    //如果node节点的学号比p节点的学号大,继续向后移动指针(依然保持pq一前一后)q....p  这样的顺序。
                    q = p;
                    p = p->next;
    
                }
            }
            //如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
            q->next = node;
    
        }
        return true;
    }
    
    //老师留下的作业,自己完成需要
    bool deleteNode(Link head){
    
        // 按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
    
        //输入要处理的学号
        char no[NO_LENGTH];
        inputStudentNo("删除", no);
        Link p, q;
    
        if (head==NULL ||head->next==NULL ) //如果链表没有数据,返回false
        {
            return false;
        }
        q = head;
        p = head->next;  //初始化。q,p两个指针,一前一后。
    
        while (p!=NULL)
        {
            if (strcmp(p->data.studentNo, no) == 0)  //判断2个字符串相同,不能用==,而应该用strcmp函数!
            {
                q->next = p->next;
                free(p);
                return true;
            }
            else            //如果没有找到,就让两个指针,同时往下一个结点去遍历
            {
                q = p;
                p = p->next;
            }
        }
        //如果循环遍历结束,都没有找到相对应的学号,说过指定学号不在链表当中
        return false;
    
    }
    
    //老师留下的作业,自己完成需要,查找学生记录
    bool queryNode(Link head){
        // 按照给定的学号查询学生记录,如果查询成功返回true,如果没找到学号返回false
    
        //输入要处理的学号
        char no[NO_LENGTH];
        inputStudentNo("查找", no);
        //printf("要查找的数组序号是:%s \n", no);
    
        Link p;
        p = head->next;
        while (p!=NULL)
        {
            /*printf("学生的姓名是: %s \n", p->data.studentNo);
            printf("学生的姓名是: %s \n", p->data.studentName);*/
            
            if (strcmp(p->data.studentNo,no)==0 )      //判断2个字符串相同,不能用==,而应该用strcmp函数!
            {
                
                printf("成功了!该学生的姓名是: %s", p->data.studentName);
                return true;
            }
            p = p->next;
        }
        //如果循环结束了,说明没有找到
        return false;
    }
    
    //老师留下的作业,自己完成需要
    bool modifyNode(Link head){
        // 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
    
        //输入要处理的学号-----------只修改学号,不修改姓名?还是2者都可以随便修改?
        char no[NO_LENGTH];
        inputStudentNo("修改", no);
    
        if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
        {
            return false;
        }
        Link p;
        p = head->next;
        while (p != NULL)
        {
            if (strcmp(p->data.studentNo, no) == 0)  //当找到用户的学号的时候,
            {
                printf("学生的姓名是: %s \n", p->data.studentName);
                scanf("把此学生姓名修改为: %s \n", p->data.studentName);
                return true;
            }
            p = p->next;
        }
    
    
    
    
    
    
        return false;
    
    }
    
    //老师留下的作业,自己完成需要
    int countNode(Link head){
        //统计学生人数,扫描链表统计节点个数,返回节点数
        Link p;
        int count = 0;
        p = head->next;
    
        if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
        {
            return false;
        }
    
        while (p!=NULL)
        {
            p = p->next;
            count++;
        }
        //填充代码
        return count;    //注意count的初始值和返回值之间的关系。
    
    }
    
    //老师留下的作业,自己完成需要,我自己写的不知道是否可以。
    int clearLink(Link head){
        Link q, p;
        //遍历链表,用free语句删除链表中用malloc建立起的所有的节点
        if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
        {
            return false;
        }
        while (head->next!=NULL)
        {
            q = head;
            head = head->next;
            free(q);
        }
        return true;
    
    
    }
    
    
    int main() {
        int select;
        int count;
        Link head;  // 定义链表
    
    
        //建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的数据
        head = (Link)malloc(sizeof(Node));
        head->next = NULL;
    
        while (1)
        {
            myMenu();
            printf("\n请输入你的选择(0-7):");  //显示提示信息
            scanf("%d", &select);
    
            switch (select)
            {
            case 1:
                //增加学生记录
                if (addNode(head))
                    printf("成功插入一个学生记录。\n\n");
                break;
            case 2:
                //删除学生记录
                if (deleteNode(head))
                    printf("成功删除一个学生记录。\n\n");
                else
                    printf("没有找到要删除的学生节点。\n\n");
                break;
            case 3:
                //查询学生记录
                if (queryNode(head))
                    printf("成功找到学生记录。\n\n");
                else
                    printf("没有找到要查询的学生节点。\n\n");
                break;
            case 4:
                //修改学生记录
                if (modifyNode(head))
                    printf("成功修改一个学生记录。\n\n");
                else
                    printf("没有找到要修改的学生节点。\n\n");
                break;
            case 5:
                //统计学生人数
                count = countNode(head);
                printf("学生人数为:%d\n\n", count);
                break;
            case 6:
                //显示学生记录
                displayNode(head);
                break;
            case 7:
                //退出前清除链表中的所有结点
                clearLink(head);
                return 0;
            default:
                printf("输入不正确,应该输入0-7之间的数。\n\n");
                break;
            }
        }
        return 0;
    }
    
    
    

    =========
    我在网上,找到了一个学生的学习笔记,写的比我的好,细节很到位
    网址:https://www.yuque.com/jason2018/euoi7a/mxiowo

    
    //============================================================================
    // Name        : LinkBlank.cpp
    // Author      :
    // Version     :
    // Copyright   : Your copyright notice
    // Description : Hello World in C++, Ansi-style
    //============================================================================
    
    #include <stdio.h>
    #include<string.h>
    #include<malloc.h>
    #include<stdlib.h>
    #include<stdbool.h>
    
    #define NO_LENGTH  20
    #define NAME_LENGTH 11
    
    /* 定义学生结构体的数据结构 */
    typedef struct Student{
        char studentNo[NO_LENGTH];
        char studentName[NAME_LENGTH];
    }st;
    
    /* 定义每条记录或节点的数据结构 */
    typedef struct node
    {
        struct Student data; //数据域
        struct node *next; //指针域
    }Node, *Link;  //Node为node类型的别名,Link为node类型的指针别名
    
    //定义提示菜单
    void myMenu(){
        printf(" * * * * * * * * * 菜     单 * * * * * * * * * *\n");
        printf("     1 增加学生记录            2 删除学生记录                     \n");
        printf("     3 查找学生记录            4 修改学生记录                     \n");
        printf("     5 统计学生人数            6 显示学生记录                     \n");
        printf("     7 退出系统                                     \n");
        printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
    }
    
    void inputStudent(Link l){
        printf("请输入学生学号:");
        scanf("%s", l->data.studentNo);
        printf("请输入学生的姓名:");
        scanf("%s", l->data.studentName);
    
        //每个新创建的节点的next域都初始化为NULL
        l->next = NULL;
    }
    //这个是干嘛的???
    void inputStudentNo(char s[], char no[]){        //数组名当做函数形参
        printf("请输入要%s的学生学号:", s);          //char s中的s,代表 修改  查询,删除,等字样
        scanf("%s", no);
    }
    
    
    //作业内容,我自己编写的
    void displayNode(Link head){
        // 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
        Link p;
        p = head->next;
        while (p!=NULL)
        {
            printf("学生的学号是:%s \n", p->data.studentNo);
            printf("学生的姓名是:%s \n", p->data.studentName);
            p = p->next;
        }
    }
    
    
    
    
    /* 增加学生记录 */
    bool addNode(Link head){
        Link p, q;   //p,q两个节点一前一后
        Link node;  //node指针指向新创建的节点
        node = (Link)malloc(sizeof(Node));
        inputStudent(node);     //传入一个节点,手动输入学生学号和学生姓名这2个数据,传入到结点node当中!,有意思的操作!
    
        q = head;
        p = head->next;  //q指向head后面的第一个有效节点
        if (head->next == NULL)
            //链表为空时
            head->next = node;
        else {  //当链表不为空,说明链表本身就有数据的时候,执行下段代码。。
            //循环访问链表中的所有节点
            while (p != NULL){
                if (node->data.studentNo < p->data.studentNo){
                    //如果node节点的学号比p节点的学号小,则插在p的前面,完成插入后,提前退出子程序
                    q->next = node;
                    node->next = p;
                    return true;
                }
                else{
                    //如果node节点的学号比p节点的学号大,继续向后移动指针(依然保持pq一前一后)q....p  这样的顺序。
                    q = p;
                    p = p->next;
    
                }
            }
            //如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
            q->next = node;
    
        }
        return true;
    }
    
    //老师留下的作业,自己完成需要
    bool deleteNode(Link head){
    
        // 按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
    
        //输入要处理的学号
        char no[NO_LENGTH];
        inputStudentNo("删除", no);
        Link p, q;
    
        if (head==NULL ||head->next==NULL ) //如果链表没有数据,返回false
        {
            return false;
        }
        q = head;
        p = head->next;  //初始化。q,p两个指针,一前一后。
    
        while (p!=NULL)
        {
            if (strcmp(p->data.studentNo, no) == 0)  //判断2个字符串相同,不能用==,而应该用strcmp函数!
            {
                q->next = p->next;
                free(p);
                return true;
            }
            else            //如果没有找到,就让两个指针,同时往下一个结点去遍历
            {
                q = p;
                p = p->next;
            }
        }
        //如果循环遍历结束,都没有找到相对应的学号,说过指定学号不在链表当中
        return false;
    
    }
    
    //插入一个学生记录
    void insertNode(Link head, Link newNode)
    {
        Link p, q;
        bool flag = false; //是否插入成功
    
        p = head;
        q = head->next;
        //如果是空链表
        if (head->next == NULL)
        {
            head->next = newNode;
            flag = true;
        }
        else
        {
            //不是空链表
            while (q != NULL)
            {
                /*
                ① str1小于str2,返回负值或者-1(VC返回-1);
    
                ② str1等于str2,返回0;
                ③ str1大于str2,返回正值或者1(VC返回1);
                */
                if (strcmp(newNode->data.studentNo, q->data.studentNo) < 0)        //如果newnode小于studentNo,就进行下列操作。。
                {
                    p->next = newNode;  //如果不明白,画一下图,立马就明白了。
                    newNode->next = q;
                    flag = true;
                    break;
                }
                else   //如果新增的学生序号大于q->学生序号,那么就顺着循序往下移动。精妙的操作
                {
                    p = q;
                    q = q->next;
                }
            }
        }
    
        if (q == NULL && flag == false)   //如果q指针带头了,或者flag=false,那么久
        {
            p->next = newNode;
        }
    }
    
    
    //老师留下的作业,自己完成需要,查找学生记录
    bool queryNode(Link head){
        // 按照给定的学号查询学生记录,如果查询成功返回true,如果没找到学号返回false
    
        //输入要处理的学号
        char no[NO_LENGTH];
        inputStudentNo("查找", no);
        //printf("要查找的数组序号是:%s \n", no);
    
        Link p;
        p = head->next;
        while (p!=NULL)
        {
            /*printf("学生的姓名是: %s \n", p->data.studentNo);
            printf("学生的姓名是: %s \n", p->data.studentName);*/
            
            if (strcmp(p->data.studentNo,no)==0 )      //判断2个字符串相同,不能用==,而应该用strcmp函数!
            {
                
                printf("成功了!该学生的姓名是: %s", p->data.studentName);
                return true;
            }
            p = p->next;
        }
        //如果循环结束了,说明没有找到
        return false;
    }
    
    //老师留下的作业,自己完成需要
    bool modifyNode(Link head){
        // 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
    
        //输入要处理的学号-----------只修改学号,不修改姓名?还是2者都可以随便修改?
        char no[NO_LENGTH];
        char no_new[NO_LENGTH];     //新学号
        char name_new[NAME_LENGTH]; //新姓名
        int select;                 //功能选择
        Link p, q;
    
        inputStudentNo("修改", no);
        printf("请输入需要修改的项目: 1 学号 2 姓名\n");
        scanf("%d", &select);
    
    
        p = head;
        q = head->next;
    
        while (q != NULL)
        {
            if (strcmp(q->data.studentNo, no) == 0)     //当在链表中遍历到该学生学号的时候, 
            {
                if (select == 1)
                {
                    p->next = q->next;
                    q->next = NULL;
                    printf("请输入该学生的新学号:");
                    scanf("%s", no_new);
                    strcpy(q->data.studentNo, no_new);
                    insertNode(head, q);
                }
                else
                {
                    printf("请输入该学生的新姓名:");
                    scanf("%s", name_new);
                    strcpy(q->data.studentName, name_new);
                }
                return true;
            }
            else
            {
                p = q;
                q = q->next;
            }
        }
    
        return false;
    
    
    }
    
    //老师留下的作业,自己完成需要
    int countNode(Link head){
        //统计学生人数,扫描链表统计节点个数,返回节点数
        Link p;
        int count = 0;
        p = head->next;
    
        if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
        {
            return false;
        }
    
        while (p!=NULL)
        {
            p = p->next;
            count++;
        }
        //填充代码
        return count;    //注意count的初始值和返回值之间的关系。
    
    }
    
    //老师留下的作业,自己完成需要,我自己写的不知道是否可以。
    int clearLink(Link head){
        Link q, p;
        //遍历链表,用free语句删除链表中用malloc建立起的所有的节点
        if (head == NULL || head->next == NULL) //如果链表没有数据,返回false
        {
            return false;
        }
        while (head->next!=NULL)
        {
            q = head;
            head = head->next;
            free(q);
        }
        return true;
    
    
    }
    
    
    int main() {
        int select;
        int count;
        Link head;  // 定义链表
    
    
        //建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的数据
        head = (Link)malloc(sizeof(Node));
        head->next = NULL;
    
        while (1)
        {
            myMenu();
            printf("\n请输入你的选择(0-7):");  //显示提示信息
            scanf("%d", &select);
    
            switch (select)
            {
            case 1:
                //增加学生记录
                if (addNode(head))
                    printf("成功插入一个学生记录。\n\n");
                break;
            case 2:
                //删除学生记录
                if (deleteNode(head))
                    printf("成功删除一个学生记录。\n\n");
                else
                    printf("没有找到要删除的学生节点。\n\n");
                break;
            case 3:
                //查询学生记录
                if (queryNode(head))
                    printf("成功找到学生记录。\n\n");
                else
                    printf("没有找到要查询的学生节点。\n\n");
                break;
            case 4:
                //修改学生记录
                if (modifyNode(head))
                    printf("成功修改一个学生记录。\n\n");
                else
                    printf("没有找到要修改的学生节点。\n\n");
                break;
            case 5:
                //统计学生人数
                count = countNode(head);
                printf("学生人数为:%d\n\n", count);
                break;
            case 6:
                //显示学生记录
                displayNode(head);
                break;
            case 7:
                //退出前清除链表中的所有结点
                clearLink(head);
                return 0;
            default:
                printf("输入不正确,应该输入0-7之间的数。\n\n");
                break;
            }
        }
        return 0;
    }
    
    
    
    

    相关文章

      网友评论

          本文标题:懒猫老师-C语言-链表作业1:学生管理系统(链表练习,链表应用)

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