商品品牌信息的增删改查操作步骤_图书信息管理系统

b49fcddc-4314-eb11-8da9-e4434bdf6706.png

不仅仅是图书信息管理系统

基于双链表,采用面向对象编程方法制作的图书管理系统

来源微信公众号:

不仅仅是图书信息管理系统​mp.weixin.qq.com
b69fcddc-4314-eb11-8da9-e4434bdf6706.png

效果演示

b79fcddc-4314-eb11-8da9-e4434bdf6706.png

框架结构

数据层:双链表管理

核心层:用户管理、图书管理

用户管理:

用户分三种:readonly、write、root(可删除数据)

功能:Exit(退出), Add(添加), Show(显示), Change(修改), Delete(删除), Search(查找)

图书管理:

权限分级:暂未实现(可自行实现)

功能:EXIT(退出), ADD(添加), SHOW(显示), CHANGE(修改), DELETE(删除), SEARCH(查找)

ps:用这个双链表框架可以解决99.9%的各种信息管理系统(增删改查)问题,那%0.1就是给自己留的后路,毕竟没有什么问题可以100%解决

以后再跟我提xxx管理系统我就给你扔过去这对代码,自己去实现

核心部分:双链表的实现

b99fcddc-4314-eb11-8da9-e4434bdf6706.png
 typedef struct deroy_node
 {
     void* data;
     struct deroy_node* prev;
     struct deroy_node* next;
 }deroy_node_t;
 typedef deroy_node_t* deroy_node_pt;
 ​
 ​
 typedef struct deroy_list
 {
     int  limit_size;
     deroy_node_pt head;
     deroy_node_pt tail;
 }deroy_list_t;
 typedef deroy_list_t* deroy_list_pt;

为什么链表里面的data是void*呢,谭浩强的C语言不是这样教的啊

void类型是空类型,可以转成任意一种类型,你不知道你插入的数据的结构体是什么,或者说你要插入多种数据的结构体,确定的结构体已经不能够满足需求了,需要定义void*类型来指向你要添加进链表的结构体数据

我们需要实现一些函数来管理链表,注意o,前方高能,小白勿看

功能函数

 /*初始化链表*/
 deroy_list_pt deroy_list_create(void);
 /*插入节点*/
 int deroy_list_insert_before(deroy_list_t** list_head, int num, void* new_node_data);
 /*删除节点*/
 int deroy_list_delete(deroy_list_t** list_head, int num);
 /*修改节点*/
 int deroy_list_modify(deroy_list_t** list_head, int num, void* new_node_data);
 /*遍历节点*/
 void deroy_list_cuid(deroy_list_t* list_head, void (*do_function)(void*));
 /*查询数据 返回 数据的位置*/
 int deroy_list_search(deroy_list_t** list_head, void* find_data, int(*compare)(void*, void*));
 /*查询数据 返回 数据的指针*/
 void* deroy_list_find(deroy_list_t** list_head, void* find_data, int(*compare)(void*, void*))

为什么我要先把功能函数的原型给列举出来,因为你仔细看参数,双链表功能实现多次用到回调函数

什么是回调函数呢?

回调函数就是一个通过函数指针调用的函数。

怎么说呢,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数能够干什么?

你学过C++知道多肽吧,就是一个方法实现多个功能,回调函数就是C里面实现多肽的方式

举个栗子:

功能函数里面有个遍历所有节点的功能函数

 /*遍历节点*/
 void deroy_list_cuid(deroy_list_t* list_head, void (*do_function)(void*))
 {
     int i = 0;
     if (list_head == NULL || list_head->limit_size < 0)
     {
         errno = EINVAL;
         exit(errno);
     }
     for (i = 0; i < list_head->limit_size; i++)
     {
         (*do_function)(__deroy_list_visit(&list_head, i));
     }
 }

前面那个判断没啥可看的,直接看(*do_function)(__deroy_list_visit(&list_head, i));

__deroy_list_visit是个内联函数,它的功能就是返回list_head里面的第i个节点数据(void *data)

然后将数据给传入的do_function,让dofunction去处理data数据,核心层用户管理区实现dofunction

 /*回调函数 打印所以学生信息*/
 static void proxy_find_stu(deroy_data_pt pdata)
 {
     /*遍历学生信息*/
     if (pdata->type == STU)
     {
         printf(" %dt%dt%st%dt%dn", pdata->type, pdata->id, pdata->name, pdata->sex, pdata->rank);
     }
 }
 ​
 /*回调函数 root用户打印所有信息*/
 static void proxy_find_all(deroy_data_pt pdata)
 {
     /*遍历所有信息*/
     printf(" %dt%dt%st%dt%dt%d:t%sn", pdata->type, pdata->id, pdata->name, pdata->sex, pdata->rank, pdata->acount,pdata->password);
 }

