链表实现学生管理系统

这次我们运用链表的基础知识,增删改查,实现对学生系统进行管理,采用的多文件编程模式,接下来介绍一下什么叫做多文件编程。

程序一般分三类文件:

  • 头文件( .h ) 。放置各种声明,用于被文件包含。(头文件的存在是为了联系多个源文件,是源文件之间的接口。)
  • 模块文件(.c)。放置一些函数定义,也称为功能模块。
  • 主程序文件(.c)。包含main()的文件,程序入口,调用模块文件实现的方法
  • 在这里呢要给大家强调一下**:**在我们包含自己所写的头文件时,用" "(<>包含的头文件为标准库路径下的," "为工作路径下的,搜索范围是整个磁盘)

头文件的完整流程描述

#pragma once//避免头文件重复引用

进行头文件引用,把需要运用的都添加进来

#include <stdio.h>
#include<stdlib.h>
#include<string.h> 

首先需要定义一个结构体变量 student,其中包括学生的id,姓名,年龄,专业。

typedef struct Student{
    int id;
    char name[50];
    int age;
    char major[50];
    struct Student*next;
    }Stu;

头文件也需要满足对后续函数的声名定义功能

111

主函数的完整流程描述

菜单printMenu.c的完整流程描述

  • 功能 :打印操作菜单到控制台,提示用户进行选择。
  • 实现
    • 使用printf函数打印菜单的各个部分,包括欢迎语句、各个操作选项以及一个提示用户输入选择的语句。
    • 菜单中的每个选项对应一个数字,用户可以通过输入这个数字来选择对应的操作。
  • 菜单选项
    • 添加学生:允许用户输入新学生的详细信息(如ID、姓名、年龄和专业),并将这些信息添加到系统中。
    • 删除学生:允许用户通过指定学生的ID来删除该学生的信息。
    • 更新学生:允许用户修改已存在学生的信息,如姓名、年龄和专业等。
    • 搜索学生:允许用户通过学生的ID来搜索并查看该学生的详细信息。
    • 退出:退出程序,在退出前,程序应该释放所有动态分配的内存资源,确保没有内存泄漏。
  • 用户引导
    • 在打印完菜单后,最后一行"输入您的选择: "用于提示用户输入他们的选择。这是一个重要的交互步骤,它告诉用户该怎么做来选择一个操作。

      #include "NodeList.h"
      void printMenu(){
      printf("\n##########学生管理系统#######\n");
      printf("\n请进行选择操作\n");
      printf("1.添加学生\n"):
      printf("2.删除学生\n"):
      printf("3.更新学生\n"):
      printf("4.搜索学生\n");
      printf("5.退出程序\n");
      printf("\n##################\n");
      }

appendStudent.c的完整流程描述:

createStudent 函数

  • 功能 :动态分配内存以创建一个新的Student结构体实例,并初始化其成员变量。
  • 参数 :int id: 学生的ID。
    • char* name: 学生的姓名。
    • int age: 学生的年龄。
    • char* major: 学生的专业。
  • 返回值 :返回一个指向新创建的Student实例的指针。如果内存分配失败,则返回NULL。

