实现图书增删的代码_不仅仅是图书信息管理系统

点击蓝字 关注我们

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

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

效果演示

root用户:账号:0,密码:0

a24d37c48b81f54abc05ec09eafc8b82.gif

普通用户:账号:1001,密码:666666

e96cdcd286fdadeac9af28b0d84a85c9.gif

图书信息

f2eacb4cb15456cb3dc835617b3de2e4.gif

没有完全演示,只是个大概,微信gif只能300帧以内

框架结构

数据层:双链表管理

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

用户管理:

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

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

图书管理:

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

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

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

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

核心部分:双链表的实现

636abff6f9798dfb5a0334f96c0e04a5.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(" %d\t%d\t%s\t%d\t%d\n", pdata->type, pdata->id, pdata->name, pdata->sex, pdata->rank);
}
}

/*回调函数 root用户打印所有信息*/
static void proxy_find_all(deroy_data_pt pdata){
/*遍历所有信息*/
printf(" %d\t%d\t%s\t%d\t%d\t%d:\t%s\n", 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权限\n\n");
deroy_list_cuid(ptlist, proxy_find_stu);
}
else if(rank == ROOT)
{
printf(" 类型\t学号\t姓名\t性别\t权限\t账号:\t密码\n\n");
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,整数方便,图个开心

「公众号【编程学习基地】后台发送关键字「图书信息管理系统」获取源代码」

关键字【图书管理系统】

End


作者:梦凡梦想在,终不凡~你们的在看就是对我最大的肯定,点个在看好吗~
9483abb202735451befec49200b50869.png
编程学习基地常回基地看看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU1846 - Brave Game【巴什博弈】

十年前读大学的时候&#xff0c;中国每年都要从国外引进一些电影大片&#xff0c;其中有一部电影就叫《勇敢者的游戏》&#xff08;英文名称&#xff1a;Zathura&#xff09;&#xff0c;一直到现在&#xff0c;我依然对于电影中的部分电脑特技印象深刻。 今天&#xff0c;大家…

Ubuntu18.04换源更新国内源

参考&#xff1a;Ubuntu18.04更新国内源 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-05 10:24:11 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107808268 树莓派换源博文&#xff1a;https://blog.csdn.net/zhuguanlin121/article/d…

php中解析数组,在PHP中解析多维数组

您应该在将数据解析为Smarty之前准备好数据。你可以这样做&#xff1a;$result array(array(name > Hockey Team 1, category_id > 1),array(name > Hockey Team 2, category_id > 2),array(name > Hockey Team 3, category_id > 3),array(name > Footba…

了解jQuery并掌握jQuery对象和DOM对象的区别

jQuery的优势&#xff1a; 开源--开放源代码 轻量级 强大的选择器 出色的DOM操作(对DOM元素的一个增删改查) 完善的Ajax&#xff0c;出色的浏览器兼容性&#xff0c;丰富的插件支持&#xff0c;完善的文档&#xff08;说明书&#xff09; 链式操作方式&#xff0c; 写得少&…

linux下复制

复制文件 cp - i file tofile 复制目录 cp - r dic todic转载于:https://www.cnblogs.com/Hero-Qiang/archive/2013/03/20/2971579.html

rh php56 php,在全球范围内提供RHSCL PHP的最佳方法

我使用以下网址安装了RHSCL 2&#xff1a;使用RedHat订阅管理器.然后我运行yum删除php *,然后是yum install rh-php56一切顺利,除非现在找不到PHP.然后我运行find / -name php并在以下目录中找到rh-php56&#xff1a;/var/opt/rh/rh-php56/lib/php/opt/rh/rh-php56/register.co…

Vmware15的安装(ps解决:重装Vmware出现无法安装服务Vmware Authorization Service)

参考&#xff1a;Linux之Vmware的安装 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-07-09 22:13:14 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107238658 目录1.前言2.打开Vmware虚拟机安装包安装解决&#xff1a;重装Vmware出现无法…

python多线程模块_python 多线程模块参考

threading.active_count() 返回当前处于 active 状态的线程的数目 threading.current_thread() 返回调用者当前的 Thread 对象 threading.get_ident() 返回当前线程的“thread identifier”属性&#xff08;3.3新增&#xff09; threading.enumerate() 返回当前处于 active 状态…

谈谈即时通讯开发平台

由于即时通讯系统的复杂性和对服务器稳定性的很高要求&#xff0c;一般即时通讯系统开发至少需要1年左右的时间&#xff0c;而这还只是测试版&#xff0c;离"稳定"还有一定距离&#xff0c;而这时匆匆上马的不稳定的系统会让你失去用户&#xff0c;您也不可能召集上万…

内存,RAM(DDR),ROM(EEPROM、flash),存储卡(emmc,sd,tf)以及Cache的区别与联系

参考&#xff1a;内存&#xff0c;RAM&#xff0c;ROM&#xff0c;Cache的区别与联系 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-09-26 09:55:40 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108808106 参考&#xff1a;EEPROM和flash…

PHP数据库可视化分析工具,5个MySQL GUI工具推荐,帮助你进行数据库管理

MySQL的数据库管理工具非常多&#xff0c;有哪些优秀的GUI工具可以帮助提高工作效率?不妨看一看这5个MySQL GUI工具。1、Navicat for MySQLNavicat for MySQL是数据库管理工具&#xff0c;与MySQL&#xff0c;MariaDB和云数据库兼容&#xff0c;是目前非常受欢迎的数据库前端用…

idea 项目jar反编译java_带你上手阿里开源的 Java 诊断利器:Arthas

本文适合有 Java 基础知识的人群。本文作者&#xff1a;HelloGitHub-秦人HelloGitHub 推出的《讲解开源项目》系列&#xff0c;今天给大家带来一款阿里开源的 Java 诊断利器 Arthas 项目—— Arthas项目源码地址&#xff1a;https://github.com/alibaba/arthas一、简介 为什么要…

22Java之JDBCTemplate总结

写在前面&#xff1a;这里总结4种方式来操作数据库&#xff08;SE阶段&#xff09; 一、JDBC JDBC有关的类&#xff1a;都在java.sql 和 javax.sql 包下.1.数据准备 这里假设已经在数据库中新建立了mydb4数据库&#xff0c;并且也插入了一些数据&#xff0c;并且还需要导入一个…

福布斯评科技未来五大趋势:电脑消失融入生活时间

福布斯评科技未来五大趋势&#xff1a;电脑消失融入生活时间 谈趋势似乎并不讨巧&#xff0c;因为所谓趋势通常都是指时尚。每每谈及趋势&#xff0c;人们立刻就会想到穿着夸张服饰在T台上昂首阔步的模特&#xff0c;但每当下一季的新款推出&#xff0c;再华丽的时装都会很快…

Windows如何开启虚拟化,以安装虚拟机?

参考&#xff1a;Windows如何开启虚拟化&#xff0c;以安装虚拟机&#xff1f; 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-28 20:58:45 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/108286787 设置BIOS 安装 Ubuntu 时报错&#x…

php生成文件index.html,Typecho生成静态首页index.html文件

Typecho生成静态首页index.html文件作者&#xff1a;佚名来源&#xff1a;爱好者时间&#xff1a;2019-11-02在挨踢路看到的教程&#xff0c;不仅仅适用于Typecho&#xff0c;wordpress也是可以通用。教程在网站根目录新建文件f5.php然后里面写入下面的代码。$nowtimetime();$p…

python语言1002python语言_PYTHON语言学习

PYTHON 语言学习 通过两个星期的自学 python 语言&#xff0c;初步了解到 python 的知识构架。它比 C 语言和 C 语 言在某种程度上来说要简单些&#xff0c; 但是也有很多我不懂的东西。 陈老师给我安排的课堂任务是 第 21 章的 Database Programming &#xff0c;通过 python …

python数据结构之栈

栈栈&#xff08;stack&#xff09;&#xff0c;有些地方称为堆栈&#xff0c;是一种容器&#xff0c;可存入数据元素、访问元素、删除元素&#xff0c;它的特点在于只能允许在容器的一端&#xff08;称为栈顶端指标&#xff0c;英语&#xff1a;top&#xff09;进行加入数据&a…

Ubuntu 16.04安装教程及虚拟机设置

摘自&#xff1a;Ubuntu 16.04安装教程及设置 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-07-09 22:36:50 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107239119 配合这篇博文&#xff1a;安装ubuntu20.04并进行优化——安装vim,gcc,…

matlab vision工具箱使用手册,matlab-Computer Vision System ToolBox的系统对象使用

在MATLAB中&#xff0c;调用计算机视觉工具箱中的vision.GeometricScaler可实现对输入图像的缩放变换。 vision.GeometricScaler的具体使用方法如下&#xff1a; vision.GeometricScaler 功能&#xff1a;对图像进行几何尺寸的放缩&#xff1b; 语法&#xff1a;A step(vision…