通过对dofunction的实现,我们一个deroy_list_cuid函数可以遍历所有data的id段,还是不管什么数据都打印,这样就实现了root用户查看的权限更大

如果觉得这个直接两个函数实现不是更好吗,如果你想到这里,证明你还在思考,对,两个函数实现更方便,但是,那是核心层(自己写回调函数)去重新解释这个功能,达到了分层的概念

回叙这里的回调函数应用的不明显,这里还有个

 /*查询数据 返回 数据的位置*/
 int deroy_list_search(deroy_list_t** list_head, void* find_data, int(*compare)(void*, void*))
 {
     int counter = 1;
     deroy_node_pt current = NULL;
     if (list_head == NULL || *list_head == NULL)
     {
         errno = EINVAL;
         exit(errno);
     }
     if ((*list_head)->limit_size == 0)
     {
         return -1;  //无数据可查询   
     }
     current = (*list_head)->head;
     /*通过传入的comper函数进行比较*/
     while (compare(current->data, find_data) == 0 && current->next != NULL)
     {
         current = current->next;
         counter++;
     }
     if (current->next == NULL && compare(current->data, find_data) == 0)
         return 0;
     return counter;
 }

这里的的回调函数要求判断两个数据,返回真假

 /*回调函数 比较db_data_pt数据段的id是否相同*/
 static int proxy_compare_id(deroy_data_pt pdata, deroy_data_pt other)
 {
     if (pdata->id == other->id)
         return 1;
     return 0;
 }

通过核心层的用户管理去实现按id查找,还是其他查找方式,这里你总不能两个函数解决吧,必须也要分层

不能扯太远,咱说的是链表,继续..

双链表的实现,我之前发过一篇循环双链表,有图解,还算详细

这个双链表还算可以,没有内存泄漏(如果有请告诉我,反正我也不会去改),各种判断安全系数高,功能完善,能处理各种增删改查功能的系统设计

核心层:用户管理

啊~当时想着用双链表实现学生信息管理系统来着,码着码着就想把图书信息管理系统也码下来,比较学生信息管理系统已经烂大街了,我上个学生信息管理系统在知乎都有2000赞了

 #define STU 0
 #define TEACHER 1
 ​
 typedef enum Menu
 {
     Exit, Add, Show, Change, Delete, Search
 }MENU;
 ​
 typedef enum Sex
 {
     MAN, WOMAN
 }SEX;
 ​
 /*权限*/
 enum RANK
 {
     READ_ONLY   /*只读*/
     , WRITE     /*读写*/
     , ROOT      /*root可删除*/
 };
 ​
 /*学号、专业、姓名、年龄、性别属性。*/
 ​
 typedef struct deroy_data
 {
     char   type;    /*类型*/
     char   rank;    /*级别*/
     int    id;      /*编号*/
     char   name[10];    /*姓名*/
     char   sex;         /*性别*/
     int    acount;      /*账号*/
     char   password[20];    /*密码*/
     void*  data;        /*其他*/
     int(*Init)(struct deroy_data* pdata);
 }deroy_data_t;
 typedef deroy_data_t* deroy_data_pt;

没什么特殊的,甚至用户信息少的可怜,有点用处的就是权限了,然后看到deroy_data里面的void* data段了吗,没错,我就是想告诉你们,这个是扩展功能,可扩展用户的其他信息,这个我就不实现了,比较代码多了,你们看着挺烦的

然后这个结构体里面的函数指针,就相当于C++里面的方法,可以指向一个功能函数

