第一章 設計要求
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");
}
}
第七章 工作總結
在這次課程設計中,首先是認識到自己知識的嚴重不足。剛開始對該怎么做的理解都是一些空想,沒有變成實際的代碼。在編寫程序時,知識應用完全沒有概念,只是憑着感覺去寫一些,沒有把學到的東西應用起來。對函數的具體用法用處沒有充分的了解。像在信息的保存時,文件該怎樣正確的去建立,准確保存都是開始時的瓶頸。在信息查詢刪除時存在出現相同信息的判斷問題,新加聯系人的排序問題,等等。在后期過程中,通過查資料和同學的幫助,逐漸能夠解決這些問題。從這次課程設計中收獲最大的就是動手能力和初步解決問題的能力。這次課程設計不僅提升是實際操作能力的過程,也是對學習這門課程的一次總的檢驗,還是對以前學過知識的復習鞏固。對在以后的學習過程將會起到很大的幫助。我相信通過以后認真的學習和更多的實踐,將會取得更多的收獲。