学生信息管理系统-C语言

一、原理

如何写一个学生信息管理系统?那么首先想到,学生信息包含哪些东西(数据)。如:一个人,有名字、性别、年龄、专业、学号等信息,如何定义一个人?int,char,long等都不行,这时,结构体就是一个很好的办法。

定义一个结构体:

如: struct snode {

char name[16];

char sex;

char age;

long id;

.......

};

此时一个结构体就包含了一个学生的所有信息,但是学生不止一人,定义多个结构体吗?显然不现实,此时我们就需要在结构体里面加一个结构体成员,这个成员是结构体指针,这个指针指向下一个结构体,里面包含了学生信息和下一个的结构体指针,这样就可以通过上一个结构体找到下一个结构体,就像一块一块的东西用一根线挨个连接,每一段线就是一个指针,每一块东西就是结构体,它们整体就叫做链表,像一根链子一样,每个结构体就是它的节点。

如:struct snode {

char name[16];

char sex;

char age;

long id;

......

struct snode *next;

};

那么只要我们找到链子的头,就可以顺藤摸瓜,找到后面的东西,定义一个头节点,把学生信息都连在后面,此时我们就只需要知道头节点的地址,就可以通过遍历链表得到全部的学生信息。但是有一个问题,当学生人数少的时候,这是完全没有问题的,当学生人数上万或者跟多,遍历链表查找信息就太浪费时间了,其实有 一种快速查找的方法,那就是哈希(hash)算法。

hash算法:

首先要计算hash值,计算hash值的方法与很多种,可能每个人都有不同的计算方法,把hash值存入一个比较大的数组(结构体数组),如:arr[2048],&arr[hashval]就是它的地址,当做头地址,后面挂着相同hash值的学生信息,这些信息连成一个链表,找到hash值的地址就相当于找到链表的头了,遍历这个链表就能快速找到需要的信息。有点像图的链式存储。

原理:存入:根据关键字,计算hash值,存入该位置。

取出:根据关键字,计算hash值,直接取出来。

如下图:

二、代码实现

代码的话,有几个不完美的地方:

  1. 由于使用名字计算hash值的,名字输入只能是英文字母。

  1. 可以存储同名的人,但是修改同名的人的其他数据(年龄、学号等),只能修改第一个人的信息,不能够指定人,可以增加一些判断来决定修改哪一个人的信息(代码中没有实现)。但是可先修改名字,找到这个新名字,再修改信息(年龄、学号等),然后再把名字改回去,或者删除后重新添加,不过都太麻烦了。

注:如果有大佬有更好的方法,请多多指教

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

#define MAX  2048

struct stunode{
    char name[16];
    char sex[8];
    int age;
    int id;
    struct stunode *next;
};
//定义一个结构体数组,用来存放链表头(hash值)
struct stunode stu_head_arr[2048];
//计算hash值,这里比较简单,由名字的字母计算,所以只能输入英文
int hash_calucate(char *name)
{
    int sum=0;
    for(int i=0;i<strlen(name);i++)
      sum+=name[i];
    return sum%MAX;//限制范围
}

//学生信息输入,每一个学生信息都是一个结构体
int stu_info_add_member(void)
{
    struct stunode *p = malloc(sizeof(*p));

    printf("pls input name sex age id:");
    scanf("%s %s %d %d",p->name,p->sex,&p->age,&p->id);

    int hashval=hash_calucate(p->name);//计算hash值
    struct stunode *pthead=&stu_head_arr[hashval];//存入数组的值作为链表头
    struct stunode *pttail=&stu_head_arr[hashval];
    //头部插入
    p->next=pthead->next;
    pthead->next=p;
//    尾部插入
//    while(pttail->next!=NULL)
//      pttail=pttail->next;
//    pttail->next=p;
    return 0;
}
//学生信息查找,定义结构体函数
struct stunode *stu_info_find_member(char*name)
{
    int hashval= hash_calucate(name);//计算hash值