然后就和之前的学生信息管理系统差不多了~

 /*学生信息管理系统*/
 int system_proxy_stu(deroy_list_pt ptlist,int user_rank)
 {
     rank = user_rank;
     while (1)
     {
         switch (menu_proxy_stu())   //菜单选择
         {
         case Exit:      //退出程序
             system("cls");
             printf("退出程序n");
             Quit();
             return 1;
             break;
         case Show:      //显示所有学生信息
             system("cls");
             if (rank == READ_ONLY)
             {
                 printf(" 类型t学号t姓名t性别t权限nn");
                 deroy_list_cuid(ptlist, proxy_find_stu);
             }
             else if(rank == ROOT)
             {
                 printf(" 类型t学号t姓名t性别t权限t账号:t密码nn");
                 deroy_list_cuid(ptlist, proxy_find_all);
             }
             Quit();
             break;
         case Add:       //添加学生信息
             init_proxy_stu(ptlist);
             Quit();
             break;
         case Change:    //修改学生信息
             proxy_stu_modify(ptlist);
             Quit();
             break;
         case Delete:    //删除学生信息
             proxy_stu_delete(ptlist);
             Quit();
             break;
         case Search:    //查询学生信息
             proxy_stu_find(ptlist);
             Quit();
             break;
         }
         system("cls");
     }
 }

把所有功能函数都实现了,并且功能函数都有权限设置

核心层:图书管理

这个图书管理实现的比用户管理还简单,我都没去设置权限问题,可自行设计

typedef enum BookMenu
{
    EXIT, ADD, SHOW, CHANGE, DELETE, SEARCH
}BOOKMENU;

/*图书编号、书名、图书分类、数量、出版日期、登记日期*/
typedef struct deroy_book
{
    int  iID;            /*序号*/
    char cId[4];         /*编号*/
    char cName[20];      /*书名*/
    char cSubject[20];   /*图书分类*/
    int  iNums;           /*数量*/
    char cPublish_data[20];/*出版日期*/
    char cData[20];        /*登记日期*/
    int(*Init)(struct deroy_book* pdata);   /*初始化函数*/
}deroy_book_t;
typedef deroy_book_t* deroy_book_pt;

简简单单的把基本的图书信息给列举出来,只需要实现功能函数即可

/*初始化图书数据*/
static void init_book_proxy_node(deroy_book_pt self)
/*注册图书*/
static void register_book_proxy_method(deroy_list_pt ptlist, void* pdata)
/*初始化图书信息*/
static void init_proxy_book(deroy_list_pt ptlist)
/*菜单选择*/
static int menu_proxy_book()
/*修改图书信息*/
static void proxy_book_modify(deroy_list_pt ptlist)
/*删除图书信息*/
static void proxy_book_delete(deroy_list_pt ptlist)
/*查找图书信息*/
static void proxy_book_find(deroy_list_pt ptlist)
/*图书信息管理系统*/
int system_proxy_book(deroy_list_pt ptlist)

这些个功能函数都挺简单的,都是围绕着之前设计的链表来实现的,详情可以看原码

这其实就是我将用户管理的代码复制过来,改void *data所指向的结构体deroy_book,几乎是一模一样的,所以说这是个模板,是个框架,框架定死了,你围绕着这个框架去实现功能就行

这里提个有趣的:就是图书注册日期,这里不用管理员去实现,直接sprintf(self->cData, "%s", __DATE__);__DATE__是一个宏,打印的是当前日期,打印的是年月日例如Jul 11 2020,这个宏我在C语言预处理那里提过,可惜看的人不多,

用户登录

首先主函数里面把两个核心层给创建咯,

	deroy_list_pt pStu_Head = deroy_list_create();	//创建用户
	deroy_list_pt pBook_Head = deroy_list_create();	//创建书籍

在创建用户的时候会创建两个用户对象,一个root、一个普通read_only,用于初始登录

登录就是去调用函数,接收函数的返回值

	int user_rank = load(pStu_Head);
	if (user_rank < 0)
	{
		printf("登录失败");
		return 0;
	}

这个返回值是用户的权限,用来层级之间交互

int load(deroy_list_pt phead)
{
	char account[20],password[20];	//账号密码
	printf("input acount:");
	scanf("%s", account);
	printf("password:");
	scanf("%s", password);
	deroy_data_t temp;
	temp.id = atoi(account);
	deroy_data_pt find_data = deroy_list_find(&phead, &temp, proxy_compare_load);
	if (find_data >= 0)
	{
		if (strcmp(password, find_data->password) == 0)
		{
			return find_data->rank;
		}
	}
	return -1;
}

之而立直接调用链表提供的方法deroy_list_find,自己实现回调函数

int proxy_compare_load(deroy_data_pt pdata, deroy_data_pt other)
{
	if (pdata->id == other->id)
		return 1;
	return 0;
}

为什么是找id而不是用户名呢,这里我懒了一下,直接将id赋值给account,整数方便,图个开心

公众号后台发送关键字「图书信息管理系统」获取源代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值