数据结构
课程设计报告设计题目:图书管理信息系统的设计与实现
专业通信工程(物联网)
班级
学生
学号
指导教师
起止时间2012-8-20至2012-9-11
师学院
2012年下学期
一、设计题目
十七、图书管理信息系统的设计与实现
【问题描述】图书信息所表示的就是一个数据库文件。图书管理一般包括:图书采编、图书编目、图书查询及图书流通(借、还书)等。要求设计一个图书管理信息系统,用计算机实现上述系统功能。
【基本要求】
建立一个图书信息数据库文件,输入若干种书的记录,建立一个以书号为关键字的索引文件;在主数据库文件中建立以书名、作者及出版社作为次关键字的索引以及对应的索引链头文件,如图所示;
建立关于书号、书名、作者及出版社的图书查询;
(1)实现图书的借还子系统,包括建立读者文件、借还文件、读者管理及图书借还等相关的处理。
记录号书号书名指针 1作者指针出版社指针分藏书借出
23类量数11021数据库0小云0人民邮080
电
21014数据结0小洋0中国科001360
.
构学
31106操作系 0许海平0人民邮 170统电
41108数据结 2一0清华大 001350构学
51203程序设 0小云1中国科 260计学
62201数据库1许海平3清华大 460
学
72360数据结 4小云5人民邮 301350构电
80030程序设 5小洋2清华大 670计学
a)图书主索引文件
书名链头地址长度作者链头地址长度出版社链头地址长度
数据库62小云73人民邮电73
数据结构73小洋82中国科学52
操作系统31许海平62清华大学83
程序设计82一41
b) 书名索引链头文件c) 作者索引链头文件d) 出版社索引链头文件
二、设计容
设计一个计算机管理系统完成图书管理基本业务。
(1 )每种书的登记容包括书号、书名、著作者、现存量和库存量;
(2 )对书号建立索引表(线性表)以提高查找效率;
(3 )采编入库:新购一种书,确定书号后,登记到图书帐目表中,如果表中已有,
则只将库存量增加;
(4 )借阅:如果一种书的现存量大于0 ,则借出一本,登记借阅者的书证号
.
和还
期限,改变现存量;
(5 )归还:注销对借阅者的登记,改变该书的现存量。
三、概要设计:确定所需模块及模块间调用关系
分析:首先应该定义借书人的结构体信息和图书结构体信息,为了便于查找图
书和借书人,分别对其建立单链表。然后定义buy(),SearchByNum (),SearchByName(), borrow(),return()五个函数分别实现图书采编入库的功能,
按书号查询的功能,按书名查找的功能,借书功能和还书功能。
.根据任务的要求,先定义头文件。然后写出借书人和图书的结构体信息。为
了便
于查找图书和存储借书人的信息,分别对借书人和图书采用链表的形式存放。
//头文件的声明
#include
#include
#include
#define MAXSIZE 100// 最大值定义为 100
#define LIST_INIT_SIZE 100//图书证使用者最大值定义为100
.
// 借书人的结构体
typedef struct Boro//借书记录
{
char BNum[20];//所借书的书号
char BorDate[8];//借书日期
char RetDate[8];//归还日期
struct Boro *next;
}Bor;
typedef struct LinkBook
{
Bor *next;//该图书证的借书记录
char CNum[20];//图书证号
int Total;//借书的数量
}lend[LIST_INIT_SIZE];//借书人数组
//图书的结构体信息
typedef struct LNode
{
char CardNum[20];//图书证号
struct LNode *next;
}LinkList; // 借书人
typedef struct book
{// 每种图书需要登记的容包括书号、书名、作者、出版社、总库存量和现库量。char num[20];//书号
char name[20];//书名
char auth[20];//作者
char pub[20];//出版社
int TotNum;//总库存
int NowNum;//现库存
LinkList *next;//借了该书的人}ook;
1、新图书采编入库的设计方案
采编入库:新购入一种书,如果该书在图书账目中已经存在,则将其库存量增加(包括总库存量和现库存量),如果该书不存在,则在图书账目中增加一种书,总库存
量和现库存量均为 1。为了便于查找,另外定义了一个专门用于查找的函数BinarySearch() ,使用的是折半查找法。
(1)折半查找法查找书号
int mid=0;//外部函数mid,用来返回查找到的位置
int BinarySearch(ook boo,char SearchNum[])// 二分法查找比较书号
{ 由于函数不能有两个返回值 ,所以设置一个外部变量 mid ,用来返回查找到的位置
int low=0,high=total-1;
int found=0;
while(low<=high)
{
mid=(low+high)/2; //中间点
if(strcmp(boo[mid].num,SearchNum)==0) //书号相同
{
found=1;
return true;
}// 查找成功
if(strcmp(boo[mid].num,SearchNum)!=0)//书号不同
high=mid-1;
else low=mid+1;
}
if(found==0)
return false; //查找失败
}
2.新图书采编入库
void Buy(ook &boo, char BuyNum[])
{
if(BinarySearch(boo,BuyNum))// 如果书库中有此书{
boo[mid].TotNum++;// 总库存加 1
word 专业资料
printf(" 入库成功 .\n");
printf(" 已更改书库中该书的信息。编号%s 的书 %s 作者是 %s , 出版社是 %s ,
目前的总库存是%d , 现库存是%d 。\n",
boo[mid].num,boo[mid].name,boo[mid].auth,boo[mid].pub,boo[mid].TotN
um,boo[mid].NowNum);
}
if(!BinarySearch(boo,BuyNum))
{
int i;
for(i=total;i>mid&&total;i--)// 插在适合位置保持有序
boo[i]=boo[i-1];// 空出插入位置
printf(" 该书在书库中不存在。设立新书目,请补全书的详细信息。\n");
strcpy(boo[i].num,BuyNum);
printf(" 该书购入的数量是 :");
scanf(" %d",&boo[i].NowNum);
boo[i].TotNum=boo[i].NowNum;
printf(" 该书的名字是 :");
scanf(" %s",&boo[i].name);
printf(" 该书的作者是 :");
scanf(" %s",&boo[i].auth);
printf(" 该书的出版社是 :");
scanf(" %s",&boo[i].pub);//补全信息
boo[i].next=NULL;
total++;// 总量 +1
printf(" 已增加该书的信息。编号 %s 的书 %s 作者是%s ,出版社是%s ,目前
的总库存是%d , 现库存是%d 。\n",
boo[i].num,boo[i].name,boo[i].auth,boo[i].pub,boo[i].TotNum,boo[i].NowN
um);
printf(" 入库成功 .\n");
}
}
3、查找图书的设计方案
为了更便于查找,这里设计了两种查找方案,按书号查找和按书名查找。在按书号查找中使用了折半查找法的查找函数。按书号查找方案中都显示图书的所有状态,包括是在库还是借出,如果借出,并显示何人借走。(1).按书号查找
void SearchByNum(ook &boo,char SeaNum[])
{//BY NUM根据书号查找
LinkList *p;
p=boo[mid].next;
if(BinarySearch(boo,SeaNum)==false)printf("对不起,未找到您想查找的书。\n");//二分查找没找到
else// 找到了的话
{
printf(" ┃书号┃书名┃作者┃出版社┃现库存┃ 总库存┃\n");
printf("--------------------------------------------------------------------------
-----\n");
printf(" ┃%10s ┃%10s ┃%10s ┃%10s ┃%10d ┃%10d ┃\n",
boo[mid].num,boo[mid].name,boo[mid].auth,boo[mid].pub,boo[mid].Now
Num,boo[mid].TotNum);
if(boo[mid].next!=NULL)
{ printf(" ┃已借该书的┃\n"); printf("
┃图书证号┃\n");
while(p)
{ printf(" ┃%14s ┃\n",p-
>CardNum); p=p->next;
}
}
}
while(p)
printf(" %s",p->CardNum);//在按书号查找的函数里也显示借了这本书的借阅者的证号
p=p->next;
}
printf(" \n");
}// 显示查找的书籍的信息
}
(2).按书名查找
void SearchByName(ook &boo)
{//BY NAME根据书名查找
char SeaName[20];
printf(" 输入想查找的书的书名 :\n");
scanf(" %s",&SeaName);
printf(" 找到符合该书名的书的详细信息如下:\n");
.
for(int i=0;i { if(strcmp(SeaName,boo[i].name)==0)//如果书名一样 { printf(" 书号: %s\n 书名: %s\n 作者: %s\n 出版社: %s\n 总库存量: %d\n 现 库存 量: %d\n\n",boo[i].num,boo[i].name,boo[i].auth,boo[i].pub,boo[i].TotNum ,boo [i].NowNum); }// 显示符合信息的所有书籍的信息 } } 4、借阅图书的设计方案 如果一种书的现库存量大于零,则借出一本书,将现库存量减1 , . 并登记借阅者的图书证号和归还期限。 void Borrow(ook &boo,lend &Lin,char BorrowNum[],char CaNum[]) { Bor *p,*q; LinkList *m,*n; if(!BinarySearch(boo,BorrowNum)||total==0) //如果没有找到此书 printf(" 书库里没这书。 \n");//如果有这书 if(BinarySearch(boo,BorrowNum))// 书库里有 { if(boo[mid].NowNum>0)// 看现库存是否大于 0 { boo[mid].NowNum--;//借出一本,少1 if(boo[mid].next==NULL)// 若该书信息下显示该种书还没被人借过{ m=(LinkList *)malloc(sizeof(LNode));//分配 boo[mid].next=m;//该图书信息中的链表的第一个结点 strcpy(m->CardNum,CaNum); m->next=NULL;//后一个结点为空 } else// 如果已经有人在借这书了 { m=boo[mid].next; while(m->next) //遍历到最后一个结点 m=m->next; n=(LinkList *)malloc(sizeof(LNode));//分配空间,增加1个结点m->next=n; strcpy(n->CardNum,CaNum);//记录证号 n->next=NULL; } int i=0; for(i=0;i { if(!strcmp(Lin[i].CNum,CaNum))//如果已经有该图书证的信息{ p=Lin[i].next; while(p->next)p=p->next;//遍历到最后一个结点 q=(Bor *)malloc(sizeof(Boro));//分配空间 p->next=q; strcpy(q->BNum,BorrowNum);// 记录书号 printf(" 输入归还日期 :"); scanf("%s",&q->RetDate); q->next=NULL; printf(" 借阅成功 .\n"); break;// 找到证了就跳出循环 } } if(i==Retotal)//如果没有这证的信息 { strcpy(Lin[i].CNum,CaNum); //记录证号p=(Bor *)malloc(sizeof(Boro)); //分配空间Lin[i].next=p; strcpy(p->BNum,BorrowNum); printf(" 输入归还日期 :"); scanf(" %s",&p->RetDate); p->next=NULL; Retotal++;// 借阅证号信息总数加 1 . printf(" 借阅成功 .\n"); } } else printf("借阅失败.该书现在库存为0.\n"); } } 5、归还图书的设计方案 定义了一个 return 函数,当进行还书时,在借阅者表里查找借阅者,注销对借阅者的登记。在图书链表中改变该书的现存量,把现存量增加。 void Return(ook &boo,lend &Lin,char ReturnNum[],char BorrowerNum[]) {Bor *p,*q; LinkList *m,*n; int flag=0;//设置一个参数 if(!BinarySearch(boo,ReturnNum)||!total)// 没书 . printf(" 书库中无此书 .\n"); if(BinarySearch(boo,ReturnNum))// 有书 { m=boo[mid].next; if(!strcmp(m->CardNum,BorrowerNum))// 如果是第一个借的人还的{ boo[mid].NowNum++;// 现库存加 1 boo[mid].next=m->next;// 删除结点 free(m);// 释放该结点的空间空间 } else { while(m->next)// 查找归还者的借阅者结点 {