    struct stunode *pthead=&stu_head_arr[hashval];//找到对应的链表头
    struct stunode *p=pthead->next;
    while(p)//通过字符串比较,查找所需要的信息
    {
        if(strcmp(p->name,name)==0)
          return p;
        p=p->next;
    }
    return NULL;//没找到返回空
}
//修改学生信息
int stu_info_change(char*name)
{
    struct stunode *p = stu_info_find_member(name);//通过查找函数找到地址
    if(!p)
    {
        printf("sorry no found\n");
        return -1;
    }
    int hashval=hash_calucate(p->name);//计算hash值
    struct stunode *q=&stu_head_arr[hashval];//记录头地址

    while(1)
    {
        printf("*****************菜单*****************\n");
        printf("1: modify name\n");
        printf("2: modify sex\n");
        printf("3: modify age\n");
        printf("4: modify id\n");
        printf("5: exit\n");
        printf("*****************菜单*****************\n");
        int select;
        scanf("%d",&select);
        switch(select)
        {
            case 1:if(q->next!=p)//找到p前面的地址
                        q=q->next;
                   q->next=p->next;//q与p后面的数据相连
                   printf("pls modify name:");scanf("%s",p->name);
            //     q->next=p->next;//原来的头与p后面的数据相连
                   int val=hash_calucate(p->name);//计算hash值
                   struct stunode *pthead=&stu_head_arr[val];//存入数组的值作为新的链表头
                   p->next=pthead->next;//插入新的位置
                   pthead->next=p;
                   break;
            case 2:printf("pls modify sex:");scanf("%s",p->sex);//修改性别       
                   break;
            case 3:printf("pls modify age:");scanf("%d",&p->age);//修改年龄  
                   break;
            case 4:printf("pls modify id:");scanf("%d",&p->id); //修改id
                   break;
            case 5:return 0;

        }
    }
}
//删除信息
int stu_info_delete(char*name)
{
    struct stunode *p = stu_info_find_member(name);//查找信息
    if(!p)
    {
        printf("sorry no found\n");
        return -1;
    }
    int hashval=hash_calucate(p->name);//计算hash值
    struct stunode *pre=&stu_head_arr[hashval];
    while(pre->next!=p)//找到p前面一个地址pre
      pre=pre->next;
    pre->next=p->next;//p前面与p后面相连
}

int main(void)
{
    char name[16];

    while(1){
        printf("*****************菜单*****************\n");
        printf("1: add member\n");
        printf("2: find member by name\n");
        printf("3: modify member by name\n");
        printf("4: delete member by name\n");
        printf("5: exit\n");
        printf("*****************菜单*****************\n");

        int select;
        scanf("%d",&select);
        switch(select){
            case 1:
                stu_info_add_member();
                break;
            case 2:
                printf("pls input your name:");
                scanf("%s",name);
                struct stunode *p = stu_info_find_member(name);

                if(p)
                {
                    printf("name:%s sex:%s age:%d id:%d \n",\
                                p->name,p->sex,p->age,p->id);
                    //如果有重名的,都打印出来
                    while((p->next!=NULL)&&(strcmp(p->name,p->next->name)==0))
                    {
                        printf("name:%s sex:%s age:%d id:%d \n",\
                                    p->next->name,p->next->sex,p->next->age,p->next->id);
                        p=p->next;
                    }
                }
                else 
                    printf("sorry no found\n");

                break;        
            case 3:
                printf("pls input your name:");
                scanf("%s",name);
                stu_info_change(name);
                break;            
            case 4:
                printf("pls input your name:");
                scanf("%s",name);
                stu_info_delete(name);
                break;    
            case 5: return 0;
        }
    }
}

结果如下:

  1. 输入信息和查找信息

可以看见输入姓名、性别、年龄 ID之后能够查找到信息

  1. 修改信息

a.修改名字

b.修改年龄

c.查看修改后的信息

可以看见修改成功了,也能查找到

  1. 删除信息

可以看见删除“kang”之后再查找,显示“sorry no found”,说明删除成功了

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值