图书管理系统开发

1.1需求分析

市场竞争激烈,图书企业迫切需要采用一种新的管理模式加快图书流通信息的反馈速度:
需要具备以下特点:
1)能够对图书信息进行集中管理;
2)能够大大提升用户的工作效率;
3)能够对图书的信息进行查询;

功能分析:
管理图书是最关键,包括图书的增加,删除(分为通过书名还是通过书号),修改,查询(书名查询还是书号查询),借还(分为借书和还书,只有会员才能实现,需要保留用户的信息)

1.2系统设计

实现的功能如下:
1)录入图书信息;
2)实现删除功能,输入书名或书号删除相应的书;
3)实现查找功能,输入书名或书号查询该书的相关信息;
4)实现修改功能,输入书名或者书号修改相应的信息;
5)添加会员信息,只有会员才能借书;
6)实现借书功能,输入书号与会员号借书;
7)实现还书功能,还书时仍然要输入书号和会员号;
8)保存添加的图书信息;
9)保存添加的会员信息;

该系统的结构设计如图所示

1.3各模块功能实现

1.头文件与宏定义
头文件:

#include <stdio.h>//标准输入/输出函数库;
#include <stdlib.h>//标准函数库;
#include <string.h>//字符串函数库;
#include <conio.h>//屏幕操作函数库;
#include <graphics.h>//因为程序的功能选择界面是在图形模式下实
#include <dos.h>

程序中用到的宏定义:

#define HEADER1 "********************************************************BOOK*****************************************************\n"
#define HEADER2 "* number    |       name                          |price|                author            |                      publishing
campany | number * \n"
#define HEADER3 "******************************************************************************************************************\n"
#define HEADER4 "************************************MEMBER********************************\n"
#define HEADER5 "*number              |     name     |         telephone      *\n "
#define HEADER6 "*******************************************************************\n"
#define HEADER7 "*      mnumber        |member name          |      bnumber           |         book name    *\n"
#define HEADER8 "*****************************************************************************************************************\n"
#define HEADER9 "******************************borrow book***********************************************\n"
#define FORMAT "*%-10s|%-15s|5d|%-15s|%-20s|%5d *\n"
#define FORMAT1 " *%-10s|%-15s|%-15s *\n"
#define FORMAT2 "*%-10s|%-15s|%-10s|%-15s*\n"
#define DATA p->data.num, p->data.name, p->data.price, p->data.author, p->data.pub,p->data.number
#define END "**************************************************************************************************************************\n"
#define Key_Up 0x4800
#define Key_Enter Ox1c0d
#define Key_Down 0x5000

注意,header到end都是输入输出的基本格式,直接将其宏定义就极大的方便了程序的编写,如果不进行这种宏定义,代码中难免多次出现这种字符串,容易引起错误,格式统一,也更加美观,
最后的时候对向上键,向下键,回车键也进行了宏定义

2.结构体及全局变量的定义:

1)结构体book用来存储图书信息,包括书号,书名,定价,作者,出版社,图书的数量

typedef struct book
{char num[10];//书号char name[15];//书名int price;//定价char author[15】;//作者;char pub[20];//出版商int number;//数量
};

2)结构体member用来存放会员信息(包括会员号,会员姓名,联系电话)

typedef struct Member
{char mnum[10];//会员号char mname[15];//会员姓名char tel[15];//联系电话
};

3)结构体borrow用来存储借书信息,包括借书人的会员号,借书人姓名,借出图书的书名和书号
注意借书必须要有会员号

typedef struct borrow
{char mnum[10];//会员号char mname[15];//会员姓名char num[10];//书号char name[15];//书名
};

4)结构体node用来定义图书链表的结点结构:(注意之前定义过了struct book ,这个地方直接拿来用了,这个属于结构体类型的嵌套)

typedef struct node//定义图书信息链表的结点结构
{struct book data;//数据域struct node *next;//指针域
} Node, *Link;

5)结构体mnode定义的是会员信息链表的结点结构(注意struct member 我们之前也定义过这个结构体类型了)

typedef struct mnode//定义会员信息链表的结点结构
{struct Member inf;//数据域struct mnode *next;//指针域
}Mnode, *Mlink;

6)结构体bnode用于定义借书信息链表的结点结构(struct borrow 我们之前也定义过)

typedef struct bnode//定义借书信息链表的结点结构
{struct borrow binf;//数据域struct bnode *next;//指针域
}Bnode, *Blink;

