目录
一、题目概述
设计一个图书馆管理系统,实现书籍的添加、查询、借阅和归还等功能。要求使用合适的数据结构来存储书籍信息,如书名、作者、出版社、ISBN号等,并能够实现高效的查询和借阅操作。
背景:
1.技术背景:
现代图书馆系统的发展得益于互联网平台、物联网平台、大数据技术、信息技术等现代高科技技术的进步。这些技术的发展为智慧图书馆的实现提供了坚实的技术基础。
2.人文背景:
智慧图书馆的发展不仅仅是技术的进步,更是科学技术与人文精神的有机结合。它强调以人为本的服务理念,旨在通过技术手段提升图书馆的服务质量,满足广大人民的需求。
3.社会背景:
图书馆的工作随着社会需求的变化而变化。在信息化时代,图书馆不仅提供图书借阅服务,还注重提供人性化、个性化的现代服务,以满足不同读者的需求。
4.特点和优势:
图书馆管理系统实现了图书馆管理流程的自动化,减少了人工操作,提高了工作效率,降低了管理成本。同时,系统可以对图书借阅情况、读者使用情况等数据进行统计和分析,为图书馆决策提供科学依据。
意义:
提高管理效率:传统的图书管理方式需要手动记录、查询和统计,效率低下且易出错。而图书管理系统可以自动完成这些工作,提高管理效率和准确性。
方便用户借阅:图书管理系统可以通过电子化的方式提供图书查询和借阅服务,方便用户随时随地查询和借阅图书。
满足管理员需求:通过对图书馆组织和图书馆系统工作的研究,以此来满足图书管理员的不同需求,激发管理员的工作热情,让管理员能够得到全面的发展。
实现资源共享和合理配置:一个良好的图书管理系统必须拥有友好便捷的系统用户界面,使该界面操作简单便捷,能够满足城市图书馆以及各大院校的日常业务处理需求。不仅能够减轻管理人员的劳动强度,提高其工作效率,还可以给读者查阅信息提供便利,使图书馆资源得到充分利用与合理配置,明确分配图书馆人员的分工,使采购图书的流程更为合理化,从而增强图书馆资源的共享性和流动性
二、需求分析
1. 选择合适的数据结构存储书籍信息,如链表、数组或树形结构。
2. 设计高效的查询算法,以便根据书名、作者等关键信息快速定位书籍。
3. 实现借阅和归还功能,需要维护借阅记录,包括借阅人、借阅时间等信息。
三、总体设计
本程序的任务是实现一个图书信息管理系统,主要功能包括添加图书信息、删除图书信息、显示所有图书信息、借阅图书和归还图书。输入形式为键盘输入,输入值的范围应符合实际情况。输出形式为控制台输出。程序所能达到的功能应能够满足用户的需求。测试数据应包括正确的输入及其输出结果和含有错误的输入及其输出结果。
本程序的主程序流程为:显示菜单,根据用户输入的选项执行相应的操作,直到用户选择退出为止。
遇到的问题及解决方案:
1.代码可维护性问题:
解决方案:
遵循良好的编程规范,如使用注释、合理组织代码结构、避免重复代码等。进行代码审查,及时发现并修复潜在问题。
2.如何设计一个直观、易用的用户界面,以便用户能够轻松地进行图书的查询、借、归还等操作?
解决方案:
进行用户测试,收集反馈,并根据反馈迭代改进界面设计。提供清晰的操作指南和帮助文档,以便用户能够快速上手。
3.系统崩溃或无响应:
解决方案:
确保系统有足够的资源来处理当前的任务,避免超时和内存泄漏。进行压力测试,找出系统瓶颈并优化。
4.前端界面问题:
解决方案:
检查前端代码是否存在错误,如乱码、404错误等。确保Tomcat配置正确,特别是字符编码设置。
5.业务逻辑问题:
解决方案:
理清业务流程,确保程序逻辑正确。例如,在处理图书借阅时,需要正确更新书籍的可借阅数量和读者的借阅记录。
6.性能问题:
解决方案:
使用性能优化技巧,如避免不必要的对象创建和销毁、优化循环结构、使用缓存等。对应用程序进行性能测试和分析,找出性能瓶颈并进行优化。
四、详细设计
1.主要函数清单:
InputNode():上传图书信息,包括图书的编号、作者、数量和介绍
入口参数:图书相关信息
出口参数:表示上传图书信息成功
Sreach(bth):根据输入的图书编号进行查找相同的图书编号信息
入口参数:图书编号
出口参数:表示查找是否成功
Insert_BookInfo(bth):输入图书信息并编号进行查找
入口参数:图书编号
出口参数:表示对已有图书数量进行修改
Delete_BookInfo(bth):输入相应图书编号实现将图书信息从图书馆中删除
入口参数:图书编号
出口参数:表示删除书籍是否成功
Output_BookInfo(bth):显示图书馆中所有的图书信息
入口参数:数值
出口参数:表示图书馆中所有的图书信息
Borrow_TheBook(bth):输入相应图书编号实现借阅
入口参数:图书编号
出口参数:表示借阅是否成功
TurnBack_TheBook(bth):输入相应图书编号实现归还
入口参数:图书编号
出口参数:表示归还是否成功
2.函数调用关系描述:
主程序调用图书信息管理类中的各个程序。即在程序启动时分别在主函数main中用switch语句调用所需函数。例如在上传图书信息时调用InputNode()函数、在借阅图书时调用Borrow_TheBook(bth)函数、在归还图书时调用TurnBack_TheBook(bth)函数等。
五、代码实现
#include "iostream"
#include "string"
#include "conio.h"
using namespace std;
struct Date {//日期结构
int m_nYear;//年
int m_nMonth;//月
int m_nDay;//日
};
struct Reader {//读者结构
string name;//读者姓名
Date bro;//借出时间
Date back;//归还时间
};
struct Book {//图书结构
int m_nBook_Number;//图书编号
string m_strTitle;//书名
string m_strWroter;//作者
int m_nMoreNum;//当前在图书馆数量
int m_nTotalHoldNum;//图书馆共计数量
string m_sttrComment;//图书介绍
Reader reader[20];
};
struct Info {//借书信息结构
Info* m_pParentPoint;//前驱节点
Book* m_oBookInfo;//对应图书信息
Info* m_pNextPoint;//后继节点
};
Book* InputNode() {
//上传图书
Book* p = new Book;//动态分配一片大小为sizeof(Book)字节的空间,并将该内存空间的起始位置赋值给p
system("cls");//清屏
fflush(stdin);//清楚以前的输入
cout << "请输入图书编号:"; cin >> p->m_nBook_Number;
cout << "请输入图书:"; cin >> p->m_strTitle;
cout << "请输入作者:"; cin >> p->m_strWroter;
cout << "请输入当前在图书馆数量:"; cin >> p->m_nMoreNum;
cout << "请输入图书馆共计数量:"; cin >> p->m_nTotalHoldNum;
cout << "请输入图书介绍:"; cin >> p->m_sttrComment;
for (int i = 0; i < 20; i++) {//初始化书本结构成员中相关读者指针内容为空
(p->reader[i]).name = '\0';
}
return p;//返回成功读入的书本信息
}
Info* Sreach(Info* bth, int x, int* k, int* flag) {
//搜索图书
Info* p = bth;
*flag = 0;
while (p) {
if (p->m_oBookInfo->m_nBook_Number == x) {//寻到相同的图书编号
*flag = 1;
return p;
}
else {
*flag = 0;
}
if (p->m_pNextPoint != NULL) {
p = p->m_pNextPoint;
}
else {
break;
}
}
return bth;
}
Info* Insert_BookInfo(Info* bth) {
//上传图书
int flag, k, x;
cout << "请输入您想上传的图书编号:";//按照书本编号进行查找
cin >> x;
Info* p = Sreach(bth, x, &k, &flag);
if (flag == 1) {//找到直接对已有的数量进行修改
cout << "当前图书馆内拥有这本书" << p->m_oBookInfo->m_nMoreNum << "本,您想在增加一本" << p->m_oBookInfo->m_strTitle << "书?(Y/N)" << endl;
char ch;
cin >> ch;
if (ch == 'Y' || ch == 'y') {
p->m_oBookInfo->m_nMoreNum++;
p->m_oBookInfo->m_nTotalHoldNum++;
cout << "增加后图书馆内拥有这本书" << p->m_oBookInfo->m_nMoreNum << "本,一共拥有" << p->m_oBookInfo->m_nTotalHoldNum << "本" << endl;
}
return bth;
}
//图书管内未找到这本图书编号
Book* r = InputNode();
if (bth == NULL) {//当bth指针为空时,需要对其进行单独处理,链表表头内存的分配
bth = new Info;
bth->m_pParentPoint = NULL;
bth->m_oBookInfo = r;
bth->m_pNextPoint = NULL;
}
else {
//说明存在头指针
p = bth;
while (p->m_pNextPoint != NULL)
p = p->m_pNextPoint;
Info* q = new Info;
q->m_oBookInfo = r;
q->m_pNextPoint = NULL;
q->m_pParentPoint = p;
p->m_pNextPoint = q;
}
return bth;
}
Info* Delete_BookInfo(Info* bth) {
//删除图书
int flag, k, x;
cout << "请输入您想删除的图书编号:";//按照书本编号进行查找
cin >> x;
Info* p = Sreach(bth, x, &k, &flag);
if (flag == 0) {//为查找图书编号
cout << "图书馆内并没有这本书!!!" << endl;
return bth;
}
else {
if (p == NULL) {//确保当前操作是有效的,防止出现非法操作
cout << "查找错误" << endl;
return bth;
}
else {
cout << "你想删除的图书信息如下:" << endl;
cout << "图书编号:" << p->m_oBookInfo->m_nBook_Number << endl;
cout << "书名:" << p->m_oBookInfo->m_strTitle << endl;
cout << "作者:" << p->m_oBookInfo->m_strWroter << endl;
cout << "当前在馆图书数量:" << p->m_oBookInfo->m_nMoreNum << endl;
cout << "图书共计数量:" << p->m_oBookInfo->m_nTotalHoldNum << endl;
cout << "这本图书简介:" << p->m_oBookInfo->m_sttrComment << endl;
cout << "您确定删除吗?(Y/N)" << endl;
char ch;
cin >> ch;
if (ch == 'Y' || 'y') {
if (p->m_pNextPoint != NULL && p->m_pParentPoint != NULL) {//夹在链表中间的节点
Info* Left = p->m_pParentPoint;//将要删除节点的前驱节点指向赋值给前驱结点指针变量
Info* Right = p->m_pNextPoint;//将要删除节点的后继结点指向赋值给后继结点指针变量
Left->m_pNextPoint = Right;//将后继结点指针指向的地址作为前驱结点的后继域
Right->m_pParentPoint = Left;//将前驱结点指针指向的地址作为后继结点的前驱域
//释放空间
p->m_pNextPoint = NULL;
p->m_pParentPoint = NULL;
delete p->m_oBookInfo;
p->m_oBookInfo = NULL;
delete p;
p = NULL;
return bth;
}
else if (p->m_pParentPoint == NULL) {//首结点的前驱为空,处理首结点删除操作
if (p->m_pNextPoint == NULL) {//说明只有一个结点
delete p->m_oBookInfo;
p->m_oBookInfo = NULL;
delete p;
p = NULL;
return bth;
}
bth = p->m_pNextPoint;
bth->m_pParentPoint = NULL;
p->m_pNextPoint = NULL;
p->m_pParentPoint = NULL;
delete p->m_oBookInfo;
p->m_oBookInfo = NULL;
delete p;
p = NULL;
return bth;
}
else if (p->m_pNextPoint == NULL) {
Info* Left = p->m_pParentPoint;
Left->m_pNextPoint = NULL;
p->m_pNextPoint = NULL;
p->m_pParentPoint = NULL;
delete p->m_oBookInfo;
p->m_oBookInfo = NULL;
delete p;
p = NULL;
return bth;
}
}
}
}
}
void Output_BookInfo(Info* bth) {
//输出图书信息
system("cls");
Info* p = bth;
while (p) {
cout << "图书编号:" << p->m_oBookInfo->m_nBook_Number;
cout << "书名:" << p->m_oBookInfo->m_strTitle;
cout << "作者:" << p->m_oBookInfo->m_strWroter;
cout << "当前在馆图书数量:" << p->m_oBookInfo->m_nMoreNum;
cout << "图书共计数量:" << p->m_oBookInfo->m_nTotalHoldNum;
cout << "这本图书简介:" << p->m_oBookInfo->m_sttrComment << endl;
p = p->m_pNextPoint;
}
}
void Borrow_TheBook(Info* bth) {
//图书借出
system("cls");
int flag, k, x, i = 0;
cout << "请输入您想借阅的图书编号:";//按照书本编号进行查找
cin >> x;
Info* p = Sreach(bth, x, &k, &flag);
if (flag == 1) {
Book* r = p->m_oBookInfo;
cout << "你想借阅的图书信息如下:" << endl;
cout << "书名:" << p->m_oBookInfo->m_strTitle << endl;
cout << "作者:" << p->m_oBookInfo->m_strWroter << endl;
cout << "当前在馆图书数量:" << p->m_oBookInfo->m_nMoreNum << endl;
cout << "图书共计数量:" << p->m_oBookInfo->m_nTotalHoldNum << endl;
cout << "这本图书简介:" << p->m_oBookInfo->m_sttrComment << endl;
cout << "您确定借阅吗?(Y/N)" << endl;
char ch;
cin >> ch;
if (ch == 'Y' || ch == 'y') {
if (r->m_nMoreNum == 0) cout << "对不起,本书 已经全部借出···" << endl;
else {
system("cls");
for (i = 0; i < 20; i++)
if ((r->reader[i]).name[0] == '\0') break;
cout << "请输入借阅者的姓名:"; cin >> (r->reader[i]).name;
cout << "请输入借出日期:" << endl;
cout << "请输入借出年份:"; cin >> (r->reader[i]).bro.m_nYear;
cout << "请输入借出月份:"; cin >> (r->reader[i]).bro.m_nMonth;
cout << "请输入借出日:"; cin >> (r->reader[i]).bro.m_nDay;
cout << "请输入归还日期:" << endl;
cout << "请输入归还年份:"; cin >> (r->reader[i]).back.m_nYear;
cout << "请输入归还月份:"; cin >> (r->reader[i]).back.m_nMonth;
cout << "请输入归还日:"; cin >> (r->reader[i]).back.m_nDay;
r->m_nMoreNum--;
cout << endl << "成功接到这本书" << endl;
}
}
}
}
void TurnBack_TheBook(Info* bth) {
//图书归还
system("cls");
int flag, k, x, i = 0, j = 0;
cout << "请输入您想借阅的图书编号:";//按照书本编号进行查找
cin >> x;
Info* p = Sreach(bth, x, &k, &flag);
if (flag == 1) {
Book* r = p->m_oBookInfo;
cout << "你想归还的图书信息如下:" << endl;
cout << "书名:" << p->m_oBookInfo->m_strTitle << endl;
cout << "作者:" << p->m_oBookInfo->m_strWroter << endl;
cout << "当前在馆图书数量:" << p->m_oBookInfo->m_nMoreNum << endl;
cout << "图书共计数量:" << p->m_oBookInfo->m_nTotalHoldNum << endl;
cout << "这本图书简介:" << p->m_oBookInfo->m_sttrComment << endl;
cout << "您确定归还吗?(Y/N)" << endl;
char ch;
cin >> ch;
if (ch == 'Y' || ch == 'y') {
system("cls");
cout << "请输入借阅者的姓名:";
string nm;
cin >> nm;
for (i = 0; i < 20; i++)
if ((r->reader[i]).name == nm) {
j = 1;
break;
}
if (j == 0) {
cout << "你未借阅过这本书" << endl;
return;
}
(r->reader[i]).name[0] = '\0';
r->m_nMoreNum++;
cout << "书名:" << p->m_oBookInfo->m_strTitle << endl;
cout << "作者:" << p->m_oBookInfo->m_strWroter << endl;
cout << "当前在馆图书数量:" << p->m_oBookInfo->m_nMoreNum << endl;
cout << "图书共计数量:" << p->m_oBookInfo->m_nTotalHoldNum << endl;
cout << "这本图书简介:" << p->m_oBookInfo->m_sttrComment << endl;
}
}
else cout << "您不能归还不存在的图书" << endl;
}
int Select_Menu() {
//图书管理系统主界面
cout << "--------------------------------------------------" << endl << endl;
cout << " 图 书 馆 管 理 系 统 " << endl;
cout << " 主 菜 单 " << endl << endl;
cout << " 1.上传图书" << endl;
cout << " 2.下架图书" << endl;
cout << " 3.显示图书" << endl;
cout << " 4.借阅图书" << endl;
cout << " 5.归还图书" << endl;
cout << " 6.退出系统" << endl << endl;
cout << " 请选择菜单项:(1-6)" << endl;
cout << "--------------------------------------------------" << endl;
int id = 0;//编号
cout << "请输入您的选择:";
cin >> id;
return id;
}
int main() {
Info* bth = NULL;
while (true) {
int id = Select_Menu();
switch (id) {
case 1:
bth = Insert_BookInfo(bth);
break;
case 2:
bth = Delete_BookInfo(bth);
break;
case 3:
Output_BookInfo(bth);
break;
case 4:
Borrow_TheBook(bth);
break;
case 5:
TurnBack_TheBook(bth);
break;
case 6:
system("cls");
cout << "您确定要退出系统(Y/N)";
char t;
cin >> t;
if (t == 'y' || t == 'Y') exit(0);
break;
}
cout << "按任意键返回主菜单.......";
}
}