实现细节:

  1. 使用malloc函数分配足够的内存来存储一个Student结构体实例。
  2. 检查malloc是否成功分配了内存。如果没有(即返回NULL),则打印错误消息并返回NULL。
  3. 使用参数值初始化新创建的Student实例的各个字段。
  4. 将next指针设置为NULL,因为这个新节点目前不指向任何其他节点。
  5. 返回新创建的Student实例的指针。
   #include "NodeList.h"
   Stu*creatStudent(int id,char *name,int age,char*major){
       Stu*student=(Stu*)malloc(sizeof(Stu));
       if(student==NULL){
           printf("分配空间失败\n");
           return 0;
       }
       student->id=id;
       strcpy(student->name,name);
       studnet->age=age;
       strcpy(student->major,major);
       student->next=NULL;
       return student;

appendStudent 函数

  • 功能 :将一个新的Student节点添加到学生链表的末尾。
  • 参数 :Student** head: 指向链表头节点指针的指针。
    • 其他参数(id, name, age, major)与createStudent函数相同,用于创建新的学生节点。
  • 返回值 :无。

实现细节:

  1. 调用createStudent函数创建一个新的学生节点。
  2. 如果新节点创建成功,检查链表是否为空(即头指针是否为NULL)。如果链表为空,直接将头指针指向新节点。
    1. 如果链表不为空,遍历链表找到最后一个节点,然后将其next指针指向新节点,从而将新节点添加到链表末尾。

      #include "NodeList.h"
      void appendStudent(Student**head,int id,char*name,int age,char*major){
          Stu*newstu=creatStudent(id,name,age,major);
          if(newstu==NULL){        newstu=*head;
          }else{
          Stu*temp=*head;
          while(temp->next!=NULL){
              temp=temp->next;
          }
          temp->next=newstu;
             }
              }
      

deleteStudent.c的完整流程描述:

deleteStudent 函数

  • 功能 :从链表中删除具有指定ID的学生节点。
  • 参数
    • Student** head:指向链表头节点指针的指针。使用指针的指针是为了能够在函数内部修改头节点指针的值(例如,当头节点被删除时)。
    • int id:要删除的学生的ID。
  • 返回值 :无。

实现细节:

  1. 检查链表是否为空 :首先检查头指针是否指向NULL,如果是,表示链表为空,打印一条消息并直接返回。

  2. 删除头节点的情况

    1. 如果链表不为空,检查头节点是否就是要删除的节点(通过比较id字段)。
    2. 如果是,将头指针指向下一个节点(*head = fast->next;),释放原头节点占用的内存,并打印一条删除成功的消息。
  3. 查找要删除的节点:

    1. 如果要删除的节点不是头节点,遍历链表寻找匹配的id。使用两个指针fast和slow进行遍历,fast用于指向当前检查的节点,而slow用于记录temp的前一个节点。
    2. 遍历过程中,如果找到了匹配的节点(fast->id == id),则退出循环准备进行删除操作;如果遍历结束也没有找到匹配的节点,则temp将为NULL。
  4. 处理学号不存在的情况:

    1. 如果遍历结束fast为NULL,表示链表中没有找到具有指定ID的学生,打印一条消息说明找不到该学生,并返回。
  5. 删除找到的节点:

    1. 如果找到了要删除的节点,将slow->next指向fast->next,这样就从链表中移除了fast指向的节点。
    2. 然后释放fast节点占用的内存,并打印一条删除成功的消息。
       #include"NodeList.h"
       void deleteSudent(Stu**head,int id){
         
           if(*head==NULL){
               printf("链表为空\n");
               return ;
           }else{
               Stu*fast=head,*slow;
               if((*head)->id=id){
                   *head=fast->next;
                   printf("删除成功\n");
                   free(fast);
                   
               }else{
               while(fast!=NULL&&fast->id!=id){
                   slow=fast;
                   fast=fast->next;
                   }
                   if(fast==NULL){
                       pritnf("没有找到要删除的学生\n");
                   return;
                   }
                   slow-next=fast->next;
                   free(fast);
                   printf("删除成功\n");  
                   }
    

    updateStudent.c的完整流程描述:

    updateStudent 函数

    • 功能 :更新链表中具有指定ID的学生节点的信息。
    • 参数:
      • Student* head:链表头节点的指针。
      • int id:要更新的学生的ID。
      • char* newName:学生的新姓名。
      • int newAge:学生的新年龄。
      • char* newMajor:学生的新专业。
    • 返回值:无。

    实现细节:

    1. 初始化变量:

      1. 使用一个临时指针temp来遍历链表,从头节点开始。
      2. 使用一个标志变量found来记录是否找到了具有指定ID的学生节点。
    2. 遍历链表:

      1. 在链表不为空的情况下,遍历每个节点。
      2. 对于每个节点,检查其ID是否与要更新的学生ID相匹配。
    3. 更新学生信息:

      1. 如果找到了匹配的节点,使用strcpy函数将新姓名和新专业复制到该节点的相应字段中,并直接更新年龄字段。
      2. 更新完成后,打印一条确认消息,并将found标志设置为1,然后跳出循环。
    4. 处理未找到的情况:

      1. 如果遍历完整个链表后没有找到匹配的节点(即found仍为0),打印一条错误消息说明找不到具有指定ID的学生。
         #include "NodeList.h"
         void updataStudent(Stu*head,int id,char*newName,int newAge,char*newMajor){
             Stu*temp=head;
             int found=0;
             if(head==NULL)return ;
             while(temp!=NULL){
                 if(temp->id=id){
                 strcpy(temp->name,newName);
                 temp->age=newAge;
                 strcpy(temp->major,newMajor);
                 printf("更新完成\n");
                 found=1;
                 break;
             }
             printf("\n");
             }
      

      searchStudent.c的完整流程描述:

      searchStudent 函数

      • 功能 :在链表中搜索具有指定ID的学生,并打印该学生的详细信息。
      • 参数:
        • Student* head:链表头节点的指针。
        • int id:要搜索的学生的ID。
      • 返回值 :无。

      实现细节:

      1. 初始化变量:
        1. 使用一个临时指针temp来遍历链表,从头节点开始。
        2. 使用一个标志变量found来记录是否找到了具有指定ID的学生节点。
      2. 遍历链表:
        1. 在链表不为空的情况下,遍历每个节点。
        2. 对于每个节点,检查其ID是否与要搜索的学生ID相匹配。
      3. 打印学生信息:
        1. 如果找到了匹配的节点,使用printf函数打印该学生的详细信息(包括ID、姓名、年龄和专业)。
        2. 打印完成后,将found标志设置为1,并跳出循环。
      4. 处理未找到的情况:
        1. 如果遍历完整个链表后没有找到匹配的节点(即found仍为0),打印一条错误消息说明找不到具有指定ID的学生。

    #include "NodeList.h"
    void searchStudent(Stuhead,int id){
    Stu
    temp=head;
    int found=0;
    if(temp=NULL)return;
    while(temp!=NULL&&temp->id!=id){
    temp=temp->next;
    }
    if(temp==NULL){
    printf("没有找到\n");
    return;
    }
    printf("找到了id为%d的学生姓名为%s\n",id,name);
    printf("找到了id为%d的学生年龄为%d\n",id,age);
    printf("找到了id为%d的学生专业为%s\n",id,major);

         }
    
相关推荐
FeboReigns2 小时前
C++简明教程(文章要求学过一点C语言)(1)
c语言·开发语言·c++
FeboReigns2 小时前
C++简明教程(文章要求学过一点C语言)(2)
c语言·开发语言·c++
_小柏_3 小时前
C/C++基础知识复习(43)
c语言·开发语言·c++
yoyobravery3 小时前
c语言大一期末复习
c语言·开发语言·算法
axxy20005 小时前
leetcode之hot100---21合并两个有序链表(C++)
c++·leetcode·链表
R_.L5 小时前
数据结构:双向循坏链表
数据结构·链表
落羽的落羽7 小时前
【落羽的落羽 C语言篇】自定义类型——结构体
c语言
Kisorge7 小时前
【C语言】代码BUG排查方式
c语言·开发语言·bug
yoyo勰8 小时前
sqlite3
c语言·sqlite
就爱学编程9 小时前
重生之我在异世界学编程之C语言:数据在内存中的存储篇(上)
c语言·数据结构