第一章 设计要求
1.1 需求分析
本系统是基于哈希表的图书信息管理系统,实现了图书查找,删除,添加功能,并且可以借阅图书,归还图书,包括了还书日期超过时的罚款功能,还有将图书的信息导出,可以方便保存,基本实现了图书的管理功能,方便管理人员的管理工作。
1.2 本系统的主要功能(功能图,详细功能描述)
1.添加图书信息
2.显示图书信息
3.查找图书信息
4.删除图书
5.借阅图书
6. 归还图书
7. 保存图书信息到指定文件中
第二章 概要设计
2.1 主界面设计
2.2 存储结构设计
typedef struct
{ int year;
int month;
int day;
}data;
typedef struct
{
char num[5]; //读者编号记录
data bro;
data back;
}ReaderNode;
typedef struct
{
char title[15];
char writer[15];
int current;
int total;
int key; //书的编号
ReaderNode reader[10]; //记录借读该书的读者记录
}BookNode;
typedef struct
{
BookNode *elem;
int count; //记录节点中的总数
}HashTable;
2.3 系统功能设计
1. 主菜单显示,显示主菜单的信息,以及用户可选的执行操作,用户在输入相应的执行代码后,跳转至相应功能模块。
2. 添加模块,实现图书信息的添加功能。当添加的编号出现相同时,系统会重新设定信息,更新输入新的编号为止。
3. 查看模块,可以查找指定图书的所有信息,查找支持编号查询。当输入的编号不对或者不存在时,给出用户相应的提示。
4. 删除模块,可以实现删除指定图书的信息,支持按编号删除。当输入的编号不对或者不存在时,给出用户相应的提示。
5. 显示模块,实现显示图书管理系统所包含的所有图书的详细信息。可以直接输出显示在电脑上,或把信息录入创建的文档中。
6. 保存模块,实现信息的保存记录。当根目录中不存在指定的文档时,会再自动创建新的文档并记录信息。
7. 借阅归还模块,实现图书的借阅归还功能,当超过了归还日期的时候,系统会提示罚款的信息。
第三章 模块设计
3.1 系统子程序及功能设计
函数名 |
功能 |
int SearchHash(HashTable H,int K,int *p,int *c) |
执行查找哈希表的信息 |
unsigned Hash(int K) |
哈希函数,实现哈希存储地址 |
void collision(int *p,int d) |
开放定址法处理冲突 |
int InsertHash(HashTable *H,BookNode e) |
哈希表的数据插入函数 |
int DeleteHash(HashTable *H,BookNode e) |
哈希表的删除操作函数 |
void ShowBook(HashTable H) |
图书信息的显示函数 |
void menu(void) |
图书信息显示菜单的操作函数 |
void SaveBook(HashTable H) |
保存信息至指定文件中 |
main() |
主函数,执行操作功能的选择 |
3.2 系统功能图
第四章 详细设计
4.1 数据类型定义
本图书管理系统中,数据类型:
typedef struct
{ int year;
int month;
int day;
}data;
typedef struct
{
char num[5]; //读者编号记录
data bro;
data back;
}ReaderNode;
typedef struct
{
char title[15];
char writer[15];
int current;
int total;
int key; //书的编号
ReaderNode reader[10]; //记录借读该书的读者记录
}BookNode;
typedef struct
{
BookNode *elem;
int count; //记录节点中的总数
}HashTable;
4.2 系统主要子程序详细设计
1. 添加模块
2. void AddBook(HashTable *H)
3. {
4. BookNode e;
5. int i;
6. system("CLS");
7. printf("\n\n**************************************************\n");
8. printf("\t你能在此目录下添加图书信息");
9. printf("\n**************************************************\n");
10. printf("\n\t 请输入书的编号(形如: 1***): ");
11. scanf("%d",&e.key);
12. getchar();
13. printf("\n\t 请输入书名: ");
14. gets(e.title);
15. printf("\n\t 请输入该书作者: ");
16. gets(e.writer);
17. printf("\n\t 请输入该书现库存量: ");
18. scanf("%d",&e.current);
19. printf("\n\t 请输入该书总库存量: ");
20. scanf("%d%*c",&e.total);
21. for(i=0;i<10;i++)
22. (e.reader[i]).num[0]='\0'; //用'\0'来初始化借该书的读者证号,表示一开始时没人借书
23. if(InsertHash(&(*H),e))
24. printf("图书添加成功!\n");
25. (*H).count++;
26. }
27.
28. 删除模块
/
29. void DeleteBook(HashTable H)
30. {
31. int x,p,c,t;
32. system("CLS");
33. printf("\n\n**************************************************\n");
34. printf("\t你能在此目录下按编号删除图书信息");
35. printf("\n**************************************************\n");
36. printf("\n\t 请输入你想删除的书的编号: ");
37. scanf("%d%*c",&x);
38. if(SearchHash(H,x,&p,&c))
39. {
40. printf("\n\t 你想删除这本书吗 ?(y/n)\n");
41. printf("图书编号:%d\n",(H).elem[p].key);
42. printf("书名: 《%s》\n",(H).elem[p].title);
43. printf("作者: %s\n",(H).elem[p].writer);
44. printf("图书现存量: %d\n",(H).elem[p].current);
45. printf("图书总量 : %d\n",(H).elem[p].total);
46. }
47. else
48. printf("对不起,不存在该书!\n");
49. t=getch();
50. if(t=='y'||t=='Y')
51. {
52. (H).elem[p].key=NULL_KEY;
53. printf("删除成功!\n");
54. }
55.
56. }
57. 查询模块
/
58. void Find(HashTable *H)
59. {
60. int x,p,c;
61. system("CLS");
62. printf("\n\n**************************************************\n");
63. printf("\t你能在此目录下按编号查找图书信息");
64. printf("\n**************************************************\n");
65. printf("\n\t 请输入你想查找的书的编号: ");
66. scanf("%d%*c",&x);
67. if(SearchHash(*H,x,&p,&c))
68. {
69. printf("图书编号:%d\n",(*H).elem[p].key);
70. printf("书名: 《%s》\n",(*H).elem[p].title);
71. printf("作者: %s\n",(*H).elem[p].writer);
72. printf("图书现存量: %d\n",(*H).elem[p].current);
73. printf("图书总量 : %d\n",(*H).elem[p].total);
74. }
75. else
76. printf("对不起,不存在该书!\n");
77.
78. }
79. 显示模块
80. void ShowBook(HashTable H)
81. {
82. int i;
83. system("CLS");
84. printf("\n\n**************************************************\n");
85. printf("\t你能在此目录查看图书信息");
86. printf("\n**************************************************\n");
87. for(i=0;i<m;i++)
88. if(H.elem[i].key != NULL_KEY) /* 有数据 */
89. {
90. printf("图书编号:%d\n",H.elem[i].key);
91. printf("书名: 《%s》\n",H.elem[i].title);
92. printf("作者: %s\n",H.elem[i].writer);
93. printf("图书现存量: %d\n",H.elem[i].current);
94. printf("图书总量 : %d\n",H.elem[i].total);
95. printf("***************************************************\n");
96. }
97. }
98. 保存模块
99. void SaveBook(HashTable H){
100. FILE *fp1;
101. int i;
102. fp1=fopen("record.txt","w");
103. fprintf(fp1,"=============== 图书信息记录表 =================\n");
104. for(i=0;i<m;i++)
105. {
106. if(H.elem[i].key != NULL_KEY)
107. {
108. fprintf(fp1,"============================================\n");
109. fprintf(fp1,"图书编号:%d\n",H.elem[i].key);
110. fprintf(fp1,"书名:%s\n",H.elem[i].title);
111. fprintf(fp1,"作者:%s\n",H.elem[i].writer);
112. fprintf(fp1,"现库存量:%d\n",H.elem[i].current);
113. fprintf(fp1,"总库存量:%d\n",H.elem[i].total);
114. }
115. }
116. fprintf(fp1,"**************************************************\n");
117. fclose(fp1);
118. printf("\n\n成功储存!你能在record.txt找到相应纪录\n");
119. printf("**************************************************\n");
120. }
第五章 测试分析
各功能的运行结果:
1. 添加图书信息
2.显示已有的记录 (即显示添加的信息1)
3. 借阅图书
4.归还图书
5.
生成的文档中的记录截图
第六章 源程序清单
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<conio.h>
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
#define NULL_KEY 0//无记录元素
int hashsize[]={17,19,23,29};//存储容量
int m=0;//表长
typedef struct
{ int year;
int month;
int day;
}data;
typedef struct
{
char num[5]; //读者编号记录
data bro;
data back;
}ReaderNode;
typedef struct
{
char title[15];
char writer[15];
int current;
int total;
int key; //书的编号
ReaderNode reader[10]; //记录借读该书的读者记录
}BookNode;
typedef struct
{
BookNode *elem;
int count; //记录节点中的总数
}HashTable;
void InitHashTable(HashTable *H)
{
int i;
(*H).count=0;
m=hashsize[0];
(*H).elem=(BookNode *)malloc(m*sizeof(BookNode));
for(i=0;i<m;i++)
(*H).elem[i].key=NULL_KEY;
}
unsigned Hash(int K)//哈希函数,自己设定
{
return K%m;
}
void collision(int *p,int d) // 开放定址法处理冲突
{
*p=(*p+d)%m;
}
int SearchHash(HashTable H,int K,int *p,int *c)//p为数据的地址位置,返回
{
*p=Hash(K);
while(H.elem[*p].key != NULL_KEY && (K != H.elem[*p].key))
{
(*c)++;
if(*c<m)
collision(p,*c); //下一地址
else
break;
}
if (K == H.elem[*p].key)
return SUCCESS;
else
return UNSUCCESS;
}
int InsertHash(HashTable *H,BookNode e)
{
int c,p;
c=0;
if(SearchHash(*H,e.key,&p,&c))
return DUPLICATE;
else if(c<hashsize[0]/2)
{
(*H).elem[p]=e;
++(*H).count;
return 1;
}
return 0;
}
int DeleteHash(HashTable *H,BookNode e)
{
int c,p;
c=0;
if(SearchHash(*H,e.key,&p,&c))
{
(*H).elem[p].key=NULL_KEY;
--(*H).count;
return 1;
}
else
{
printf("不好意思,不存在\n");
}
return 0;
}
void AddBook(HashTable *H)
{
BookNode e;
int i;
system("CLS");
printf("\n\n**************************************************\n");
printf("\t你能在此目录下添加图书信息");
printf("\n**************************************************\n");
printf("\n\t 请输入书的编号(形如: 1***): ");
scanf("%d",&e.key);
getchar();
printf("\n\t 请输入书名: ");
gets(e.title);
printf("\n\t 请输入该书作者: ");
gets(e.writer);
printf("\n\t 请输入该书现库存量: ");
scanf("%d",&e.current);
printf("\n\t 请输入该书总库存量: ");
scanf("%d%*c",&e.total);
for(i=0;i<10;i++)
(e.reader[i]).num[0]='\0'; //用'\0'来初始化借该书的读者证号,表示一开始时没人借书
if(InsertHash(&(*H),e))
printf("图书添加成功!\n");
(*H).count++;
}
void ShowBook(HashTable H)
{
int i;
system("CLS");
printf("\n\n**************************************************\n");
printf("\t你能在此目录查看图书信息");
printf("\n**************************************************\n");
for(i=0;i<m;i++)
if(H.elem[i].key != NULL_KEY) /* 有数据 */
{
printf("图书编号:%d\n",H.elem[i].key);
printf("书名: 《%s》\n",H.elem[i].title);
printf("作者: %s\n",H.elem[i].writer);
printf("图书现存量: %d\n",H.elem[i].current);
printf("图书总量 : %d\n",H.elem[i].total);
printf("***************************************************\n");
}
}
void Find(HashTable *H)
{
int x,p,c;
system("CLS");
printf("\n\n**************************************************\n");
printf("\t你能在此目录下按编号查找图书信息");
printf("\n**************************************************\n");
printf("\n\t 请输入你想查找的书的编号: ");
scanf("%d%*c",&x);
if(SearchHash(*H,x,&p,&c))
{
printf("图书编号:%d\n",(*H).elem[p].key);
printf("书名: 《%s》\n",(*H).elem[p].title);
printf("作者: %s\n",(*H).elem[p].writer);
printf("图书现存量: %d\n",(*H).elem[p].current);
printf("图书总量 : %d\n",(*H).elem[p].total);
}
else
printf("对不起,不存在该书!\n");
}
void BorrowBook(HashTable *H)
{
int i,k, x, f,t;
system("CLS");
printf("\n\n**************************************************\n");
printf("\t你能在此目录下按编号借阅图书");
printf("\n**************************************************\n");
printf("\n\t 请输入你想借的书编号: ");
scanf("%d%*c",&x);
if(SearchHash(*H,x,&k,&f))
{
printf("\n\t 你想借这本书吗 ?(y/n)");
printf("\n\t 书名: 《%s》",(*H).elem[k].title);
printf("\n\t 作者: %s",(*H).elem[k].writer);
printf("\n\t 现库存量: %d",(*H).elem[k].current);
printf("\n\t 总库存量: %d",(*H).elem[k].total);
t=getch();
if(t=='y'||t=='Y')
{
if( ((*H).elem[k].current)==0) printf("\n\t对不起,这本书已经被借光了...");
else
{
for(i=0;i<10;i++)
if( ((*H).elem[k].reader[i]).num[0]=='\0') break;
printf("\n\t 请输入你的借书证号: ");
scanf("%s",((*H).elem[k].reader[i]).num);
printf("\n\t 请输入借书日期: "); //输入借书日期
printf("\n\t 年: ");
scanf("%d",&(((*H).elem[k].reader[i]).bro.year));
printf("\t 月: ");
scanf("%d",&(((*H).elem[k].reader[i]).bro.month));
printf("\t 日: ");
scanf("%d",&(((*H).elem[k].reader[i]).bro.day));
printf("\n\t 输入应还书日期: "); //输入应还书日期
printf("\n\t 年: ");
scanf("%d",&(((*H).elem[k].reader[i]).back.year));
printf("\t 月: ");
scanf("%d",&(((*H).elem[k].reader[i]).back.month));
printf("\t 日: ");
scanf("%d%*c",&(((*H).elem[k].reader[i]).back.day));
(*H).elem[k].current--; //现存书量减1
printf("\n\t 你已借了该书.");
}
}
}
else printf("\n\t 这本书不存在!\n");
}
void ReturnBook(HashTable *H)
{
int i,k, x, f,t,j;
int year,month,day,d;
float pay;
char temp[20];
system("CLS");
printf("\n\n**************************************************\n");
printf("\t你能在此目录下按编号归还图书");
printf("\n**************************************************\n");
printf("\n\t 请输入你还的书: ");
scanf("%d%*c",&x);
if(SearchHash(*H,x,&k,&f))
{
printf("\n\t 你想还这本书吗 ?(y/n)");
printf("\n\t 书名: 《%s》",(*H).elem[k].title);
printf("\n\t 作者: %s",(*H).elem[k].writer);
printf("\n\t 现库存量: %d",(*H).elem[k].current);
printf("\n\t 总库存量: %d",(*H).elem[k].total);
t=getch();
if(t=='y'||t=='Y')
{
printf("\n\t 请输入你的借书证号: ");
scanf("%s",temp);
j=0;
for(i=0;i<5;i++)
{
if(!(strcmp(temp,((*H).elem[k].reader[i]).num))) {j=1;break;} //查看是否有借书
}
if(j==0)
{ printf("\n\t 你没有借书.");return;} //该借书证号的人没借书
printf("\n\t 今天是:");
printf("\n\t 年: ");
scanf("%d",&year);
printf("\t 月: ");
scanf("%d",&month);
printf("\t 日: ");
scanf("%d%*c",&day);
d=0;
if(year<((*H).elem[k].reader[i]).back.year) d=1; //判断是否已过了还书日期,d=1还没过期,d=0过期
if(year<=((*H).elem[k].reader[i]).back.year && month<((*H).elem[k].reader[i]).back.month) d=1;
if(year<=((*H).elem[k].reader[i]).back.year && month<=((*H).elem[k].reader[i]).back.month && day<((*H).elem[k].reader[i]).back.day) d=1;
if(d==0)
{
pay=(year-((*H).elem[k].reader[i]).back.year)*365+(month-((*H).elem[k].reader[i]).back.month)*30+(day-((*H).elem[k].reader[i]).back.day);
printf("\n\t 你在 %d-%d-%d 借了这本书",((*H).elem[k].reader[i]).bro.year,((*H).elem[k].reader[i]).bro.month,((*H).elem[k].reader[i]).bro.day);
printf("\n\t 你应该在 %d-%d-%d 还这本书",((*H).elem[k].reader[i]).back.year,((*H).elem[k].reader[i]).back.month,((*H).elem[k].reader[i]).back.day);
printf("\n\t 今天是 %d-%d-%d",year,month,day);
printf("\n\n\t 所以你超出了还书日期");
printf("\n\t 你应该被罚款 %2.1f 元.",0.1*pay); //过期一天还1角钱
}
((*H).elem[k].reader[i]).num[0]='\0'; //已还,清除该读者借书记录
(*H).elem[k].current++; //现存书量加1
printf("\n\t 你已经还了这本书.\n");
}
}
else printf("\n\t 你要还一本没库存的书 ???\n");
}
void SaveBook(HashTable H){
FILE *fp1;
int i;
fp1=fopen("record.txt","w");
fprintf(fp1,"=============== 图书信息记录表 =================\n");
for(i=0;i<m;i++)
{
if(H.elem[i].key != NULL_KEY)
{
fprintf(fp1,"============================================\n");
fprintf(fp1,"图书编号:%d\n",H.elem[i].key);
fprintf(fp1,"书名:%s\n",H.elem[i].title);
fprintf(fp1,"作者:%s\n",H.elem[i].writer);
fprintf(fp1,"现库存量:%d\n",H.elem[i].current);
fprintf(fp1,"总库存量:%d\n",H.elem[i].total);
}
}
fprintf(fp1,"**************************************************\n");
fclose(fp1);
printf("\n\n成功储存!你能在record.txt找到相应纪录\n");
printf("**************************************************\n");
}
void DeleteBook(HashTable H)
{
int x,p,c,t;
system("CLS");
printf("\n\n**************************************************\n");
printf("\t你能在此目录下按编号删除图书信息");
printf("\n**************************************************\n");
printf("\n\t 请输入你想删除的书的编号: ");
scanf("%d%*c",&x);
if(SearchHash(H,x,&p,&c))
{
printf("\n\t 你想删除这本书吗 ?(y/n)\n");
printf("图书编号:%d\n",(H).elem[p].key);
printf("书名: 《%s》\n",(H).elem[p].title);
printf("作者: %s\n",(H).elem[p].writer);
printf("图书现存量: %d\n",(H).elem[p].current);
printf("图书总量 : %d\n",(H).elem[p].total);
}
else
printf("对不起,不存在该书!\n");
t=getch();
if(t=='y'||t=='Y')
{
(H).elem[p].key=NULL_KEY;
printf("删除成功!\n");
}
}
void menu(void)
{
system("cls");
system("color aa");//改变颜色
system("cls");
printf("*****************************************************************************\n");
printf("*****************************************************************************\n");
printf("************ 图书管理系统 ************************\n");
printf("*****************************************************************************\n");
printf("*****************************************************************************\n");
printf("\n\n\t选择你需要操作的功能:(现无记录,请先添加信息)\n");
printf("\n");
printf("\t\t1.添加图书信息\n");
printf("\t\t2.显示图书信息\n");
printf("\t\t3.查找图书信息\n");
printf("\t\t4.删除图书\n");
printf("\t\t5.借阅图书\n");
printf("\t\t6.归还图书\n");
printf("\t\t7.保存图书信息到指定文件中\n");
printf("\n**************************************************\n");
}
int main()
{
int n,i,c;
int year,month,day;
BookNode book;
HashTable H;
system("cls");
system("color 5e");//改变颜色
system("cls");
printf("********************************* 图书管理系统 *********************************\n");
printf("********************************* 软件工程 *********************************\n");
printf("********************************* 丁洋 *********************************\n");
printf("********************************* 07 *********************************\n");
printf("\n\n\t\t\t\t欢迎您!!!\n");
printf("请按ENTER进入主菜单\n");
getchar();
InitHashTable(&H);
while(1)
{
menu();
printf("选择你需要操作的功能号码:");
scanf("%d",&c);
getchar();
switch(c)
{
case 1:
AddBook(&(H));break;
case 2:
ShowBook((H));break;
case 3:
Find(&(H));break;
case 4:
DeleteBook(H);break;
case 5:
BorrowBook(&(H));break;
case 6:
ReturnBook(&(H));break;
case 7:
SaveBook((H));break;
default : printf("Enter error!!\n");
}
printf("请按ENTER返回主菜单\n");
getchar();
system("CLS");
}
}
第七章 工作总结
在这次课程设计中,首先是认识到自己知识的严重不足。刚开始对该怎么做的理解都是一些空想,没有变成实际的代码。在编写程序时,知识应用完全没有概念,只是凭着感觉去写一些,没有把学到的东西应用起来。对函数的具体用法用处没有充分的了解。像在信息的保存时,文件该怎样正确的去建立,准确保存都是开始时的瓶颈。在信息查询删除时存在出现相同信息的判断问题,新加联系人的排序问题,等等。在后期过程中,通过查资料和同学的帮助,逐渐能够解决这些问题。从这次课程设计中收获最大的就是动手能力和初步解决问题的能力。这次课程设计不仅提升是实际操作能力的过程,也是对学习这门课程的一次总的检验,还是对以前学过知识的复习巩固。对在以后的学习过程将会起到很大的帮助。我相信通过以后认真的学习和更多的实践,将会取得更多的收获。