栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

23.C语言 学生系统管理

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

23.C语言 学生系统管理

一、实验目的

1.掌握链表的基本结构和关系。

2.掌握C指针和结构体的使用方法,掌握链表编程。

链表知识点讲解:

链表的遍历:

 有·两种链表,第一种是第一个节点数据部分为空。另一种是第一个节点就存放数据。

两种方式的编程是有点不同的:

        第一种方式,不管怎样对链表进行增加修改和删除,head的位置都不会变化,head的值只需要传入到函数中,不需要返回,不需要返回。

        第二种方式,如果数据插入到第一个节点,head存储的地址会发生变化。这种方式的链表在定义函数时,需要返回链表的head。

实现思路:

①用head指针永远指向链表头。

②用q指针一开始指向第一个有数据的节点,然后就可以访问到节点中的数据了。访问结束后,q移动到下一个节点(q=q->next;),直到q的值为NULL,结束对链表的访问。

typedef struct Student{

        char studentNo[20];

        char studentName[11];

}st;

typedef struct node{

        struct Student data;     //数据段

        struct node *next;         //指针域 

}Node,*link;                        //Node为node类型的别名,link为node类型的指针别名

Node st1;

link p;(link 本身就是一个指针类型的结构体变量)


链表的插入(建立):

在这个例子中,学生节点的插入是有顺序的(链表按照学号排序),也就是说,每次准备插入一个学生节点时,先要找到这个节点应该插入到那个节点的前面。有几种情况需要考虑:

1.当前链表是空的(head的指针域为空),状态如下(node为新节点(用malloc创立),准备插入的第一个节点):

此时,则直接用head->next = node;这条语句,就可以把node插入到链表中。 

if(head->next==NULL)
        head->next=node;

2.当前链表已经有节点的情况,状态如下图(node为新建立,准备插入的节点):

想要插入节点就需要两个一前一后的指针

 那么此时,就需要比较“node中studentNo”和“p的studentNo”,查看大小关系。如果“node中的studentNo”小于“p中的studentNo”,这把node插入到q,p之间。如果q,p永远保持一前一后的关系,这样才能保证在找到节点位置后,可以顺利的插入。                   q=head;
                                                                                                             p=head->next; 

bool addNode(link head)
{
    link p,q;        //p,q两个节点一前一后
    link node;       //node指针指向新创建的节点
    node=(link)malloc(sizeof(Node));
    inputStudent(node);
    
    q=head;
    p=head->next;    //p指向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节点的学号大,继续向后移动指针(依然保持q p一前一后)
                q=p;    
                p=p->next;    
            }
        }
        //如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
        q->next=node;
    }
    return true;
}

实现步骤:


链表的删除:

 删除链表的思路:

首先,利用p指针扫描链表,根据学生的学号找到要删除的节点位置。

如果找到,则用以下语句就可以删除p所指向的节点(free p):

                                                                q->next = p->next;

                                                                free(p);

这里编程的要点是:保证q在前,p在后的关系,这样才能保证在找到节点位置后,可以顺利的删除。

如果当前p的学号不等于要删除的学号,则p指针后移。

要考虑如果找不到学生学号的情况。

测试数据时,应该实验可以找到学号的情形,和给定的学号找不到的情形,然后查看删除是否成功。

链表的修改,链表的查询:

这两个功能和删除链表的思路类似:

都是先找到要处理的节点,然后处理即可。

“修改”还需要考虑修改内容是否是学号,如果修改了学号,则应该编写程序保证不能破坏链表有序性的这个特点。


链表的清除:(养成好的习惯)

        当在菜单中选择了退出功能后,则结束程序。在结束程序之间,要考虑到一个问题:前面用malloc语句建立的节点,在main函数退出时,分配的存储空间是不会自动释放的,所以必须主动释放链表中所有节点占用的内存。(free语句释放所有malloc产生的节点)

        定义一个clearlink函数,实现链表的遍历,并用free语句释放所有malloc产生的节点。


 

#include 
#include 
#include 
#include 
#include 


typedef struct Student{

        char studentNo[20];

        char studentName[11];

}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);
    scanf("%s",no);
}

void displayNode(link head)
{
    //填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息

}

bool addNode(link head)
{
    link p,q;        //p,q两个节点一前一后
    link node;       //node指针指向新创建的节点
    node=(link)malloc(sizeof(Node));
    inputStudent(node);

    q=head;
    p=head->next;    //p指向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节点的学号大,继续向后移动指针(依然保持q p一前一后)
                q=p;
                p=p->next;
            }
        }
        //如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
        q->next=node;
    }
    return true;
}

bool deleteNode(link head,char no[])
{
    //按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
    //输入要处理的学号
    inputStudentNo("删除",no);

    return false;
}

bool queryNode(link head,char no[])
{
    //按照给定的学号查询学生记录,如果查询成功返回true,如果没找到学号返回false

    //输入要处理的学号
    inputStudentNo("查询",no);

    return false;


}

bool modifyNode(link head,char no[])
{
    //按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false

    //输入要处理的学号
    inputStudentNo("修改",no);

    return false;

}

int countNode(link head)
{
    //统计学生的人数,扫描链表统计节点个数,返回节点数
    //link p;
    //int count = 0;
    //p = head->next;

    return false;
}

void clearlink(link head)
{
    //link q,p;
    //遍历链表,用free语句删除链表中用malloc建立起的所有节点

}

int main()
{
    int select;
    int count;
    link head;      //定义链表
    char no[20];

    //建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的
    head = (link)malloc(sizeof(Node));
    head->next = NULL;

    while(1)//死循环
    {
        myMenu();
        printf("n请输入你的选择(1-7):");    //显示提示信息
        scanf("%d",&select);

        switch(select)
        {
            case 1:
                //增加学生记录
                if(addNode(head))
                    printf("成功插入一个学生记录。nn");
                break;

            case 2:
                //删除学生记录
                if(deleteNode(head,no))
                    printf("成功删除一个学生记录。nn");
                else
                    printf("没有找到要删除的学生节点。 nn");

            case 3:
                //查询学生记录
                if(queryNode(head,no))
                    printf("成功找到学生记录。nn");
                else
                    printf("没有找到学生记录。nn");
                break;

            case 4:
                //修改学生记录
                if(modifyNode(head,no))
                    printf("成功修改一个学生记录。nn");
                else
                    printf("没有找到要修改的学生节点。nn");
                break;

            case 5:
                //统计学生人数
                count = countNode(head);
                printf("学生人数为:%dnn",count);
                break;

            case 6:
                //显示学生记录
                displayNode(head);
                break;

            case 7:
                //退出前清除链表中的所有节点
                clearlink(head);
                return 0;
            default:
                printf("输入不正确,应该输入0~7之间的数。nn");
                break;
        }
    }
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/384579.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号