2020年十一月整理图书馆管理系统程序.doc

 N

  《程序设计实践》报告 学号;题目来源及序号难度等级

 一、题目 说明:由教师给出 题目 13、 图书管理系统(查找应用)

 [问题描述] 图书管理基本业务活动包括:对一本书的采编入库、清除库存、借阅和归还等等。试设计一个图书管理系统,将上述业务活动借助于计算机系统完成。

 [实现提示] 1、 每种书的登记内容至少包括书号、书名、著者、现存量和总库存量等五项。

 2、 由于图书管理的基本业务活动都是通过书号(即关键字)进行的,所以要用对书号 索引,以获得高效率。

 3、 系统应实现的基本功能有:

 4 采编入库:新购入一种书,经分类和确定书号之后登记到图书帐目中去。如果这两种书在帐中已有,则只将总库存量增加。

 5 清除库存:某种书已无保留价值,将它从图书帐目中注销。

 6 借阅:如果一种书的现存量大于零,则借出一本,登记借阅者的图书证号和归还期限。

 7 归还:注销对借阅者的登记,改变该书的现存量。

 8 显示:以凹入表的形式显示 B 树。这个操作是为了调试和维护的目的而设置的。

 二、问题分析及求解基本思路 说明:给出题目的分析及初步的解题思路。要求简洁、易懂 一、概要设计 主要实现系统的功能:

 a.图书初始化:

 输入图书的一些信息,编号、作者、书名、数量,有一定的库存。

 b.新书入库:

 新书采编入库,输入编号后有次数只需输入数量,没有则继续输入 c.添加读者信息:

 读者信息初始化,输入读书证号和姓名后才能进行借书还书 d.借书模块:

 读者输入读书证号,证号存在输入要借的图书编号,不能借同一本书,如果借书数量以达到最大也不能借书。

 e.还书模块:

 归还已借的图书,要先输入读者书证号,书证号存在继续输入要还的图书编号,图书编号存在并且借来此书,归还成功。

 f.查询图书信息 g.查询读者信息:

 可查询读者姓名书证号,借了几本书,都是什么书和还书日期, 还可以借几本书。

 h.退出:

 退出读书管理系统并保存读者和图书信息。

 设计的的初步思路:

 主要采取定义结构体,定义两个结构体分别为图书结构体和阅读者的结构体,将其数据存储到字符串中,然后逐个构建单链表,将其数据存储到单链表结点的数据域中,然后进行图书文件的读取或者可以选择图书的初始化,输入图书的编号,作者,书名,数量和一定的库存和现存量。新书入库创造新结点,定义指针,此处分两种情况,若图书编号存在,则直接进库,只须输入书的数量,通过字符串的比较来判定,同理阅读者的添加是增加阅读者的单链表的结点,同时一个读者规定只能借阅 5 本书存储到数据域的字符串中。分别定义还书和借书的函数,用字符串的比较功能判断读者借书不能同一种书借两次,同时采编新书要求如果书号相同只需要直接输入采编的本数和如果没有书时会返回等待新书到来,包括索书号以及读者的学号输入出现不存在会返回错误,还书函数也是通过字符串中存储的库存量和现存量增加,同时读者借书数量 right 减少。最后将图书的单链表和阅读者的单链表读写到文件中。

 N

  三、问题求解的整体框架结构 说明:围绕求解目标给出具体的模块。要求简洁、易懂

  1 图书录入流程图:

  2 登记读者程图:

 N N

 Y

 Y

 首先定义图书,阅读者,借书结构体; typedef struct book; typedef struct borrow; typedef struct reader; 定义菜单函数,包括图书借阅的各种功能,包括:

 1 采编入库图书

 void Init_book();

  2 登记读者

 void add_reader();

  3 借阅登记图书

  void Borrow_Book();

 4 还书管理

 void Return_Book();

 5 查询读者信息

 void Print_reader();通过读者文件读取读者信息单链表

  6 查询图书信息

 void Print_book(); 通过 图书文件读取图书单链表的信息

  0 退出系统

 void Print_book();

  读入图书文件数据 输入图书信息,将图书信息存储到字符串中 建立图书单链表 , 输入数据文件 关闭数据文件,保存 是否完成 读入读者文件数据 输入读者信息,将图书信息存储到字符串中,并且标记读者借书情况 建立读者单链表 , 输入数据文件 关闭数据文件,保存 是否完成

 N

  3 增添图书录入流程图:

  N

  Y

  Y

 N

  4 还书管理流程图:

 N

 Y

 N

 Y

 输入查询条件 如果存在,直接输入书本数

 是否存在

 继续?

  返

  回 执行录入流程图,录入图书 输入借阅者信息 while(p1->next!=NULL&&strcmp(rea_num,p1->reader_num)!=0) ,读者是否存在?

  输入所要借阅的图书信息 while(strcmp(bo_num,p0->book_num)!=0&&p0->next!=NULL),图书是否存在?

 读者借书数目是否已满?图书是否为空?采用 strcmp 判断

 N

  打印读者图书信息:

  四、 主要算法 说明:要求用自然语言描述算法。要求简洁、易懂 (1)首先首先定义图书,阅读者,借书结构体;typedef struct book;typedef struct borrow;typedef struct reader;定义好各种说需要的数据:

 typedef struct book {

 char book_num[10];//图书编号

 char book_name[20];//图书名称

 char book_writer[10];//图书的作者

 int book_xy;//现有量

 int book_kc;//库存

 struct book *next; strcpy(p1->borrow[p1->right++].borrow_book_num,bo_num);strcpy(p1->borrow[p1->right-1].limit_date,lim_date); p0->book_xy--;p0->book_kc--;通过读者结点存储借书结构体信息。

 借阅完成 请输入正确细信息,或图书已满或已空 通过单链表结点的访问,将图书单链表的每个结点的信息都访问,p=p->next,p->book_num;p->book_name;

 p->book_writer,p->book_xy,p->book_kc;打印访问阅读者单链表结点的访问,p->reader_num,p->reader_name,以及借书数量p->borrow[i].borrow_book_num,还书日期:p->borrow[i].limit_date Save();保存文件打印 结束

 N

  }BK; typedef struct borrow { char borrow_book_num[10];//借书的总数 char limit_date[8];//还书日期 }BO; typedef struct reader { char reader_num[10]; char reader_name[10]; int right;//读者所借的书的本数 BO borrow[Max]; struct reader *next; }RD; (1)

 定义实现功能所需要的函数,包括图书的登记,读者的登记,图书的录用,以及读者的借阅,图书,读者信息的保存和读音等功能。int Menu(); void Init(); void Login(); void Init_book(); void Insert_New_Book(); void Menu_select(); void Find_Book(); void add_reader(); void Print_reader(); void Print_book(); void Borrow_Book(); void Return_Book(); void Save(); void Save_Book(); void Save_Reader(); void Load(); void Load_Reader(); void Load_Book(); void Login()

 (3)通过字符串存储读者和图书的信息,然后进行图书文件的读取或者可以选择图书的初始化,输入图书的编号,作者,书名,数量和一定的库存和现存量。新书入库创造新结点,定义指针,此处分两种情况,若图书编号存在,则直接进库,只须输入书的数量,通过字符串的比较来判定,同理阅读者的添加是增加阅读者的单链表的结点,同时一个读者规定只能借阅 5 本书存储到数据域的字符串中。分别定义还书和借书的函数,用字符串的比较功能判断读者借书不能同一种书借两次,同时采编新书要求如果书号相同只需要直接输入采编的本数和如果没有书时会返回等待新书到来,包括索书号以及读者的学号输入出现不存在会返回错误,还书函数也是通过字符串中存储的库存量和现存量增加,同时读者借书数量 right 减少。最后将图书的单链表和阅读者的单链表读写到文件中。

 N

  void Insert_New_Book()/*新书入库*/ {

  BK *p,*p0,*p1; p=p1=h_book; printf("\n 新书入库模块...\n"); printf("\n 请输入图书信息..\n 包括书号.书名.数量..\n"); p0=(BK *)malloc(sizeof(BK));

 printf("图书编号:");

  scanf("%s",p0->book_num);

  while(strcmp(p0->book_num,p1->book_num)!=0&&p1->next!=NULL)

 p1=p1->next;

  if(strcmp(p0->book_num,p1->book_num)==0) /*此处分两种情况,若图书编号存在,则直接进库,只须输入书的数量*/

  {

 printf("\n 此编号图书已存在!!直接入库!\n");

 printf("图书数量:");

  scanf("%d",&p0->book_kc);

 p1->book_kc+=p0->book_kc;

  p1->book_xy+=p0->book_kc;

 } else

 {

  printf("图书名称:");

 scanf("%s",p0->book_name);

  printf("图书作者:");

 scanf("%s",p0->book_writer);

 printf("图书数量:");

 scanf("%d",&p0->book_kc);//库存数量 while(p->next) { p=p->next; } if(h_book==NULL) h_book=p0;

 else p->next=p0; p0->next=NULL;

  p0->book_xy=p0->book_kc;

 }

  printf("\n 新书入库完毕!按任意键继续下一步操作..\n");

 getch();

  system("cls");

  } void add_reader()/*添加读者*/ { RD *p0;

  int i;

  printf("\n 读者初始化开始,请输入读者信息..\n 包括书证号.姓名..\n"); p0=(RD*)malloc(sizeof(RD)); h_reader=p0; printf("\n 请输入读者的信息:\n");

  printf("读者书证号:");

  scanf("%s",p0->reader_num);

  printf("读者姓名:");

 scanf("%s",p0->reader_name);

 N

  p0->right=0;

  for(i=0;i<Max;i++)

  {strcpy(p0->borrow[i].borrow_book_num,"0");

  strcpy(p0->borrow[i].limit_date,"0");

  }

  p0->next=NULL;

  printf("\n 读者信息初始化完毕!按任意键继续下一步操作..\n");

 getch();

  system("cls"); } void Borrow_Book() /*借书模块*/ {

 BK *p0; RD *p1; char bo_num[10],rea_num[10],lim_date[8]; int i; p0=h_book; p1=h_reader; printf("\n 借书模块...\n"); printf("\n 请输入借书的读者书证号:"); scanf("%s",rea_num); while(p1->next!=NULL&&strcmp(rea_num,p1->reader_num)!=0)

 p1=p1->next;

 if(p1->next==NULL&&strcmp(rea_num,p1->reader_num)!=0)

  {

 printf("\n 此读者编号不存在!按任意键返回..\n");

  goto END;

  }

 printf("\n 请输入你要借的书的编号:");

 scanf("%s",bo_num);

 while(strcmp(bo_num,p0->book_num)!=0&&p0->next!=NULL)

  p0=p0->next;

 if(p0->next==NULL&&strcmp(bo_num,p0->book_num)!=0)

  {

  printf("\n 此图书编号不存在!按任意键返回..\n");

 goto END;

 }

  else if(p0->book_xy<=0)

 {

 printf("\n 抱歉,此书已借完!请等待新书的到来!!\n 按任意键返回....");

 goto END;

  }

 else if(p1->right>Max||p1->right==Max)

  {

  printf("\n 不好意思,借书数目已满!不能借书!\n 按任意键返回....");

 goto END;

  }

 else if(strcmp(p1->borrow[0].borrow_book_num,"0")!=0)

 {

 for(i=0;i<Max;i++)

 {

  if(strcmp(p1->borrow[i].borrow_book_num,bo_num)==0)

 {

  printf("\n 抱歉!同一读者不能同借两本相同的书!\n 按任意键返回....");

  goto END;

  } else if(strcmp(p1->borrow[i].borrow_book_num,"0")==0)

 {

 printf("\n 请输入你要归还图书的日期:");

 scanf("%s",lim_date);

 strcpy(p1->borrow[p1->right++].borrow_book_num,bo_num);

 strcpy(p1->borrow[p1->right-1].limit_date,lim_date);

 N

 p0->book_xy--;

 p0->book_kc--;

 printf("\n 读者编号%s 借书完毕!按任意键继续下步操作..",p1->reader_num);

  goto END;

  }

 }

 } else

 {

  printf("\n 请输入你要归还图书的日期:");

 scanf("%s",lim_date);

 strcpy(p1->borrow[p1->right++].borrow_book_num,bo_num);

 strcpy(p1->borrow[p1->right-1].limit_date ,lim_date );

  p0->book_xy--;

  p0->book_kc--;

  printf("\n 读者编号%s 借书完毕!按任意键继续下步操作..",p1->reader_num);

 }

  END:getch(); system("cls");} void Return_Book() /*还书模块*/ {

 BK *p; RD *q; int i,j,find=0; char return_book_num[10],return_reader_num[10]; p=h_book; q=h_reader; printf("\n 还书模块...\n"); printf("\n 请输入要还书的读者编号:"); scanf("%s",return_reader_num); while(q->next!=NULL&&strcmp(return_reader_num,q->reader_num)!=0)

  q=q->next; if(q->next==NULL&&strcmp(return_reader_num,q->reader_num)!=0)

 {

 find=2;

  printf("\n 此读者编号不存在!按任意键返回..\n");

 goto end;

  }

 printf("\n 请输入读者还书的编号:");

  scanf("%s",return_book_num);

 while(p->next!=NULL&&strcmp(return_book_num,p->book_num)!=0)

 p=p->next;

 if(p->next==NULL&&strcmp(return_book_num,p->book_num)!=0)

  {

 find=2;

  printf("\n 错误!此图书编号不存在!按任意键返回..\n");

  goto end;

  }

 for(i=0;i<Max;i++)

  if(strcmp(return_book_num,q->borrow[i].borrow_book_num)==0)

  /*如果此读者借了此书*/

  {

  find=1;

 for(j=i;j<Max-1;j++)

 {strcpy(q->borrow[j].borrow_book_num,q->borrow[j+1].borrow_book_num);

  strcpy(q->borrow[j].limit_date,q->borrow[j+1].limit_date);

 }

 strcpy(q->borrow[Max-1].borrow_book_num,"0");

 N

 strcpy(q->borrow[Max-1].limit_date,"0");

  p->book_xy++;

  p->book_kc++;

  q->right--;

  printf("\n 编号%s 的读者已完毕!按任意键继续下步操作..",return_reader_num);

 }

 if(find==0)

  printf("\n 错误!此读者未借此书!按任意键返回..\n");

  end: getch(); system("cls");} void Print_book() /*查询图书信息*/ {BK *p; p=h_book; printf("\n 图书信息如下:\n\n"); printf("图书编号\t 图书名称\t 图书作者\t 现有\t\t 库存\n");

 while(p!=NULL) {

  printf("%s\t\t%s\t\t%s\t\t%d\t\t%d\n",p->book_num,p->book_name,p->book_writer,p->book_xy,p->book_kc);

 p=p->next;} printf("\n 图书信息打印完毕!按任意键继续下一步操作.."); getch(); system("cls");} void Print_reader()

  /*查询读者信息*/ {RD *p; int i; p=h_reader; printf("\n 读者信息如下:\n\n"); printf("读者书证号\t\t 读者姓名\n");

 printf("\n"); while(p!=NULL) { printf("\t%s\t\t%s",p->reader_num,p->reader_name);

 for(i=0;i<Max;i++)

 {printf("\n");

 printf("图书编号",i+1);

 printf("\t 还书日期",i+1);

 printf("\n");

 printf("\t%s",p->borrow[i].borrow_book_num);

 printf("\t\t%s",p->borrow[i].limit_date); } printf("\n");

 p=p->next;} printf("\n 读者信息打印完毕!按任意键继续下一步操作.."); getch(); system("cls");} void Save() /*保存信息*/ {Save_Reader();

 N

  Save_Book();} void Save_Reader()

  /*保存读者信息*/ (2)

 通过创建文件将图书和读者的单链表和图书的单链表输入到文件里,再读取文件,关闭文件。

 {FILE *fp_reader; RD *p,*p0; p=h_reader; if((fp_reader=fopen("Reader.txt","wb"))==NULL)

  /*创建文件,进行保存*/ {

 printf("\n 文件保存失败!\n 请重新启动本系统...\n");

 exit(0);} while(p!=NULL) { if(fwrite(p,sizeof(RD),1,fp_reader)!=1)

  /*将链表中的信息写入文件中*/

  printf("\n 写入文件失败!\n 请重新启动本系统!\n");

 p0=p;

 p=p->next;

 free(p0); /*释放所有结点*/} h_reader=NULL; fclose(fp_reader);

 } void Save_Book() /*保存图书信息*/ {FILE *fp_book;

  /*创建文件型指针*/ BK *p,*p0; p=h_book; if((fp_book=fopen("Book.txt","wb"))==NULL)

 /*创建文件,进行保存*/ { printf("\n 文件保存失败!\n 请重新启动本系统...\n");

 exit(0);} while(p!=NULL) {

 if(fwrite(p,sizeof(BK),1,fp_book)!=1)

 /*将链表中的信息写入文件中*/

  printf("\n 写入文件失败!\n 请重新启动本系统!\n");

 p0=p;

 p=p->next;

 free(p0); } h_book=NULL; fclose(fp_book);

 } void Load() /*加载信息*/ {Load_Reader(); Load_Book();} void Load_Reader()

  /*加载读者信息*/ { RD *p1,*p2,*p3;

 FILE *fp;

  /*创建文件型指针*/

 fp=fopen("book.txt","rb");

  /*打开文件*/

 p1=(RD *)malloc(sizeof(RD));

 fread(p1,sizeof(RD),1,fp);

 h_reader=p3=p2=p1;

 N

 while(! feof(fp))

  /*读出信息,重新链入链表*/

 { p1=(RD *)malloc(sizeof(RD));

  fread(p1,sizeof(RD),1,fp);

  p2->next=p1;p3=p2;

 p2=p1; }p3->next=NULL;

 free(p1);

 fclose(fp); } void Load_Book() /*加载图书信息*/ {BK *p1,*p2,*p3; FILE *fp;

 /*创建文件型指针*/ fp=fopen("Book.txt","rb");

  /*打开文件*/

  p1=(BK *)malloc(sizeof(BK));

 fread(p1,sizeof(BK),1,fp);

  h_book=p3=p2=p1;

 while(! feof(fp))

  /*读出信息,重新链入链表*/

 { p1=(BK *)malloc(sizeof(BK));

  fread(p1,sizeof(BK),1,fp);

  p2->next=p1;

 p3=p2;

 p2=p1;

 }

 p3->next=NULL;

  free(p1);

 fclose(fp);

 } 5 编写主函数,执行程序。void main()

 { FILE *fp_book,*fp_reader;

 Login(); if((fp_book=fopen("Book.txt","rb"))==NULL||(fp_reader=fopen("Reader.txt","rb"))==NULL)

  { Init(); }

  else

 Load();

  Menu_select();

 }

 五、测试 说明:细致测试。

 1)登入系统,进行文件初始化。

 N

  2)进入主菜单,开始实现功能。

 3)选择功能 1,输入采编图书信息。

 N

 4)选择 2,登记读者。

 5)执行 3,开始借阅图书,输入借书编号,读者编号,以及还书日期。

 N

  6)执行 6,查询图书信息,发现图书的减少量,库存和预存。

 N

 7)登记图书,采编新书,如果图书已存在,则直接输入数量。

 8)还书模块 4,输入读者及图书的信息。

 N

 9)执行 5,查询读者信息。

 10)再查询图书信息,发现还书后,图书现有量改变。

 N

 11)同一读者不能借同一种书两本。

 12)如果图书为零,则说明书库已经借完等待新书到来。

 N

 13)执行 0,退出系统,保存文件。

 N

 六、总结 说明:总结完成情况、存在的不足 实现各种图书管理功能通过字符串存储,比较会出现一些语言上的小问题,进行修改后可以,同时编写时也会出现许多小问题,其次单链表建立后发现读取文件有一些问题,同时也进行相应的修改,应该采取文件方式读取。不断地改进,调试。