程序中还定义了全局变量,并且对mainmenu 函数进行类声明

void MainMenu();
int Ide, Key;
Link l;
Mlink m;
Blink b;

3.功能选择界面和退出系统设计

综述:其中mainmenu函数用来初始化图形界面,设置背景颜色为白色,调用drawmenu函数绘制出标题和菜单项,菜单中未选中状态为绿色,处于选中状态的选项为红色,接着要获取按键上的信息,当按下向下键时ide++,当按下向上键时ide–,当按下回车键时开始调用judge函数,根据ide的值,退出图形界面,进入相应的操作界面

1)实现功能选择界面的代码:

void DrawMenu(int j)//选项菜单显示的函数
{int n;char *s[10] ={"Add book", "Delete book", "Search book", "Modify book","Add member","Borrow book", "Return book","Save book","Save member","Quit system"};setcolor(RED);//此时输出字体颜色红色settextstyle(0, 0, 4);outtextxy(60, 50, "BOOK MANAGEMENT");//在这个表坐标位置输出book managmentsettextstyle(0, 0, 1);//设置字的字体,大小,样式setcolor(GREEN);for (n = 0; n < 10; n++)outtextxy(250, 110 + n * 20, s[n]);//每隔20输出字符串数组的元素,为了美观setcolor(RED);outtextxy(250, 110 + j * 20, s[j]);//j是函数中的参数,选中哪个菜单,哪个菜单就会变成红色,其他用绿色
}

注意:
1)定义了一个字符串数组,就是我们的功能项;
2)setcolor(red),就是此时输出字体颜色为红色;
3)settexstyle 就是输入字体的格式;
4)outtexxy()就是在这个坐标位置输出这个字符串;
5)接着的这个for循环就是在不同的坐标位置(间隔为20个y坐标)输出上面定义的字符串数组的数组元素;
6)后面的两行代码可以保证,选中哪个菜单,那个菜单就会变成红色;

2)主菜单函数代码

void MainMenu()//主菜单函数
{int gdriver, gmode;void JudgeIde();//这个是后面定义的gdriver = DETECT;initgraph(&gdriver, &gmode, "");setbkcolor(WHITE);//设置背景颜色为白色cleardevice();//清屏Ide = 0, Key = 0DrawMenu(Ide);//因为Ide=0,此时我们进入drawmenu函数,第一项addbook就应该是红色的;默认状态do{If(bioskey(1)//判断是否有按键{Key = bioskey(0);//将按键信息赋给Key,switch (Key){case Key_Down:{Ide++;Ide = Ide % 10;//因为我们这个菜单有10项,当我们加到第11项时,必须要仍能回到这个菜单上来才行,从头选DrawMenu(Ide);//调用drawmenu函数,使对应项变成红色break;}case Key_Up:{Ide--;Ide = (Ide + 10) % 10;//Ide是0的时候,会变成负值,需要加10DrawMenu(Ide);//重新画一下,使对应项变成红色Break;}}}} while (Key != Key_Enter);//判断是否是回车键JudgeIde();//调用judgeide函数
}

2)需要对Ide进行选择,使用judgeide函数

