图书借阅管理是图书馆一个最基本的工作,这里用C语言的知识设计开发一个简单的图书借阅管理系统,系统主要实现图书信息和学生信息的管理,图书查询及图书借阅管理。
系统主要实现以下六个功能:
① 用户登录。系统用户分为管理员和学生。管理员登录时必须输入密码,密码正确才能进入系统;学生登录时无需密码,输入学号即可。
② 图书信息管理。图书信息包括:书号、书名、作者、图书分类、出版社、出版时间、单价、总量和库存量。图书信息管理包括:输入图书信息(从键盘或从文件)、保存图书信息、修改图书信息、增加图书信息、删除图书信息和输出图书信息。
③ 学生信息管理。学生信息包括:学号、姓名、借书卡(借阅标记、书号、借阅时间)。学生信息管理包括:输入学生信息(从键盘或从文件)、保存学生信息、修改学生信息、增加学生信息、删除学生信息和输出学生信息。
④ 图书查询功能。图书查询分为:按书名查询、按作者查询、按图书分类查询、按出版社查询和按出版时间查询。
⑤ 借书功能。借书时,先判断学生是否有空闲的借书卡,若没有则应输出提示信息;若有空闲的借书卡,则要求学生输入所借图书的书号,若该书库存量不为0,则将该书借出,同时在借书卡上记录该书的书号和借阅时间,并修改该书的库存量。
⑥ 还书功能。还书时,先检查学生的借书卡,若借书卡都为空,则不能进行还书操作,若有借书卡不为空,则可以还书,此时要求学生输入所还图书的书号,将对应借书卡上的记录清零,并修改该书的库存量。
系统共定义了四个结构体类型,包括日期类型、借书卡类型、图书类型和学生类型,其中在图书类型中要使用日期类型,而在学生类型中要使用日期和借书卡类型,定义如下:
typedef struct date //日期类型
{ short year; //年
short month; //月
short day; //日
}SDATE;
typedef struct library_card //借书卡类型
{ Short flag; //是否借阅标记
Char ISBN[20]; //所借图书的书号
SDATE bor_time; //借阅时间
}SLCARD;
typedef struct student //学生类型
{ char num[15]; //学号
char name[20]; //姓名
SLCARD card[5]; //借书卡(规定每人最多有5张)
}SSTUD;
typedef struct book //图书类型
{ char ISBN[20]; //书号
char bookname[40]; //书名
char author[20]; //作者
char publisher[30]; //出版社
char bookclass[20]; //图书分类
short total_num, stock_num; //总量,库存量
float price; //单价
SDATE publish_time; //出版时间
}SBOOK;
系统定义了两个全局变量数组,分别存放图书信息和学生信息,因数组大小是固定的,为使用方便在系统中定义两个符号常量,具体定义如下:
#define BOOKNUM 1000 // BOOKNUM为系统允许的最大图书数量
#define STUDNUM 100 // STUDNUM为系统允许的最多学生人数
SSTUD student[STUDNUM]={0}; //学生数组,初始化为0
SBOOK book[BOOKNUM]={0}; //图书数组,初始化为0
(1) main函数的设计:由于图书信息和学生信息都保存在文件中,系统运行的第一个工作是从文件中将图书信息和学生信息读入到内存数组book和数组student中,在读入信息的过程中同时统计出目前图书的数量和学生的人数,并将数据分别存放在整型变量bn和sn中,bn为图书数量,sn为学生人数。如果bn=0或sn=0,系统会输出提示信息,让管理员输入图书信息和学生信息。然后系统会显示主菜单,用户必须登录后才能使用系统提供的各种服务。
(2) 用户登录管理模块包括2个函数:ManagerLogin()和StudentLogin(),该模块由main函数调用。
函数ManagerLogin()用来完成管理员登录工作,首先要求管理员用户输入密码,若密码错误,则直接返回主菜单界面;密码正确时将显示管理员用户的功能菜单,输入数字可执行相应的功能。
函数StudentLogin()用来完成学生登录工作,要求学生输入学号,若学号错误则要求学生重新输入学号;输入学号正确则显示学生用户的功能菜单,输入数字可执行相应的功能。
(3) 图书信息管理模块包括11个函数:InputOnebook()、LoadBooks()、SaveOnebook()、SaveAllbooks()、OriginalBook()、ModifyBook()、AddBook()、DelBook()、OutputOnebook()、OutputAllbooks()和OutputBrief ()。只有管理员用户可以调用图书信息管理模块。
函数InputOnebook()用来实现从键盘输入一本图书的全部信息。
函数LoadBooks()用来实现从文件“book.dat”中输入全部图书的信息,并将这些数据存放到内存数组book中。
函数SaveOnebook()用来实现将一本图书的信息保存到文件“book.dat”中。
函数SaveAllbooks()用来实现将全部图书的信息保存到文件“book.dat”中。
函数OriginalBook()用来实现图书信息的初始化,在程序第1次运行时必须调用该函数,输入若干本图书的信息,并将这些信息保存在文件中。该函数是通过循环多次调用InputOnebook()函数实现多本图书信息的输入,然后调用SaveAllbooks()函数将已输入的所有图书的信息保存在文件“book.dat”中。
函数ModifyBook()用来实现对图书信息的修改,用户首先输入书号,书号错误则输出提示信息,要求用户重新输入;书号正确则用户可以选择要修改的数据项对图书信息进行修改(用switch结构实现),一本图书的信息修改完毕后,调用SaveOnebook()函数,将修改后的信息保存到文件中。然后询问用户是否继续修改其他图书的信息,用户选择‘y’,则重复上述的修改过程;用户选择‘n’,则结束函数,返回到管理员菜单界面。
函数AddBook()用来实现添加图书信息,通过调用InputOnebook()函数,从键盘输入一本图书的信息,然后将该信息写入文件。然后询问用户是否继续添加其他图书的信息,用户选择‘y’,则重复上述过程;用户选择‘n’,则结束函数,返回到管理员菜单界面。
函数DelBook()用来实现删除图书信息,用户首先输入书号,书号错误则输出提示信息,要求用户重新输入;书号正确则会先输出该书号对应图书的信息,然后询问用户是否确定要删除该书的信息,用户选择‘y’才能真正删除该书信息。最后询问用户是否继续删除其他图书的信息,用户选择‘y’,则重复上述过程;用户选择‘n’,则结束函数,返回到管理员菜单界面。
函数OutputOnebook()用来实现输出一本图书的全部信息。
函数OutputAllbooks()通过多次调用OutputOnebook()函数来实现输出全部图书的信息。
函数OutputBrief()用来实现以列表方式输出全部图书的简要信息,简要信息包括:书号、书名、作者和总量。
(4) 学生信息管理模块包括10个函数:InputOnestud()、LoadStuds()、SaveOnestud()、SaveAllstuds()、OriginalStud()、ModifyStud()、AddStud()、DelStud()、OutputOnestud()和OutputAllstuds()。 管理员用户可以使用学生信息管理模块的全部功能,学生用户只能使用该模块中的一个功能,即OutputOnestud()函数(输出一个学生的信息)。
学生信息管理模块中函数的实现方法与图书信息管理中的类似,以下仅作简单说明。
函数InputOnestud()用来实现从键盘输入一个学生的信息。
函数LoadStuds()用来实现从文件“stud.dat”中输入全部学生的信息,并将这些数据存放到内存数组student中。
函数SaveOnestud()用来实现将一各学生的信息保存到文件“stud.dat”中。
函数SaveAllstuds()用来实现将全部学生的信息保存到文件“stud.dat”中。
函数OriginalStud()用来实现学生信息的初始化,在程序第1次运行时必须调用该函数。该函数是通过循环多次调用InputOnestud()函数实现多个学生信息的输入,然后调用SaveAllstuds()函数将已输入的所有学生的信息保存在文件“stud.dat”中。
函数ModifyStud()用来实现学生信息的修改。
函数AddStud()用来实现添加学生信息。
函数DelStud()用来实现删除学生信息。
函数OutputOnestud()用来实现输出一个学生的全部信息。
函数OutputAllstuds()用来实现输出全部学生的基本信息(即学号和姓名)。
(5) 图书信息查询模块包括6个函数:SearchMenu()、SearcBname()、SearchAuthor()、SearchBclass()、SearchPublisher()、SearchPubtime()。管理员和学生都可以使用图书信息查询模块。
函数SearchMenu()用来显示图书查询服务菜单,用户输入数字可执行相应的查询服务。
函数SearcBname()用来实现按书名进行图书信息的查询。用户可以输入完整的书名进行精确查询(如输入“C语言程序设计”),精确查询是使用字符串比较函数strcmp(),将输入的书名与已有图书的书名逐一进行比较,当该函数的返回值等于0,表示这两个书名完全相同,即找到要查询的图书。另外,用户也可以输入书名中的几个字进行模糊查询(如输入“C语言”,或输入“程序设计”),模糊查询是使用求子串函数strstr(),在已有图书的书名中寻找输入的字符串,如果该函数的返回值不为空,则说明该书名中包含这个字符串,那么就应该输出这本图书的信息。通常,模糊查询会列出多个查询结果。
函数SearchAuthor()用来实现按作者姓名进行图书信息的查询。用户可以输入完整的姓名进行精确查询(如输入“谭浩强”),也可以只输入姓氏进行模糊查询(如只输入“张”),具体方法与按书名查询类似。
函数SearchBclass()用来实现按图书分类进行图书信息的查询。考虑到用户可能不能输入完全正确的图书分类名称,所以在该函数中只采用模糊查询方式。
函数 SearchPublisher()用来实现按出版社名称进行图书信息的查询。用户在输入出版社名称时,一般不会输入“出版社”这三个字(如想查询清华大学出版社的图书,通常用户会输入“清华大学”),所以在该函数中也是只采用模糊查询方式。
函数 SearchPubtime()用来实现按出版日期进行图书信息的查询。使用该函数必须注意要按系统规定的格式输入日期,若想查询2004年5月份出版的图书,则应输入“2004.5”;若想查询2004年出版的图书,则应输入“2004”。假设输入日期为“2004.5”,进行查询时,先判断输入的年份与出版日期中的年份是否相等,若不相等则结束本次循环,若相等则用变量k记录其下标,然后再判断月份是否相等,月份若不相等则用continue结束本次循环,月份若相等则可输出这本书(即第k本书)的信息,然后再继续判断下一本图书。
(6) 图书借阅管理模块包括2个函数:BorrowBook()和ReturnBook()函数。
函数BorrowBook()用来实现借书管理。由学生类型定义可知,每个学生有5张借书卡,借书卡的信息包括:借阅标记flag、所借图书的书号ISBN和借阅时间bor_time。借书时,首先查找学生是否有空闲的借书卡(即判断该生借书卡的借阅标记flag是否为0),若flag为0,则可以借书,这时要求学生输入要借图书的书号,然后在图书数组book中查找该书,若在数组book中没找到该书,则提示“输入的书号有误,请重新输入!”;若找到该书,则先判断该书的库存量是否为0,若库存量为0则提示"抱歉!该书库存量为0,无法借阅!”。若库存量大于0,则将该书借给学生,此时需要进行以下6步操作:
step1 将该书的库存量减1;
step2 学生借书卡的借阅标记flag置1;
step3 学生借书卡的书号填写上该书的书号;
step4 学生借书卡的借阅时间赋值为系统时间;为了提取系统时间,首先定义一个结构体变量d:struct tm d; 结构体类型struct tm定义在文件“time.h”中,具体定义如下:
struct tm
{ int tm_sec; // seconds after the minute - [0,59]
int tm_min; // minutes after the hour - [0,59]
int tm_hour; // hours since midnight - [0,23]
int tm_mday; // day of the month - [1,31]
int tm_mon; // months since January - [0,11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0,6]
int tm_yday; // days since January 1 - [0,365]
int tm_isdst; // daylight savings time flag
};
这里我们需要使用其中的3个成员:tm_year、tm_mon和tm_mday。通过调用函数_getsystime(&d); 可以得到系统时间,假设用下面语句输出日期:
printf("%d.%d.%d", d.tm_year, d.tm_mon, d.tm_mday);
若借书日期是1998.5.12,则会输出98.4.12,若借书日期为2005.5.12,则会输出105.4.12,这样的输出结果显然不好,为了正确输出1998.5.12或2005.5.12,必须对成员tm_year和tm_mon进行处理,对于tm_mon的处理比较简单,直接加1即可(d.tm_mon+1),对于tm_year按下面方法处理:如果年份整除100等于0(即年份<2000),则年份=1900+d.tm_year;如果年份整除100等于1(即年份>=2000), 则年份=2000+d.tm_year%100。
step5 保存修改过的图书信息和学生信息;
step6 提示用户借书成功。
最后询问学生是否"继续借书吗?(y/n)",若学生输入‘y’,则重复上面的借书过程;若输入‘n’,则返回到学生功能选择菜单界面。
函数ReturnBook()用来实现还书管理。还书时,首先统计该生有几张已使用的借书卡,将数据存放在变量t中,若t为0,说明该生目前根本没有借阅的图书,无法进行还书操作;若t大于0,则可进行还书操作,先输入书号,在学生的借书卡中寻找,若没找到该书号,则提示"输入的书号有误,请重新输入!";若找到该书号,则通过以下6个步骤进行还书:
step1 学生借书卡的借阅标记flag置0;
step2 学生借书卡的书号置空;
step3 学生借书卡的借阅时间清0;
step4 变量t减1;
step5 在数组book中寻找该书号,找到后其库存量加1;
step6保存修改过的图书信息和学生信息。
最后询问学生是否"继续还书吗?(y/n)",若学生输入‘y’,则重复上面的还书过程;若输入‘n’,则返回到学生功能选择菜单界面。
#include
#include
#include
#include
#include
// 结构体类型的定义
typedef struct date //日期类型
{ short year; //年
short month; //月
short day; //日
}SDATE;
typedef struct library_card //借书卡类型
{ short flag; //是否借阅标记
char ISBN[20]; //所借图书的书号
SDATE bor_time; //借阅时间
}SLCARD;
typedef struct stud //学生类型
{ char num[15]; //学号
char name[20]; //姓名
SLCARD card[5]; //借书卡
}SSTUD;
typedef struct book //图书类型
{ char ISBN[20]; //书号
char bookname[40]; //书名
char author[20]; //作者
char publisher[30]; //出版社
char bookclass[20]; //图书分类
short total_num, stock_num; //总量,库存量
float price; //单价
SDATE publish_time; //出版时间
}SBOOK;
#define SDATE_LEN sizeof(SDATE) //SDATE_LEN为日期类型占用存储空间的大小
#define SLCARD_LEN sizeof(SLCARD) //SLCARD_LEN为借书卡类型占用存储空间的大小
#define SSTUD_LEN sizeof(SSTUD) //SSTUD_LEN为学生类型占用存储空间的大小
#define SBOOK_LEN sizeof(SBOOK) //SBOOK_LEN为图书类型占用存储空间的大小
#define BOOKNUM 1000 //图书总数,可按需要更改其数值
#define STUDNUM 100 //学生总数,可按需要更改其数值
SSTUD student[STUDNUM]={0}; //学生数组(全局变量)
SBOOK book[BOOKNUM]={0}; //图书数组(全局变量)
//函数声明
void ManagerLogin(int *pbn, int *psn); //管理员登录函数
void StudentLogin(int bn, int sn); //学生登录函数
void InputOnebook(int i); //输入一本图书信息的函数
int LoadBooks(void); //从文件载入全部图书信息的函数
void SaveOnebook(int i); //保存一本图书信息的函数
void SaveAllbooks(int bn); //保存全部图书信息的函数
int OriginalBook(void); //图书信息初始化的函数
void ModifyBook(int bn); //修改图书信息的函数
int AddBook(int bn); //添加图书信息的函数
int DelBook(int bn); //删除图书信息的函数
void OutputOnebook(int i); //输出一本图书信息的函数
void OutputAllbooks(int bn); //输出全部图书详细信息的函数
void OutputBrief(int bn); //输出全部图书简要信息的函数
void InputOnestud(int i); //输入一个学生信息的函数
int LoadStuds(void); //从文件载入全部学生信息的函数
void SaveOnestud(int i); //保存一个学生信息的函数
void SaveAllstuds(int sn); //保存全部学生信息的函数
int OriginalStud(void); //学生信息初始化的函数
void ModifyStud(int sn); //修改学生信息的函数
int AddStud(int sn); //添加学生信息的函数
int DelStud(int sn); //删除学生信息的函数
void OutputOnestud(int i); //输出一个学生信息的函数
void OutputAllstuds(int sn); //输出全部学生信息的函数
void SearchMenu(int bn); //图书查询函数
void SearcBname (int bn); //按书名查询函数
void SearchAuthor(int bn); //按作者查询函数
void SearchBclass(int bn); //按图书分类查询函数
void SearchPublisher(int bn); //按出版社查询函数
void SearchPubtime(int bn); //按出版时间查询函数
void BorrowBook(int bn,int m); //借书函数
void ReturnBook(int bn,int m); //还书函数
void main(void) // main函数定义
{
int select, bn, sn;
bn=LoadBooks(); //调用LoadBooks(),返回值为图书数量,将其赋值给bn
if(bn==0) printf(" 图书信息为空!\n\n");
sn=LoadStuds(); //调用LoadStuds(),返回值为学生人数,将其赋值给sn
if(sn==0) printf(" 学生信息为空!\n\n");
while(1)
{
printf("\n");
printf("\t--------------------------------------\n");
printf("\t* *\n");
printf("\t* 图书借阅管理系统 *\n");
printf("\t* *\n");
printf("\t---------------------------------------\n\n");
printf("\t 1. 管理员\n");
printf("\t 2. 学生\n");
printf("\t 0. 退出系统\n\n");
printf("\t 请选择用户:");
scanf("%d", & select);
getchar(); //该函数用于读取回车符,消除对以后数据输入的影响
switch(select)
{
case 1: ManagerLogin(&bn,&sn); break;
case 2: StudentLogin(bn,sn); break;
case 0: printf("\n 谢谢使用!再见\n"); exit(1);
default: printf("\n 按键错误,请重新选择!\n");
} //end switch
} //end while
}
//用户登录模块的函数定义
//====================================================================//
// 功能:实现管理员登录, 显示管理员用户的菜单,进行功能选择
// 参数:pbn、psn分别为main函数中变量bn、sn的地址
// 返回:无
// 主要思路:用strcmp函数实现密码验证,用switch结构实现菜单功能选择
//====================================================================//
void ManagerLogin(int *pbn, int *psn)
{
int select, flag=0;
char password[11]; //密码最多为10位
printf("\n 请输入密码:");
gets(password);
if(strcmp(password, "123")!=0) //密码按需要事先设置好,这里假设为“123”
{ printf("\n 密码错误!\n");
return; //若密码错误,返回主菜单
}
while(1)
{
printf("\n");
printf(" 管理员,您好!\n");
printf("-----------------------------------------------------------------------\n");
printf(" 1. 图书信息初始化 7. 学生信息初始化\n");
printf(" 2. 修改图书信息 8. 修改学生信息\n");
printf(" 3. 增加图书信息 9. 增加学生信息\n");
printf(" 4. 删除图书信息 10. 删除学生信息\n");
printf(" 5. 输出图书信息 11. 输出学生信息\n");
printf(" 6. 图书信息查询 0. 返回主菜单\n");
printf("\n 请选择您需要的服务(0-11):");
scanf("%d", & select); getchar();
switch(select)
{
case 1: *pbn=OriginalBook(); break;
case 2: ModifyBook(*pbn); break;
case 3: *pbn=AddBook(*pbn); break;
case 4: *pbn=DelBook(*pbn); break;
case 5: printf(" 输出详细信息请按'1', 输出简要信息请按'2':");
scanf("%d", &flag); getchar();
if(flag==1) OutputAllbooks(*pbn);
if(flag==2) OutputBrief(*pbn);
break;
case 6: SearchMenu(*pbn); break;
case 7: *psn=OriginalStud(); break;
case 8: ModifyStud(*psn); break;
case 9: *psn=AddStud(*psn); break;
case 10: *psn=DelStud(*psn); break;
case 11: OutputAllstuds(*psn); break;
case 0: return;
default: printf("\n 按键错误,请重新选择!\n");
} //end switch
} //end while
}
//====================================================================//
// 功能:实现学生登录, 显示学生用户菜单,进行功能选择
// 参数:bn表示图书数量,sn表示学生人数
// 返回:无
// 主要思路:用strcmp函数实现学号验证,用switch结构实现菜单功能选择
//====================================================================//
void StudentLogin(int bn, int sn)
{
int select, j, m=-1;
char snum[15]; //数组snum用来存放登录学生的学号
if(sn==0)
{ printf("\n 学生信息为空,无法执行操作!\n");
return;
}
while(1)
{
printf("\n 请输入你的学号:");
gets(snum);
for(j=0; j
if(strcmp(student[j].num, snum)==0)
{ m=j; //找到该学号后记录其下标
break;
}
if(m<0) //m小于0表示数组中没有找到输入的学号
printf("\n 学号错误,请重新输入!\n");
else //m大于等于0,表示存在这个学生的信息
while(1)
{
printf("\n");
printf(" 同学,你好!\n");
printf("--------------------------------------\n");
printf(" 1. 输出个人借书信息\n");
printf(" 2. 图书信息查询\n");
printf(" 3. 借书\n");
printf(" 4. 还书\n");
printf(" 0. 返回主菜单\n");
printf("\n 请选择你需要的服务(0-4):");
scanf("%d", & select); getchar();
switch(select)
{
case 1: OutputOnestud(m); break;
case 2: SearchMenu(bn); break;
case 3: BorrowBook(bn, m); break;
case 4: ReturnBook(bn, m); break;
case 0: return;
default: printf("\n 按键错误,请重新选择!\n");
}//end switch
}
}
}
//图书信息管理模块的函数定义
//====================================================================//
// 功能:从键盘输入一本图书的全部信息
// 参数:i表示对第i本图书进行输入操作
// 返回:无
// 主要思路:按提示信息用scanf输入图书的各项信息,存放到数组book中
//====================================================================//
void InputOnebook(int i)
{
printf(" 书号:");
gets(book[i].ISBN);
printf(" 书名:");
gets(book[i].bookname);
printf(" 作者:");
gets(book[i].author);
… 略
}
//====================================================================//
// 功能:从文件“book.dat”中载入全部图书的信息
// 参数: 无
// 返回:返回文件中图书的数量
// 主要思路:用while循环从文件中读取图书信息到数组book,同时统计图书数量
//====================================================================//
int LoadBooks(void)
{
FILE *fb;
int bn=0; //变量bn用来记录图书的数量
if((fb=fopen("book.dat", "rb+"))==NULL) //以二进制读、写方式打开文件
{ printf("can't open file book.dat\n");
return(bn); //文件打开失败时,返回值为0
}
while(!feof(fb)) //文件没有结束时进行读数据操作
if(fread(&book[bn], SBOOK_LEN,1,fb))
bn++; //从文件中每读一本图书,图书数量加1
fclose(fb); //关闭文件
return(bn); //返回图书数量,即bn的值
}
//====================================================================//
// 功能:将一本图书的信息保存到文件“book.dat”中
// 参数:i表示将第i本图书的信息保存到文件中
// 返回:无
// 主要思路:先用fseek函数定位,再用fwrite函数写入第i本图书的信息
//====================================================================//
void SaveOnebook(int i)
{
略
}
//====================================================================//
// 功能:将全部图书的信息保存到文件“book.dat”中
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:用fwrite函数将数组book中的数据一次性写入文件
//====================================================================//
void SaveAllbooks(int bn)
{
略
}
//====================================================================//
// 功能:实现图书信息的初始化
// 参数:无
// 返回:输入图书的数量
// 主要思路:用for循环实现输入多本图书信息,并写入文件
//====================================================================//
int OriginalBook(void)
{
int n;
char c='y';
for(n=0; c=='y'||c=='Y'; n++)
{
printf("\n 输入图书%d的信息:\n", n+1);
InputOnebook(n); //调用函数,输入第n本图书
printf("\n 继续输入请按'y', 停止请按'n':");
c=getchar(); getchar();
}
SaveAllbooks(n); //将输入的n本图书的数据保存至文件
return(n); //返回n的值,即输入图书的数量
}
//====================================================================//
// 功能:修改图书信息
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:通过switch实现修改图书的任意信息项,并将修改后的信息写入文件
//====================================================================//
void ModifyBook(int bn)
{
int select, k=-1;
char isbn[20], c1='y', c2;
if(bn==0)
{ printf("\n 图书信息为空,无法执行操作!\n");
return; //返回到管理员功能选择菜单
}
while(c1=='y'||c1=='Y')
{
c2='y';
printf("\n 请输入要修改的图书的书号:");
gets(isbn);
for(int i=0; i
if(strcmp(book[i].ISBN, isbn )==0)
{ k=i;
break;
}
if(k<0) // k小于0,表示在数组book中没找到输入书号对应的图书
printf("\n 输入的书号有误,请重新输入!\n");
else // k大于等于0,表示找到该图书,应进行以下操作
{ printf("\n 显示此图书信息:\n");
OutputOnebook(k); //显示该图书的全部信息
while(c2=='y'||c2=='Y')
{
printf("\n 图书信息包括以下数据项\n");
printf("-------------------------------------------------\n");
printf(" 1. 书号 6. 总量\n");
printf(" 2. 书名 7. 库存量\n");
printf(" 3. 作者 8. 单价\n");
printf(" 4. 出版社 9. 出版时间\n");
printf(" 5. 图书分类\n");
printf("\n 请选择要修改的数据项(1-9):");
scanf("%d", & select); getchar();
switch(select)
{
case 1: printf(" 书号:");
gets(book[k].ISBN);
break;
case 2: printf(" 书名:");
gets(book[k].bookname);
break;
case 3: printf(" 作者:");
gets(book[k].author);
break;
case 4: printf(" 出版社:");
gets(book[k].publisher);
break;
case 5: printf(" 图书分类:");
gets(book[k].bookclass);
break;
case 6: printf(" 总量:");
scanf("%d",&book[k].total_num); getchar();
book[k].stock_num=book[k].total_num; //新库存量=新总量
break;
case 7: printf(" 库存量:");
scanf("%d", &book[k].stock_num); getchar();
if(book[k].stock_num>book[k].total_num)
book[k].stock_num=book[k].total_num;
break;
case 8: printf(" 单价:");
scanf("%f", &book[k].price); getchar();
break;
case 9: printf(" 出版时间(年.月):");
scanf("%d.%d", &book[i].publish_time.year,
&book[i].publish_time.month);
getchar();
break;
default: printf("\n 按键错误,请重新输入!\n");
} //end switch
printf("\n 还要修改此图书的其他信息吗?(y/n):");
c2=getchar(); getchar();
} //end while(c2)
}
SaveOnebook(k); //保存修改后的图书信息
printf("\n 还需要修改其它图书的信息吗?(y/n):");
c1=getchar(); getchar();
} //end while(c1);
printf("\n 按任意键继续!\n");
getch();
}
//====================================================================//
// 功能:添加图书信息
// 参数:bn表示添加前的图书数量
// 返回:添加后的图书数量
// 主要思路:调用InputOnebook函数输入要添加的图书信息,再用fwrite将其写入文件
//====================================================================//
int AddBook(int bn)
{
char c='y';
FILE *fb;
if((fb=fopen("book.dat","ab"))==NULL) // 以二进制追加方式打开文件
{ printf("can't open file book.dat\n");
exit(1);
}
while(c=='y'||c=='Y')
{
printf("\n 请输入新增图书的信息:\n");
InputOnebook(bn); //调用函数,输入第bn本图书的信息
fwrite(&book[bn],SBOOK_LEN,1,fb); //将第bn本图书的信息保存至文件
bn++; //图书数量加1
printf("\n 继续输入其它新图书的信息吗?(y/n):");
c=getchar(); getchar();
}
printf("\n 按任意键继续!\n");
getch();
fclose(fb);
return(bn); //返回添加图书后的图书数量
}
//====================================================================//
// 功能:删除图书信息
// 参数:bn表示删除前的图书数量
// 返回:删除后的图书数量
// 主要思路:先输入要删除图书的书号,找到该书后进行删除操作,再调用SaveAllbooks
// 函数将删除后的图书信息写入文件
//====================================================================//
int DelBook(int bn)
{
int i, k=-1;
char isbn[20], c1='y', c2;
if(bn==0)
{ printf("\n 图书信息为空,无法执行操作!\n");
return(bn);
}
while(c1=='y'||c1=='Y')
{
c2='n';
printf("\n 请输入要删除的图书的书号:");
gets(isbn);
for(i=0; i
if(strcmp(book[i].ISBN, isbn)==0)
{ k=i; break; } //找到要删除的图书,用k记录其下标
if(k<0) //k小于0,表示没找到输入书号所对应的图书
printf("\n 输入的书号有误,请重新输入!\n");
else
{ printf("\n 显示该图书的信息:\n");
OutputOnebook(k);
printf("\n 确定要删除该图书的全部信息吗?(y/n):");
c2=getchar(); getchar();
if(c2=='y') //c2为’y’,表示确定进行删除操作
{ for(i=k; i
book[i]=book[i+1]; //从数组中删除第k本图书
bn--; //图书数量减1
printf("\n 成功删除!\n");
}
else //c2为’n’,表示不进行删除操作
printf("\n 取消删除!\n");
printf("\n 继续删除其它图书的信息吗?(y/n):");
c1=getchar(); getchar();
}
} //end while
SaveAllbooks(bn); //保存删除后的全部图书信息
printf("\n 按任意键继续!\n"); getch();
return(bn); //返回删除后的图书数量
}
//====================================================================//
// 功能:输出一本图书的全部信息
// 参数:i表示对第i本图书进行输出操作
// 返回:无
// 主要思路:用printf函数输出一本图书的全部信息
//====================================================================//
void OutputOnebook(int i)
{
略
}
//====================================================================//
// 功能:输出全部图书的详细信息
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:通过for循环多次调用OutputOnebook函数输出全部图书的信息
//====================================================================//
void OutputAllbooks(int bn)
{
略
}
//====================================================================//
// 功能:以列表方式输出全部图书的简要信息
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:用for循环输出全部图书的简要信息(书号、书名、作者、库存量)
//====================================================================//
void OutputBrief(int bn)
{
int i;
printf("\n 全部图书的简要信息:\n");
printf("\n 序号 书号 书名 作者 库存量 \n");
for(i=0;i
{
printf(" %2d %-18s %-20s", i+1, book[i].ISBN, book[i].bookname);
printf(" %-8s %2d\n", book[i].author, book[i].stock_num);
}
printf("\n 按任意键继续!\n");
getch();
}
//学生信息管理模块的函数定义
//====================================================================//
// 功能:输入一个学生信息
// 参数:i表示对第i个学生进行输入操作
// 返回:无
// 主要思路:用gets函数输入学生的学号和姓名
//====================================================================//
void InputOnestud(int i)
{
略
}
//====================================================================//
// 功能:从文件“stud.dat”中载入全部学生的信息
// 参数: 无
// 返回:返回文件中学生的人数
// 主要思路:用while循环从文件中读取学生信息到数组student,同时统计学生人数
//====================================================================//
int LoadStuds(void)
{
参考LoadBooks函数
}
//====================================================================//
// 功能:保存一个学生信息
// 参数:i表示将第i个学生的信息保存到文件中
// 返回:无
// 主要思路:先用fseek函数定位,再用fwrite函数写入第i个学生的信息
//====================================================================//
void SaveOnestud(int i)
{
FILE *fs;
if((fs=fopen("stud.dat","rb+"))==NULL) //以二进制读、写方式打开文件
{ printf("can't open file stud.dat\n"); exit(1); }
fseek(fs, SSTUD_LEN*i, 0); //文件指针定位到第i个学生
fwrite(&student[i], SSTUD_LEN, 1, fs); //将第i个学生的信息写入文件
fclose(fs);
}
//====================================================================//
// 功能:将全部学生信息保存到文件“stud.dat”中
// 参数:sn表示学生人数
// 返回:无
// 主要思路:用fwrite函数将数组student中的数据一次性写入文件
//====================================================================//
void SaveAllstuds(int sn)
{
略
}
//===================================================================//
// 功能:实现学生信息的初始化
// 参数:无
// 返回:学生人数
// 主要思路:用for循环多次调用InputOnestud函数实现输入多个学生信息,并写入文件
//====================================================================//
int OriginalStud(void)
{
int n;
char c='y';
for(n=0; c=='y'||c=='Y'; n++)
{
printf("\n 输入学生%d的信息:\n", n+1);
InputOnestud(n); //调用函数,输入第n个学生的信息
printf("\n 继续输入请按'y'; 停止请按'n':");
c=getchar(); getchar();
}
SaveAllstuds(n); //将输入的n个学生的信息保存到文件中
return(n); //返回学生人数,即n的值
}
//====================================================================//
// 功能:修改学生信息
// 参数:sn表示学生人数
// 返回:无
// 主要思路:通过switch实现修改学生的任意信息项,并将修改后的信息写入文件
//====================================================================//
void ModifyStud(int sn)
{
修改方法与ModifyBook函数类似,代码略。
}
//====================================================================//
// 功能:添加学生信息
// 参数:sn表示添加前的学生人数
// 返回:添加后的学生人数
// 主要思路:调用InputOnestud函数输入要添加的学生信息,再用fwrite将其写入文件//====================================================================//
int AddStud(int sn)
{
添加方法与AddBook函数类似,代码略。
}
//====================================================================//
// 功能:删除学生信息
// 参数:sn表示删除前的学生人数
// 返回:删除后的学生人数
// 主要思路:先输入要删除学生的学号,找到该学生后进行删除操作,再调用SaveAllstuds
// 函数将删除后的学生信息写入文件
//====================================================================//
int DelStud(int sn)
{
删除方法与DelBook函数类似,代码略。
}
//====================================================================//
// 功能:输出一个学生信息
// 参数:i表示输出第i个学生的信息
// 返回:无
// 主要思路:输出一个学生信息,并输出目前所借图书的书号和借阅时间
//====================================================================//
void OutputOnestud(int i)
{
略
}
//====================================================================//
// 功能:输出全部学生信息
// 参数:sn表示学生人数
// 返回:无
// 主要思路:用for循环输出全部学生的信息
//====================================================================//
void OutputAllstuds(int sn)
{
int i, j, t;
printf("\n 全部学生的信息:\n");
printf("\n 序号 学号 姓名 所借图书书号 借阅时间\n");
for(i=0; i
{
printf(" %2d %10s %6s ", i+1, student[i].num, student[i].name);
for(j=0,t=0; j<5; j++)
if(student[i].card[j].flag)
{ if (t) printf("\n%26c", ' '); //输出空格
printf(" %-20s",student[i].card[j].ISBN);
printf("%d.%d.%d", student[i].card[j].bor_time.year,
student[i].card[j].bor_time.month,student[i].card[j].bor_time.day);
t=1;
}
printf("\n\n");
}
printf("\n 按任意键继续!\n"); getch();
}
//图书查询模块的函数定义
//====================================================================//
// 功能:显示图书查询菜单,实现功能选择
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:采用switch结构实现图书查询功能的选择
//====================================================================//
void SearchMenu(int bn) //函数功能是显示图书查询菜单
{
int select;
while(1)
{
printf("\n 欢迎使用图书查询服务\n");
printf("-----------------------------------------------------------\n");
printf(" 1. 按书名查询 2. 按作者查询\n");
printf(" 3. 按出版社查询 4. 按出版时间查询\n");
printf(" 5. 按图书分类查询 0. 退出查询服务\n");
printf("\n 请选择查询方式(0-5):");
scanf("%d", & select); getchar();
switch(select)
{
case 1: SearcBname (bn); break;
case 2: SearchAuthor(bn); break;
case 3: SearchPublisher(bn); break;
case 4: SearchPubtime(bn); break;
case 5: SearchBclass(bn); break;
case 0: return;
default: printf("\n 按键错误,请重新选择!\n");
}
}
}
//====================================================================//
// 功能:按书名进行图书查询
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:输入书名,先用strcmp函数进行精确查询,若无查询结果,再用strstr函数
// 进行模糊查询
//====================================================================//
void SearcBname (int bn)
{ int i, j, k;
char bname[40], c='y';
while(c=='y'||c=='Y')
{ k=-1;
printf("\n 请输入书名:");
gets(bname);
for(i=0,j=1; i
if(strcmp(book[i].bookname, bname)==0) //精确查询
{ k=i;
printf("\n 图书%d的信息:\n", j++);
OutputOnebook(k);
printf("\n 按任意键继续!\n"); getch();
}
if(k==-1) //k为-1表示没有精确查询的结果
{ printf("\n 模糊查询结果如下:\n");
for(i=0, j=1; i
if(strstr(book[i].bookname, bname)!=NULL) //模糊查询
{ k=i;
printf("\n 图书%d的信息:\n", j++);
OutputOnebook(k);
printf("\n 按任意键继续!\n"); getch();
}
if(j==1) printf("\n 抱歉!没有相应的图书信息!\n");
}
printf("\n 继续查询其他图书的信息吗?(y/n):");
c=getchar(); getchar();
}
printf("\n按任意键继续!\n"); getch();
}
//====================================================================//
// 功能:按作者姓名进行图书查询
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:输入作者姓名,先用strcmp函数进行精确查询,若无查询结果,再用strstr
// 函数进行模糊查询
//====================================================================//
void SearchAuthor(int bn)
{
查询方法与SearcBname函数类似,代码略。
}
//====================================================================//
// 功能:按图书分类进行图书查询
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:输入图书分类,直接用strstr函数进行模糊查询
//====================================================================//
void SearchBclass(int bn)
{
略
}
//====================================================================//
// 功能:按出版社进行图书查询
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:输入出版社名称,直接用strstr函数进行模糊查询
//====================================================================//
void SearchPublisher(int bn)
{
查询方法与SearcBclass函数类似,代码略。
}
//====================================================================//
// 功能:按出版时间进行图书查询
// 参数:bn表示图书的数量
// 返回:无
// 主要思路:用嵌套的if语句实现按出版时间查询
//====================================================================//
void SearchPubtime(int bn)
{ int i, j, k, year, month;
char c='y';
while(c=='y'||c=='Y')
{
k=-1;
month=0;
printf("\n 若只知道图书出版于2004年,则输入2004↙\n");
printf("\n 请输入时间(年.月):");
scanf("%d.%d.%d", &year, &month); getchar();
for(i=0,j=1; i
if(book[i].publish_time.year==year)
{ k=i; //年份相等时用k记录该图书的下标
if(month!=0)
if(book[i].publish_time.month!=month)
continue; //月份不相等,则结束本次循环
printf("\n 图书%d的信息:\n", j++);
OutputOnebook(k); //输出找到的图书信息
printf("\n 按任意键继续!\n");
getch();
}
if(k== -1||j==1) printf("\n 抱歉!没有相应的图书信息!\n");
printf("\n 继续查询其他图书的信息吗?(y/n):");
c=getchar(); getchar();
}
printf("\n 按任意键继续!\n");
getch();
}
//图书借阅管理模块的函数定义
//====================================================================//
// 功能:实现借书操作
// 参数:bn表示图书的数量,m表示第m个学生进行借书
// 返回:无
// 主要思路:先输入要借阅的图书书号,找到该书后进行借书操作,并保存借书操作完成
// 后的图书信息和学生信息
//====================================================================//
void BorrowBook(int bn, int m)
{
int i, j, k=-1;
struct tm d; //变量d用来获取系统时间
char isbn[20], c='y';
while(c=='y'||c=='Y')
{
for(j=0; j<5; j++)
if(student[m].card[j].flag==0)
{ printf("\n 请输入要借入图书的书号:");
gets(isbn);
for(i=0; i
if(strcmp(book[i].ISBN, isbn)==0)
{ k=i;
break;
}
if(k>=0)
{
if(book[k].stock_num>0) //该书的库存量大于0
{
book[k].stock_num--; //该书的库存量减1
student[m].card[j].flag=1; //借书卡借阅标记置1(表示已借书)
strcpy(student[m].card[j].ISBN, isbn);
_getsystime(&d); //获取系统时间
if(d.tm_year/100>=1)
student[m].card[j].bor_time.year=2000+d.tm_year%100;
else
student[m].card[j].bor_time.year=1900+d.tm_year;
student[m].card[j].bor_time.month=d.tm_mon+1;
student[m].card[j].bor_time.day=d.tm_mday;
SaveOnebook(k); //保存借书操作完成后的这本图书的信息
SaveOnestud(m); //保存借书操作完成后的学生信息
printf("\n 你已成功借阅该书!\n");
}
else // book[k].stock_num <=0,表示该书的库存量等于0
printf("\n 抱歉!该书库存量为0,无法借阅!\n");
break; //终止for(j)循环
}
else //k<0,表示在数组book中未找到该书
{ printf("\n 输入的书号有误,请重新输入!\n");
j--;
}
} //end if(student[m].card[j].flag==0)
if(j==5)
{ printf("\n 你目前没有空闲的借书卡,无法借书!\n");
break; //终止while循环
}
printf("\n 继续借书吗?(y/n):");
c=getchar(); getchar();
}//end while
printf("\n 按任意键继续!\n");
getch();
}
//====================================================================//
// 功能:实现还书操作
// 参数:bn表示图书的数量,m表示第m个学生进行还书
// 返回:无
// 主要思路:先输入要归还图书的书号,找到该书后进行还书操作,并保存还书操作完成
// 后的图书信息和学生信息
//====================================================================//
void ReturnBook(int bn, int m)
{
int i, j, k, t;
char isbn [20], c='y';
printf("\n 你借阅的图书如下:\n");
printf(" 书号 借阅时间\n");
for(j=0,t=0; j<5; j++)
if(student[m].card[j].flag)
{ t++;
printf(" %-20s",student[m].card[j].ISBN);
printf("%d.%d.%d\n", student[m].card[j].bor_time.year,
student[m].card[j].bor_time.month, student[m].card[j].bor_time.day);
}
if(t==0) printf("\n 你的借书卡均为空!\n");
else
while(c=='y'||c=='Y')
{
printf("\n 请输入要归还图书的书号:");
gets(isbn);
for(j=0; j<5; j++) //在该生的5张借书卡中寻找输入的书号
if(strcmp(student[m].card[j].ISBN, isbn)==0)
{
student[m].card[j].flag=0; //借阅标记赋0
strcpy(student[m].card[j].ISBN, ""); //借书卡上的书号清空
student[m].card[j].bor_time.year=0; //借阅时间清0
student[m].card[j].bor_time.month=0;
student[m].card[j].bor_time.day=0;
t--; //已借图书的数量减1
for(i=0; i
if(strcmp(book[i].ISBN, isbn)==0)
{ k=i; //找到该书,记录其下标
break;
}
book[k].stock_num++; //该书号对应图书的库存量加1
SaveOnebook(k); //保存还书操作完成后的这本图书的信息
SaveOnestud(m); //保存还书操作完成后的学生信息
printf("\n 你已成功归还该书!\n");
break; //终止for(j)循环
}
if(j==5) printf("\n 输入的书号有误,请重新输入!\n");
if(t==0)
{ printf("\n 你已归还了全部图书!\n");
break; //终止while循环
}
printf("\n 继续还书吗?(y/n):");
c=getchar(); getchar();
}
printf("\n 按任意键继续!\n");
getch();
}
本文来源:https://www.2haoxitong.net/k/doc/71473dbff121dd36a32d8261.html
文档为doc格式