目录

技术路线

实现效果展示

​程序主体

1.头文件部分

2.自定义函数定义部分

3.main函数部分

注意


技术路线

数据结构、哈希表、文件IO

通过C语言进行程序设计,有用到数据结构中的哈希表,通过哈希表对图书进行有规则地存放,并且使用文件IO的操作实现对图书馆中各种图书信息的更改。系统分为分有一个主界面和多个子界面,实现后的效果可以界面切换自如,子界面中设计有学生入口以及管理员入口,管理员入口的进入需要输入账号密码,这些功能都是结合实际设计的,实现的功能有,在管理员端可以实现对图书的入库、出库、图书的查询(编号查询、书名查询),其实就是对图书信息文件的读写操作,只需要定时更新数据即可,另外,在学生用户入口,该工程实现了借书系统和还书系统。


实现效果展示

每次的进入,都会实时显示共有的藏书和已经借出的书,在设计的时候,每经过一次管理员或者学生的操作,都会实时更新图书馆数据的.txt文件,进行重新写入,所以能做到实时性。

关于哈希表,哈希函数的设计,本项目是通过书本的编号,进行对书本编号值的不同,经由哈希函数处理,然后所得下标作为对应的在哈希表中的位置。

进行数据的查询,实际上是做了一种对图书馆图书数据文件的读取,然后进行一个匹配的过程


 程序主体


 头文件部分

#ifndef _LIBRARY_H
#define _LIBRARY_H#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>#define N 26    //哈希表中所要创建的指针数组大小
enum res
{HASHNULL = -4,MALLOCERROR,FAIL,FLAG,OK,
};//定义一个学生信息结构体(借书)
typedef struct Stu
{char name[30];//学生姓名int ID;        //学生学号char data[30];  //借出的时间
}stu;
//书籍借出时间如果能直接调用系统时间自然是最好的。(这个是我努力优化的方向)//定义一个图书信息结构体
typedef struct Book
{char number[20];//编号也是和书的信息相关,如A13-1-2022,哈希检索时用的是这个第一个字母的阿斯克码值char name[30];//书名char place[30];//固定格式,如:A区13号书架上层stu state;  //用学生信息定义状态说明,有信息表已借出,无信息表示未借出
}data_type;//哈希表的节点
typedef struct Linknode
{data_type book;struct Linknode *pnext;
}lknode;//哈希表构成
typedef struct Hash
{lknode *arr[N];int count;
}hash;hash *createHash();
int hashfun(char *number);
int insertBook(hash *phash,data_type item);
int deleteBook(hash *phash,char *bknumber);
void showInformation(lknode *pnode);
int searchbook1(hash *phash,char *bkname);
int searchbook2(hash *phash,char *bknumber);
stu change_data(lknode *ptemp);
int borrow_book(hash *phash,char *bkname);
int return_book(hash *phash,char *bknumber);
int destoryHash(hash **phash);void show_bknumber(hash *phash);
int developer_information();
int load(hash *phash);
int update(hash *phash);
int interface1(hash *phash);
int interface2(hash *phash);int judge(int id);#endif

 自定义函数定义部分


此处将所有的自定义函数都放一块了