void JudgeIde() //判断Ide的这个函数
{switch (Ide){case 0:{closegraph();//关闭功能菜单Add(l);//调用add函数,实现图书的添加break;}case 1:{closegraph();//关闭功能菜单Del(l);//调用del函数,实现图书信息的删除break;}case 2:{closegraph();//关闭功能菜单search(1);//调用search 函数,实现图书信息的查找break;}case 3:{closegraph();Modify(l);//调用modify函数,实现图书信息的修改break;}case(4):{closegraph();Addmember(l);//添加会员信息break;}case 5:{closegraph();borrow(l, m, b);//实现借书break;}case 6:{closegraph();ret(l,b);//实现还书break;}case 7:{closegraph();Save(1);//实现信息保存;保存图书信息break;}case 8:{closegraph();Savemember(m);//会员信息保存break;}case 9://离开系统{cleardevice();settextstyle(0, 0, 4);outtextsy(150, 200, "goodbye!!!");sleep(1);exit(0);}}
}

3.4.添加图书信息

源码如下:

void Add(Link l)//增加图书记录
{Node *p, *r, *s;char ch, flag = 0, num[10];r = l;s = l->next;system("cls");//清屏Disp(1);//此函数在后面有定义,输出已有的图书的信息while (r->next != NULL)//这两句意思是,如果r的next不为空,还要继续往后指r = r->next;//会将指针移动到链表最末尾,准备添加记录while (l)//可以输入多条记录,输入的如果是0,退出添加操作{stringinput(num, 10, "input number(press '0'return menu):");//后面的函数,规定长度为10,输入的是书号flag = 0;if (strcmp(num, "0") == 0){MainMenu();}s = l->next;while (s)//当s不为空的时候,会一直执行{if (strcmp(s->data.num, num) == 0)//查询输入的书号是否已经存在。{flag = 1;//如果存在,flag就会变为1break;}s = s->next;//如果不相同,在查找下一个}if (flag == 1)//提示用户是否需要重新输入{getchar();printf("======>the number %s is existing,try again?(y/n):", num);scanf("%c", &ch);if (ch == 'y' || ch == 'Y')//如果输入小写y或者大写Y,则就证明要继续进行continue;elseMainMenu();//若不是,则就会返回到功能菜单选择页面}else{break;}}p = (Node*)malloc(sizeof(Node));//申请内存空间if (!p)//说明申请内存空间没有成功{printf("\n allocate memory failure");MainMenu();}strcpy(p->data.num, num);//申请成功,就将字符串copy到p->data.num中stringinput(p->data.name, 15, "Name:");//输入图书名称到p->data.name中p->data.price = numberinput("price");//将定价输入到p->data.price中stringinput(p->data.pub, 20, "publishing company:");//输入图书出版社名称到p->data.number = numberinput("number:");//输入图书的数量p->next = NULL;//也很关键r->next = p;//将新节点插入链表之中r = p;//很关键,r永远指向链表的最后一个节点
}

注意添加完毕时按0键退出添加图书信息的页面,重新返回到功能选择页面,此时要选择savebook一项,保存当前添加的记录,再返回到图书添加页面,就发现刚刚添加的信息已经保存

程序中调用了Disp函数,用于显示单链表l中存储的图书信息

void Disp(Link l)//显示单链表l中存储的图书记录
{Node *p;p = l->next;if (p!)//如果p为空,说明没有记录;{printf("\n====>No record!\n");getchar();return;}printf("\n\n");//为了美观好看printf(HEADER1);printf(HEADER2);printf(HEADER3);while (p)//逐条输出链表中存储的图书信息{printf(FORMAT, DATA);//按照format和data的指定格式输出p = p->next;printf(HEADER3);//输出一排星号,为了分开彼此}
}

3.5图书信息的保存

void Save(Link l)//将数据保存,通过都写入磁盘文件中,实现了保存
{FILE *fp;Node *p;//p是图书信息链表的指针int count = o;fp = fopen("f:\\book", "wb");//以只写的方式打开二进制文件if (fp = NULL)//说明二进制文件没有打开,打开文件失败{printf("n====>open file error!\n");getchar();MainMenu();}p = l->next;//l是头节点,p指向l的下一个while (p)//当p不为空时{if (fwrite(p, sizeof(Node), l, fp) == 1)//如果p不是空,就将相应信息写入fp指向的磁盘文件{p = p->next;//指针后移count++;//记录图书信息的条数}else{break;}}if (count > 0){getchar();printf("\n\n\n\tsave file complete,total saved'srecord number is:%d\n", count);//提示一下保存了多少记录getchar();MainMenu();}else{system("cls");//清屏printf("the current link is empty,no student record is saved!\n");//没有学生记录保存,链表是空的getchar();MainMenu();}fclose(fp);//关闭磁盘文件
}

3.6删除图书信息

void Del(Link l)//删除指定的图书记录
{int sel;Node *p, *r;char findmess[20];if (!l->next)//看看这个链表是不是空链表{system("cls");printf("\n====no record!\n");getchar();MainMenu();}system("cls");Disp(l);//如果链表不是空的,就调用disp函数,显示链表l中的图书存储记录printf("\n            ====> 1.Delete by number         ====>2.Delete bu name  \n");//两种删除方式printf("please choice[1,2]:");scanf("%d", &sel);if (sel == 1)//依据书号删除{stringinput(findmess, 10, "input the existing student number:");//让你输入书号p = Locate(l, findmess, "num");if (p)//p的返回值不为0,说明依据书号查询找到了,接下来就要寻找p这个节点的位置{r = 1;//仍然让r指向表头while (r->next != p)//执行这个语句的时候,r在p的前面,p这个节点就是我们要删除的节点r = r->next;//r跳过p直接指向了p的下一个节点,相当于在这一步,实现了对p节点的删除r->next = p->next;//删除节点要承前启后,承接p后面的节点free(p);//p这个节点现在没用了,我们要将其释放出去printf("\n=======>delete success!\n");getchar();MainMenu();}else//p的返回值为0,说明我们压根没有找到书名为输入书名的这个节点Nofind();//调用函数getchar();MainMenu();}else if (sel == 2)//选择按书名查找{stringinput(findmess, 15, "input the existing book name");p = Locate(l, findmess, "name");if (p){r = 1;while (r->next != p)//r指向节点的下一个节点就是我们要寻找的p节点r = r->next;//直接跳过p节点r->next = p->next;//继承p后面的其他节点free(p);//释放p节点,很好的习惯printf("\n=======>delete success!\n");getchar();MainMenu();}elseNofind();getchar();MainMenu();}elseWrong();getchar();MainMenu();
}

该函数功能如下首先你要输入选择删除书的方式,书名或者书号,当通过书号删除的时候,会提示你输入图书编号。调用stringinput函数输入书号,调用locate 函数查询该图书编号是否存在

void stringinput(char *t, int lens, char *notice)//输入字符串,进行长度验证,lens就是规定的长度,notice也是字符串
{char n[50];do {printf(notice);//显示提示信息scanf("%s", n);//输入字符串if (strlen(n) > lens)//如果输入的字符串大于规定的长度printf("\n exeed the required length!  \n");  } while (strlen(n) > lens);strcpy(t, n);//如果输入的字符串符合要求,就将输入的字符串拷贝到字符串t中
}Node *Locate(Link l, char findmess[], char nameornum[])//链表节点的定位模式,书名或者书号
{Node *r;if (strcmp(nameornum, "num") == 0)//name or num 两种删除方式,如果和num匹配了,说明就是用书号来删除{r = l->next;//r是新定义的链表指针,我们要让他指向链表l的表头节点while (r)//r不为空{if (strcmp(r->data.num, findmess) == 0)//要用链表中的当前节点的书号与输入的书号进行比较,如果一致return r;//返回与输入内容相匹配的节点r = r->next;//否则,节点下移}}else if (strcmp(nameornum, "name") == 0)//如果是按书名来删除{r = l->next;//指针指向链表l表头节点while (r)//当链表不为空时,执行此循环{if (strcmp(r->data.name, findmess) == 0)//如果找到了与输入的书名匹配的节点return r;//返回当前节点的位置r = r->next;//否则就继续向下移}}return 0;//从始至终久未找到,凡是能查到的,都不会执行到return 0这一步
}

如果输入的要删除的信息不存在,也会调用一个函数Wrong函数

void Wrong()//输出按键错误信息
{printf("\n\n\n\n\n***********ERROR:input has wrong!press any key to continue**************\n");getchar();
}

注意:在删除完指定的图书信息之后,务必要对现有的图书信息进行保存,否则下次启动该程序的时候,删除的内容将会依然存在

3.7查询图书信息

void search(Link l)//实现图书的查找
{int select;char searchinput[20];Node *p;if (!l->next)//判断链表是否为空,如果为空,输出如下语句{system("cls");printf("\n======no record!\n");getchar();MainMenu();}system("cls");printf("\n            ====> 1.Search by number         ====>2.Search bu name  \n");//选择查找方式printf("          please choice[1,2]:");scanf("%d", &select);if (select == 1)//书名查找{stringinput(searchinput, 10, "input the existing book number:");//将输入的书号付给了searchinputp = Locate(l, searchinput, "num");//按书号查找,将查找到的结果赋给pif (p)//如果p不为空,说明查找到了{printheader();printdata(p);printf(END);printf("press any key to return\n");}elseNofind();getchar();}else if (select == 2)//如果按署名查找{stringinput(searchinput, 15, "input the existing book name:");p = Locate(l, searchinput, "name");if (p){printheader();printdata(p);printf(END);printf("press any key to return\n");}elseNofind();getchar();}elseWrong();getchar();MainMenu();
}

注意:首先要输入查询的方式,一种是通过书号来查询,一种是通过书名来查询,(当选择通过书号来查询时,会提示输入图书信息编号,用stringinput函数输入书号,locate函数查询书号是否存在),若选择书名来查询时,用stringinput函数来输入书名,locate函数来查询该书名是否存在

在这里也有两个小函数,格式化输出表头和格式化输出表中数据

void printheader()//格式化的一个输出函数
{printf(HEADER1);printf(HEADER2);printf(HEADER3);
}void printdata(Node *pp)//格式化的输出表中数据
{Node *p;p = pp;printf(FORMAT, DATA);//将节点中的内容输出
}

当未查找到这个书的时候,我们又引用了Nofind函数

void Nofind()//输出未查找到此书的信息
{printf("\n=====>not find this record!\n");
}

3.8.修改图书信息

void Modify(Link l)//图书信息修改
{Node *p;char findmess[20];if (!l->next)//链表是否为空{system("cls");printf("\n=====>No book record! \n");getchar();MainMenu();}system("cls");printf("modify book recorder");Disp(l);//将整个图书链表中的信息显示出来stringinput(findmess, 10, "input the existing book number: ");//首先你要输入要修改的书号p = Locate(l, findmess, "num");if (p)//p不为空就是找到了那个节点{printf("Number: %s, \n", p->data.num);printf("Name: %s,", p->data.name);//以上两条是输入原有的信息stringinput(p->data.name, 15, "input book name: ");/*调用函数,输入新的信息*/printf("price: %d,", p->data.price);p->data.price = numberinput("the price of book: ");printf("Author: %s,", p->data.author);stringinput(p->data.author, 15, " Author: ");printf("publishing company: %s,", p->data.pub);stringinput(p->data.pub, 15, "Publishing company: ");printf("number: %d, ", p->data.number);p->data.number = numberinput("the number of book: ");printf("\n=====>modify success! \n");Disp(1);//将整个图书链表的信息再输出一次}elseNofind();getchar();MainMenu();
}

注意:在修改完指定的图书信息之后,无必要对现有的信息再次保存,否则下次启动程序时,修改的内容将不复存在,

3.9.添加会员信息

首先要显示当前存在的会员信息链表:

void Mdisp(Mlink m)//显示单链表m之中存在的会员信息,注意使用的是会员信息链表m,不再是图书信息链表l
{Mnode *p;//会员信息链表指针p = m->next;if (!p)//会员信息链表为空{printf("\n=====>Not record! \n");getchar();return;}printf("n\n");printf(HEADER4);printf(HEADER5);printf(HEADER6);while (p)//逐条输出储存的会员链表的信息{printf(FORMAT1, p->inf.mnum, p->inf.mname, p->inf.tel);p = p->next;printf(HEADER6);}getchar();
}

然后再添加会员信息:

void Addmember(Mlink m)
{FILE *fp;Mnode *p, *r, *s, *q;//对应会员信息的结构体类型char ch, qu, flag = 0, num[10];r = m;s = m->next;system("cls");Mdisp(m);while (r->next != NULL)/*将原有记录输出*//*将指针移至链表最末尾,准备添加记录*/r = r->next;while (1){/*可输入多条记录,输入0时退出添加操作*/stringinput(num, 10, "input the number of the member(press '0'return menu) :");/*输入会员号*/flag = 0/*输入为0,则退出添加操作,返回功能选择界面*/if (strcmp(num, "0") == 0){MainMenu();}s = m->next;/*查询该会员号是否已经存在*/while (s){if (strcmp(s - inf.mnum, num) == 0){flag = 1;break;}s = s->next;/*提示用户是否重新输入*/if (flag == 1){getchar();printf("=====>The number %s is existing, try again?(y/n): " num);scanf("%c", &ch);if (ch == 'y' || ch == ' Y')continue;elseMainMenu();else{break;}}/*申请内存空间*/p = (Mnode *)malloc(sizeof(Mnode));if (!p){/*如没有申请到,输出提示信*/printf("\n allocate memory failure ");MainMenu();}/*返回主界面*/strcpy(p->inf.mnum, num);/*将会员号复制到p->data*/stringinput(p->inf.mname, 15, "Name:");stringinput(p->inf.tel, 15, "Telephone: ");p->next = NULL;r->next = p;/ 将新结点插入链表中 *r = p;}MainMenu();}
}

注意:添加会员信息与添加图书信息的方法是很一致的,输入0时会退出添加界面;同样,添加完会员信息,也要对相关会员信息再次保存,调用下面的函数

void Savemember(Mlink m)//保存会员信息
{FILE *fp;Node *p;int count = 0;fp = fopen("f:\\member", "wb");/*以只写方式打开*/if (fp == NULL){printf("n=====>open file error!\n");/*打开文件失败*/getchar();MainMenu();}p = m->next;while (p){if (fwrite(p, sizeof(Mnode), 1, fp) == 1)/*写记录到磁盘文件中*/{p = p->next;count++;elsebreak;}if (count > 0){getchar();printf("\n\n\n\tsave file complete, total saved's record number is: %d\n"count);getchar();MainMenu();}else{system("cls");getchar();MainMenu();}fclose(fp);}
}

3.10.借书操作

void borrow(Link 1, M1ink m, B1ink b)/*借书第一个是图书信息链表,第二个是会员信息链表,第三个是借书信息链表*/
{Mnode * p;Node *q;Bnode *t, *s, *k;char number[10], booknum[10];system("cls");t = b->next;if (!t)//说明借书信息链表时空的{printf("\n=====>Not record! \n");printf("\n\n");//不空的话就输出这些printf(HEADER9);printf(HEADER7);printf(HEADER8);while (t){printf(FORMAT2, t->binf.mnum, t->binf.mname, t->binf.num, t->binf.name);//以这个格式输出第一个节点信息t = t->next;//指向下一个节点printf(HEADER8);while (1){s = b;//s指向借书信息链表p = m->next;//p指向会员信息链表q = l->next;//q指向图书信息链表while (s->next != NULL)s = s->next;//用这两个语句直到s指向借书链表的最后一个节点stringinput(number, 10, "please input the number of member: ");/*输入会员号*/if (strcmp(number, "0") == 0)//看一下会员号是否为0,如果是0跳出循环break;do{if (strcmp(p->inf.mnum, number) == 0)/*查看该会员号是否存在*/break;//如果会员存在就跳出这个循环elsep = p->next;//和这个节点的会员信息不匹配,p就会指向下一个节点} while (p != NULL);//直到p为空stringinput(booknum, 10, " please input the number of book:");/*输入书号*/do{if (strcmp(q->data.num, booknum) == 0)/*查看书号是否存在*/break;elseq = q->next;} while (q != NULL);//与上面一致if (p == NULL)//你不是会员{printf("you are not a member!");MainMenu();}else if (q == NULL)//书不存在{printf("the book is not exist! ");MainMenu();}else{if (q->data.number != 0)//如果现在图书还有{q->data.number--;//相当于图书现在要借出去一本k = (Bnode*)malloc(sizeof(Bnode));/*申请内存空间*/if (!k){printf("\n allocate memory failure");/*如没有申请到,输出提示*/MainMenu();/*返回功能选择界面,这个时候借书信息还没有保存,也就是书还没有接触去*/}strcpy(k->binf.num, q->data.num);strcpy(k->binf.name, q->data.name);strcpy(k->binf.mnum, p->inf.mnum);strcpy(k->binf.mname, p->inf.mname);k->next = NULL;s->next = k;//把这个节点加到借书信息链表,因为s经过一顿才做之后指向的是最后一个节点s = k;}elsepreintf("no book!");}}Saveoi(b);//保存借书信息getchar();MainMenu();}}
}

注意:进入借书界面之后,会发现显示出了当前借书记录,要求输入会员号,当输入的会员号正确,再输入图书号,如果显示图书库里还有这本书,图书数量会减1,当输入0时会退出借书界面,该程序可以实现对借书信息的自动保存,调用saveoi函数,也是要将借书信息保存到磁盘文件中;

   void Saveoi(Blink b)
{FILE *fp;Bnode *p;int count = 0;fp = fopen("f: \\borrow", "wb");/*以只写方式打开二进制文件或者说新建一个文件*/if (fp == NULL)/*打开文件失败*/{printf("\n=====>open file error!\n");getchar();MainMenu();}p = b->next;//b是借书链表while (p){if (fwrite(p, sizeof(Bnode), 1, fp) == 1)/*每次写一条记录或一个结点信息至文件*/{p = p->next;count++;}else{break;}}if (count > 0){getchar();printf("\n\n\n\n\n=====>save file complete, total saved's record number is: %d\n", count);getchar();MainMenu();}else{system("cls");getchar();MainMenu();}fclose(fp);
}

3.11.还书操作:

void ret(Link 1, Blink b)//第一个指向图书信息,第二个指向借书信息
{Bnode *p, *q;Node *t;char memnum[10], booknum[10];q = b;//借书链表p = q->next;//p指向还书信息链表的首节点t = l->next;stringinput(memnum, 10, "please input the number of member: ");if (strcmp(memnum, " 0") == 0)MainMenu();stringinput(booknum, 10, "please input the number of book: ");while (p != NULL){if (strcmp(p->binf.num, booknum) == 0 && strcmp(p->binf.mnum, memnum) == 0)/* 如果书号与会员号都存在则可以还*/{q->next = p->next;//此举相当于要释放p节点do{if (strcmp(t->data.num, booknum) == 0)//要再图书信息链表之中找到那一本书,将其数量加一break;elset = t->next;} while (t != NULL);t->data.number++;//图书数量加1,还书成功free(p);//释放p节点}else//就是信息不吻合,那就移到下一个节点再进行比较{q = p;p = q->next;}}if (p == NULL)//说明整个链表都走了一遍{printf("input error");MainMenu();}Saveoi(b);getchar();MainMenu();
}

注意:还书功能实现之后依旧要对图书信息进行保存,因为还书成功之后,库存会更形,必须保存

主函数(终章)

main()
{FILE *fp;//注意fp是文件的指针int select;char ch;int count = 0;Node *p, *r;//指向图书信息链表Mnode *q, *t;//指向会员信息链表Bnode *s, *k;//指向借书信息链表b = (Bnode *)malloc(sizeof(Bnode));if (!b){printf("\n allocate memory failure ");MainMenu();}b->next = NULL;k = b;fp = fopen("f:\\borrow,""ab++");//打开借书文件if (fp == NULL){printf("\n====>can not open file!!!\n");exit(0);}while (!feof(fp)){s = (Bnode *)malloc(sizeof(Bnode));//申请一个借书节点if (!s){printf("memory malloc failure!\n");exit(0);}if (fread(s, sizeof(Bnode), l, fp) == 1)//从文件中读取借书记录{s->next = NULL;//保证新节点s是一个孤节点k->next = s;//新节点加入链表k = s;//保证k永远指向链表的最后一个节点}}fclose(fp);//关闭借书文件m = (Mnode*)malloc(sizeof(Mnode));//申请一个会员信息节点if (!m){printf("\n allocate memory failure ");/*如没有申请到, 打印提示信息*/MainMenu();/*返回功能选择界面*/}m->next = NULL;t = m;fp = fopen("f:\\menber", "ab++");//打开会员信息文件if (fp == NULL){printf("\n=====>can not open file!\n");exit(0);}while (!feof(fp)){q = (Mnode*)malloc(sizeof(Mnode));if (!q){printf("memory malloc failure!\n");exit(0);}if (fread(q, sizeof(Mnode), l, fp) == 1){q->next = NULL;//保证要新加进来的节点q是一个孤节点t->next = q;//让新节点q加入到链表中t = q;//t永远指向链表中的最后一个节点}}fclose(fp);/* 关闭文件*/l=(Node *)malloc(sizeof(Node));if (!l){printf("\n allocate memory failure ");/*如没有申请到, 打印提示信息*/MainMenu();/*返回功能选择界面*/}l->next = NULL;r = 1;fp = fopen("f:\\book", "ab+");if (fp == NULL){printf("\n=====>can not open file! n");exit(0);}while (!feof(fp)){p = (Node*)malloc(sizeof(Node));if (!p){printf(" memory malloc failure! \n");/*没有申请成功*/exit(0); /* 大退出 */}if (fread(p, sizeof(Node), 1, fp) == 1)/*从文件中读取图书信息记录*/{p->next = NULL;r->next = p;r = p;count++;}}fclose(fp);printf("\n=====>open file sucess, the total records number is :%d\n",count);MainMenu();
}

至于全部的代码和注释笔者将在下一篇文章中展开

图书管理系统开发实例开发日志相关推荐

  1. jsp mysql视频_手把手教你做jsp servlet mysql实现的图书管理系统附带视频开发教程和完整源码...

    上一个教程我们做的是对数据库框架底层原理的讲解,然后教大家做了一个自己的数据库框架,这次我们做的这个图书管理系统就是用我们上个教程自己写的数据库框架,整个项目做完框架运行的很稳定,没有出现任何问题.如 ...

  2. oa java 二次开发_泛微OA ecology 二次开发实例 开发完整.doc

    泛微OA ecology 二次开发实例 开发完整 二次开发培训文档 ECOLOGY系统框架结构 主要的程序结构 Ecology Classbean 存放编译后的CLASS文件 js 系统中使用的JAV ...

  3. javaee图书管理系统mysql_JavaEE 实例 图书管理系统

    软件151    马金忠 一.打开数据库,成功连接数据库,并导入数据库数据,很简单 ,就不一一进行解释了... 二.编写代码,编写主界面的代码和跳转页面等页面的代码,并调试运行成功: 主要的包和文件如 ...

  4. 图书管理系统【部署开发环境、解决分类、图书、前台页面模块】

    前言 巩固Servlet+JSP开发模式,做一个比较完整的小项目. 成果图 该项目包含了两个部分,前台和后台. 前台用于显示 后台用于管理 该项目可分为5个模块来组成:分类模块,用户模块,图书模块,购 ...

  5. 自学Java day41 图书管理系统-springboot快速开发 从jvav到架构师

    前端:html + css + jvavscript + vue + ajax + axios + element ui 后端:jvav + springboot + mybatisplus + my ...

  6. AgileEAS.NET平台开发实例-开发环境配置

    介绍 从官方网站或者是官方交流群中下载到了AgileEAS.NET的最新的集成化的开发包,然后有了这个条件后,我们就可以进行开发了,当然可能还有一些硬件和软件开发环境 方面的要求了,主要的软硬件环境需 ...

  7. java工作日报管理系统_GitHub - LovebuildJ/book-manager: JavaWeb图书管理系统,简单易用功能强大,可拓展性高,集成主流框架...

    book-manager 介绍 图书管理系统 请勿忽略更新日志, 会有详细的版本更新说明! 软件截图 在线API接口文档 登录 首页轮播 图书列表 图书上架 图书编辑 图书删除 图书借阅 图书检索 图 ...

  8. (附源码)springboot图书管理系统 毕业设计 160934

    Springboot图书管理系统的设计与实现 摘 要 大数据时代下,数据呈爆炸式地增长.为了迎合信息化时代的潮流和信息化安全的要求,利用互联网服务于其他行业,促进生产,已经是成为一种势不可挡的趋势.在 ...

  9. [附源码]java毕业设计图书管理系统论文

    项目运行 环境配置: Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...

最新文章

  1. Unreal Engine4 可视化虚拟现实全流程学习教程
  2. mysql connector放在哪_关于MySQL Connector/C++那点事儿
  3. java 实现验证码功能
  4. SQL刷题,procedure存储过程(hackerrank-sql-Print Prime Numbers),58道题完结撒花啦
  5. IDEA 2022 CPU占用100%问题解决
  6. 微信自动跳转默认浏览器 微信扫一扫直接打开外部浏览器
  7. c语言文件压缩与解压缩实验报告,哈弗曼树文件压缩与解压实验报告(C语言).doc...
  8. win 64 安装 sql server 2000、出现挂起 解决
  9. Android 电子签名
  10. 捷多邦6层板阻抗及压合设计
  11. OneNote 英文默认字体修改方法(2020.10)
  12. 欺骗的艺术----(8)
  13. CUDA10.2+cuDNN8+tensorflow-gpu2.3.1安装
  14. 位图(BMP)文件头格式及数据分析
  15. 求3000以内的全部亲密数。
  16. 年度考核如何实现排名?
  17. js 判断手机操作系统(ios或Android)
  18. 电商企业如何设计订单系统?
  19. 论文笔记:Deeply-Learned Part-Aligned Representations for Person Re-Identification
  20. BZOJ 3143: [Hnoi2013]游走 高斯消元 期望

热门文章

  1. 计算机office二级几天能学完,用3.12天就能1次通关计算机二级Office?!秘诀都在这里了!...
  2. NotePad++ 将数据以16进制显示,HexEditor插件的安装
  3. STM32F4 FLASH
  4. 微信小程序狼人杀游戏代码及步骤
  5. php中文返回乱码,php中文返回乱码怎么办
  6. Mac上mx master鼠标移动卡顿问题的解决
  7. jmeter源码---Mainframe
  8. vuex( 笔记二 )
  9. 电商“进销存”系统——进
  10. 【外汇投资入门与技巧有哪些?】