#include"../include/library.h"//创建哈希表
//创建一个哈希表数据类型的指针,并通过malloc开辟空间
hash *createHash()
{hash *phash = NULL;phash = (hash *)malloc(sizeof(hash));if(NULL == phash){perror("malloc error");return NULL;}memset(phash,0,sizeof(hash));//哈希表初始化return phash;
}//定义哈希表规则
int hashfun(char *number)
{int a = number[0];return a-65;
}//图书入库,向哈希表填入元素
int insertBook(hash *phash,data_type item)
{if(NULL == phash){return HASHNULL;}int index = hashfun(item.number);//通过哈希函数获得存储下标//创建存储图书信息的链表节点lknode *pnew = (lknode*)malloc(sizeof(lknode));if(NULL == pnew){perror("malloc error");return MALLOCERROR;}memset(pnew,0,sizeof(pnew));pnew->book = item;//结构体变量的直接赋值//将新增的图书信息节点插入链表,先保障后面不丢失pnew->pnext = phash->arr[index];//头插法phash->arr[index] = pnew;phash->count++;        //插入一本图书后,库里的图书总数加一return OK;
}//书籍出库(删除书),通过书的编号给书办理出库
int deleteBook(hash *phash,char *bknumber)
{   if(NULL == phash){return HASHNULL;}int pos = hashfun(bknumber);//头节点这有点特殊,单独拿出来判断了    lknode *phead = phash->arr[pos];if(0 == strcmp(phead->book.number,bknumber)){phash->arr[pos]  = phead->pnext;return OK;}int i;lknode *ptemp;for(i = 0;i < N;i++){ptemp = phash->arr[i];while(NULL != ptemp){if(0 == strcmp(ptemp->pnext->book.number,bknumber))//ptemp只定位到要删除节点的前一个{lknode *pnew_temp = ptemp->pnext;//新定义的这个指针指向要删除的节点处ptemp->pnext = pnew_temp->pnext;free(pnew_temp);phash->count--;return OK;}     ptemp = ptemp->pnext;}}printf("所要删除书籍不存在");return FAIL;
}//图书查询,显示哈希表某一节点的信息(也就是某一本书的信息),要借书你肯定是要查位置的
//通过书名找书
int searchbook1(hash *phash,char *bkname)
{if(NULL == phash){return HASHNULL;}int i;lknode *ptemp;//以下程序是遍历哈希表for(i = 0;i < N;i++){ptemp = phash->arr[i];while(NULL != ptemp)//最后一个尾节点也是一本书,也得判断进去{printf("%s\n",bkname);if(0 == strcmp(ptemp->book.name,bkname)){showInformation(ptemp);return OK;}       ptemp = ptemp->pnext;}}//在经历了上一个遍历判断后没找见的话说明就没有这本书printf("图书馆没有这本书\n");return FAIL;
}
//通过书籍编号查找
int searchbook2(hash *phash,char *bknumber)
{if(NULL == phash){return HASHNULL;}int i;lknode *ptemp;for(i = 0;i < N;i++){ptemp = phash->arr[i];while(NULL != ptemp)//最后一个尾节点也是一本书,也得判断进去{if(0 == strcmp(ptemp->book.number,bknumber)){showInformation(ptemp);return OK;}       ptemp = ptemp->pnext;}}//在经历了上一个遍历判断后没找见的话说明就没有这本书printf("图书馆没有这本书\n");return FAIL;
}//打印节点信息,也就是显示一本书的信息
void showInformation(lknode *pnode)
{printf("书名:%s\n",pnode->book.name);printf("书籍编号:%s\n",pnode->book.number);printf("存放位置:%s\n",pnode->book.place);if(0 == pnode->book.state.ID){printf("书籍未借出\n");}else{printf("书籍已出借\n");printf("出借人:%s\n",pnode->book.state.name);printf("出借人学号:%d\n",pnode->book.state.ID);printf("出借时间:%s\n",pnode->book.state.data);}
}//借书函数int borrow_book(hash *phash,char *bkname)
{if(NULL == phash){return HASHNULL;}int i;lknode *ptemp;//以下程序是遍历哈希表for(i = 0;i < N;i++){ptemp = phash->arr[i];while(NULL != ptemp)//最后一个尾节点也是一本书,也得判断进去{if(0 == strcmp(ptemp->book.name,bkname)){ptemp->book.state = change_data(ptemp);return OK;}       ptemp = ptemp->pnext;}}printf("图书馆中没有这本书\n");return FAIL;
}//借书时改变一个节点的数据,写入借阅者信息
//传入的参数是一个节点
stu change_data(lknode *ptemp)
{       stu student;memset(&student,0,sizeof(stu));printf("--------------信息登记--------------\n");printf("姓名:");scanf("%s",student.name);printf("学号:");scanf("%d",&student.ID);printf("借阅时间:");scanf("%s",student.data);return student;
}//还书函数
//通过书籍编号先找到
int return_book(hash *phash,char *bknumber)
{if(NULL == phash){return HASHNULL;}int i;lknode *ptemp;for(i = 0;i < N;i++){ptemp = phash->arr[i];while(NULL != ptemp)//最后一个尾节点也是一本书,也得判断进去{if(0 == strcmp(ptemp->book.number,bknumber)){memset(&(ptemp->book.state),0,sizeof(stu));printf("还书成功");return OK;}       ptemp = ptemp->pnext;}}printf("未匹配到书籍信息,请检查是否输入有误\n");return FAIL;
}//释放哈希表
int destoryHash(hash **phash)
{if(NULL == *phash){return HASHNULL;}lknode *ptemp1 = NULL;lknode *ptemp2 = NULL;int i;for(i = 0; i < N; i++){ptemp1 = ptemp2 = (*phash)->arr[i];while(NULL != ptemp2){ptemp1 = ptemp1->pnext;free(ptemp2);ptemp2 = ptemp1;} }free(*phash);*phash = NULL; return OK;
}//---------------------------------------以下是主函数界面下的一些函数封装--------------------------------------------
//--------------------------------------包括,导入库,导出库,操作界面函数-------------------------------------------//每次开启之前你要做图书信息库的导入
int load(hash *phash)
{  data_type bookdata;//文件IO操作时用作缓存int fo = open("library.txt",O_RDONLY | O_CREAT ,0664);//打开数据库文件,不存在就创建if(fo < 0){perror("open error");return FAIL;}else{while(1){int fr = read(fo,&bookdata,sizeof(data_type));if(0 == fr){break;}else if(fr < 0){perror("read error");return FAIL;}else{insertBook(phash,bookdata);}}}close(fo);//图书数据导入完后关闭程序return OK;
}//操作结束后的图书馆数据库更新
int update(hash *phash)
{int fo = open("library.txt",O_WRONLY);if(fo < 0){perror("open error");}else{int i;for(i = 0; i < N; i++){lknode *ptemp = phash->arr[i];while(NULL != ptemp){int fw = write(fo,&(ptemp->book),sizeof(data_type));if(fw < 0){perror("write error");}ptemp = ptemp->pnext;}}}return OK;
}//管理员界面的子函数,通过主界面调用该函数,主界面函数放在了主函数里
int interface1(hash *phash)
{int op,op2;data_type item;memset(&item,0,sizeof(data_type));char bknumber[30]="\0";int flag = 0;system("clear");while(1){system("clear");printf("------------管理员用户模式------------\n\n");printf("(1)图书入库登记\n\n");printf("(2)图书出库删除\n\n");printf("(3)返回\n");scanf("%d",&op);switch(op){case(1):printf("请输入图书编号(格式如A13-1-2002):");scanf("%s",item.number); printf("请输入书籍名称:");scanf("%s",item.name);printf("请输入图书存放位置:");scanf("%s",item.place);flag = insertBook(phash,item);if(OK == flag){printf("--------------入库成功--------------\n");}else{printf("--------------入库失败--------------\n");}printf("press 1 continue\n");place1:scanf("%d",&op2);if(1 == op2){break;}else{goto place1;}case(2):printf("请输入出库图书编号:");scanf("%s",bknumber);flag = deleteBook(phash,bknumber);if(OK == flag){printf("--------------出库成功--------------\n");}else{printf("--------------出库失败--------------\n");}printf("press 1 continue\n");place2:scanf("%d",&op2);if(1 == op2){break;}else{goto place2;}case(3):return FLAG;}}return OK;
}//学生用户界面的子函数,通过主界面调用该函数,主界面函数放在了主函数里
int interface2(hash *phash)
{int op,op2;char bknumber[30]="\0";char bkname[30]="\0";int flag = 0;system("clear");while(1){system("clear");printf("------------学生用户模式----------------\n\n");printf("(1)书籍查询(书名查询)\n\n");printf("(2)书籍查询(编号查询)\n\n");printf("(3)借书\n\n");printf("(4)还书\n\n");printf("(5)返回\n");scanf("%d",&op);switch(op){case(1):printf("请输入你要查询的书名:");scanf("%s",bkname);flag = searchbook1(phash,bkname);if(OK == flag){printf("--------------查询成功--------------\n");}else{printf("--------------查询失败--------------\n");}printf("press 1 continue\n");place3:scanf("%d",&op2);if(1 == op2){break;}else{goto place3;}case(2):printf("请输入你要查询的书籍编号:");scanf("%s",bknumber);flag = searchbook2(phash,bknumber);if(OK == flag){printf("--------------查询成功--------------\n");}else{printf("--------------查询失败--------------\n");}printf("press 1 continue\n");place4:scanf("%d",&op2);if(1 == op2){break;}else{goto place4;}case(3):printf("请输入要借阅的书名:");scanf("%s",bkname);system("clear");flag = borrow_book(phash,bkname);if(OK == flag){printf("--------------借阅成功--------------\n");}else{printf("--------------借阅失败--------------\n");}printf("press 1 continue\n");place5:scanf("%d",&op2);if(1 == op2){break;}else{goto place5;}case(4):printf("请输入归还书籍编号:");scanf("%s",bknumber);flag = return_book(phash,bknumber);if(OK == flag){printf("--------------归还成功--------------\n");}else{printf("--------------归还失败--------------\n");}printf("press 1 continue\n");place6:scanf("%d",&op2);if(1 == op2){break;}else{goto place6;}case(5):return FLAG;}}return OK;
}//显示图书馆中藏书总量,以及借出总数
void show_bknumber(hash *phash)
{printf("(馆内共有藏书%d本,",phash->count);int i,num=0;lknode *ptemp;//以下程序是遍历哈希表for(i = 0;i < N;i++){ptemp = phash->arr[i];while(NULL != ptemp)//最后一个尾节点也是一本书,也得判断进去{if(0 != ptemp->book.state.ID){num++;}        ptemp = ptemp->pnext;}}printf("已借出%d本)\n",num);}//显示版本信息
int developer_information()
{int op;system("clear");printf("版本号:图书管理系统1.0\n\n");printf("开发者:22041吴泽翔\n\n");printf("地址:华清远见西安中心\n\n");printf("联系方式:0914-2338030\n\n");printf("\t\t按1返回\n");scanf("%d",&op);if(1 == op){return FLAG;}else{return FAIL;}
}//输入密码判断是否可进入管理员模式
int judge(int id)
{int mima = 0;int op;begin:system("clear");printf("密码:");scanf("%d",&mima);if(id == mima){return OK;}else{printf("密码有误\n");printf("\n");}printf("重输请按1,返回上一级请按2\n");printf("请输入你的选择:");mid:scanf("%d",&op);if(1 == op){goto begin;}else if(2 == op){return FLAG;}else{printf("输入有误,请重新输入:");goto mid;}}/*
//--------------------------------------------进入管理员界面的密码设计------------------------------------------------//
//---------------------------------用到了密码本的导入,可以修改密码,更新密码本--------------------------------------//-
//----------------------------------------------该功能尚未实现完成---------------------------------------------------//
//每次开启之前进行账号密码的导入
int loadPassword(id pw)
{  int fo = open("password.txt",O_RDONLY | O_CREAT ,0664);//打开数据文件,不存在就创建if(fo < 0){perror("open error");return FAIL;}else{int fr = read(fo,&pw,sizeof(id));if(fr < 0){perror("read error");return FAIL;}          }close(fo);return OK;
}//操作结束后的密码数据库更新
int updatePassword(id pw)
{int fo = open("password.txt",O_WRONLY);if(fo < 0){perror("open error");return FAIL;}else{int fw = write(fo,&pw,sizeof(id));if(fw < 0){perror("write error");return FAIL;}     }return OK;
}int judge()
{int mima = 0;int op;begin:system("clear");printf("密码:");scanf("%d",&mima);if(password == mima){return OK;}else{printf("密码有误\n");printf("\n");}printf("重输请按1,返回上一级请按2\n");printf("请输入你的选择:");mid:scanf("%d",&op);if(1 == op){goto begin;}else if(2 == op){return FLAG;}else{printf("输入有误,请重新输入:");goto mid;}}
*/

 main函数部分


#include"../include/library.h"int main()
{hash *phash = createHash();//创建哈希表  load(phash);//每次开启之前你要做图书信息库的导入int id = 123;//设定管理员模式的密码int op;int flag;while(1){       start:system("clear");system("date");printf("\n");printf("欢迎使用图书管理系统");show_bknumber(phash);printf("\n");printf("(1)管理员用户入口\n\n");printf("(2)学生用户入口\n\n");printf("(3)版本信息\n\n"); printf("(4)退出系统\n\n");scanf("%d",&op);if(4 == op){break;}switch(op){case(1):flag = judge(id);if(flag == FLAG){goto start;}flag = interface1(phash);if(flag == FLAG){goto start;}       break;      case(2):flag = interface2(phash);if(flag == FLAG){goto start;}break;  case(3):flag = developer_information();if(flag == FLAG){goto start;}       break;}}update(phash);//操作结束后,更新图书库的信息destoryHash(&phash);//销毁哈希表return 0;
}

注意

该工程是在linux环境下编写的,部分函数可能windows下没有,倘若你是windows环境,该文档仅供参考。

另:若使用者需运行该程序,仍需自己新建工程,配置合适的Makefile文件,进行工程文件的运行

希望这篇文章能够给你提供帮助,如有问题,还请指出,我会及时更改,谢谢大家。

图书馆管理系统(C、数据结构、哈希表、文件IO)相关推荐

  1. 算法笔记(三)特殊数据结构——哈希表、有序表、并查集、KMP、Manacher、单调栈、位图、大数据类题

    layout: post title: 算法笔记(三)特殊数据结构--哈希表.有序表.并查集.KMP.Manacher.单调栈.位图.大数据类题 description: 算法笔记(三)特殊数据结构- ...

  2. java hashtable 数据结构_数据结构--哈希表(Java)

    数据结构--哈希表(Java) 介绍 哈希表 底层是 数组加链表 或者是 数组加二叉树 ,一个数组里面有多个链表,通过散列函数来提高效率 代码 package cn.guizimo.hashtab; ...

  3. Python中常用的数据结构---哈希表(字典)

    Python中常用的数据结构-哈希表(字典) 常用的数据结构有数组.链表(一对一).栈和队列.哈希表.树(一对多).图(多对多)等结构. 在本目录下我们将讲解,通过python语言实现常用的数据结构. ...

  4. 数据结构——哈希表的详解与实现

    数据结构--哈希表(HashTable) 1.前言 ​ 当我们频繁的查找数据中的某个元素时,我们通常会选择数组来存放数据,因为数组的的内存是连续的,可以直接通过下标访问数据,但是它添加和删除数据比较麻 ...

  5. 数据结构哈希表的实现与设计

    数据结构哈希表查找姓名的课程设计 有没有大神能帮忙写一下这道题,课设的题目.用C++语言 问题描述:针对某公司中花名设计哈希表,并完成相应的建表和查表程序,基本要求: (1)假设花名为汉字拼音形式.名 ...

  6. 数据结构 — 哈希表

    目录 文章目录 目录 哈希表 哈希表 哈希表,又称为散列表,是根据键值对(Key/Value)进行访问的数据结构,它让 Value 经过哈希函数的转换映射到哈希表对应的位置上,查找效率非常高.哈希索引 ...

  7. 哈希表数据结构_算法与数据结构-哈希表

    前面我们已经讲到了数组和链表,数组能通过下标 O(1) 访问,但是删除一个中间元素却要移动其他元素,时间 O(n). 循环双端链表倒是可以在知道一个节点的情况下迅速删除它,但是吧查找又成了 O(n). ...

  8. 哈希表数据结构_Java数据结构哈希表如何避免冲突

    前言 一.哈希表是what? 这是百度上给出的回答: 简而言之,为什么要有这种数据结构呢? 因为我们想不经过任何比较,一次从表中得到想要搜索的元素.所以就构造出来了哈希表,通过某种函数(哈希函数)使元 ...

  9. openssl lhash 数据结构哈希表

    哈希表是一种数据结构,通过在记录的存储位置和它的关键字之间建立确定的对应关系,来快速查询表中的数据: openssl lhash.h 为我们提供了哈希表OPENSSL_LHASH 的相关接口,我们可以 ...

  10. 数据结构-----------------------哈希表(最通俗易懂的文章)

    哈希表 简要 通俗来讲,哈希表是通过函数 (映射关系) 来直接寻找表中存储的关键字,哈希表也是一种数据结构,它是表结构的一种升级拓展,哈希就是一种函数映射,表是一种数据结构,那么合起来就叫哈希表 那么 ...

最新文章

  1. 重磅《美国机器智能国家战略》
  2. 今天mtk笔试,没信心了
  3. 人脸识别可以分辨同性恋?论科技研发和伦理道德之间的矛盾
  4. 常用来进行钢结构节点输出的软件是什么_Revit中如何处理钢结构节点连接
  5. mapgis编辑属性结构编辑不了_MapGIS67操作手册(3-17)MapGIS67编辑线属性结构的方法...
  6. sql数据库备份默认路径_在Linux上SQL Server中更改默认数据库文件和备份路径
  7. [py][mx]django分页第三方模块django-pure-pagination
  8. 荐一个不错的UI设计网站: uimaker
  9. 知识分享|日本面试常考问题+巧妙回答①
  10. [挑战杯] 火焰检测
  11. 树莓派开发—语音识别功能
  12. Win7激活工具无效?输入SLMGR -REARM显示不是内部命令?
  13. 不行不行,不能再讨厌英语了,要爱上英语。。。I Love You。。。
  14. 微信小程序分享功能(微信好友,朋友圈)
  15. Linux进程间通信(上)
  16. ARM架构SMMU驱动详解
  17. PCIe(二)——TLP包构成
  18. FCN训练不收敛的原因分析和最详细的FCN训练与测试自己的数据程序配置
  19. 计算机病毒相关试题,计算机病毒类考试题目以及参考答案
  20. 搭建个人的Leanote云笔记本

热门文章

  1. 面试题之利用call或者apply实现bind功能
  2. react native 出现程序包com.facebook.react不存在
  3. PostGIS中geometry与geography的区别
  4. wsl linux 桌面_(Windows)桌面上Linux年-WSL技巧和窍门
  5. DotCode二维码基本概念
  6. 4、Python基本数据类型之字典,集合
  7. 【CSS】内联样式,内部样式表,外部样式表
  8. Java面试锦囊(五)
  9. shell - 01 - Shell入门:扎好马步 走的更稳
  10. springCloud 之 Hystrix 熔断器