#include<stdio.h>
#include<stdlib.h> //提供malloc函数开辟链表空间
#include<string.h>
#include<time.h> //获得当地时间,作为图书存入时间
#define SIZE 40 //图书名称的大小
struct Book* head =NULL;//链表的首地址!!
/*首地址一定要给他初始化为NULL!!不然会乱指!!*/
struct Book* prev,*current;//记录前一个结构地址和后一个结构地址
struct Time{
int year;
int month;
int day;
int hour;
int min;
};
//入库时间的结构,用来存储当地时间
struct Book{
char bkname[SIZE];//书名
char writer[SIZE];//作者名
int number;//图书编号
float price;//图书价格
struct Time btime;//存入时间
struct Book* next;//访问链表下一个结构
};
//图书信息的结构
int num =0;//用来记录图书的数量
int BookNumber =15300;
int main()
{
void Meau();
int Input();//使用链表输入图书信息并返回choice的值做接下来的操作
int Output();//输出图书列表
int Search_book();//按图书查询
int Search_writer();//按作者查询
int Sort_price();//价格排序
int Delete_book();//按入库时间查询
int choice;
system("clear");
Meau();
printf("您的操作是:");
scanf("%d",&choice);
while(getchar()!='\n')
continue;
while(choice !='\0'){
if(choice <0 || choice >6){
printf("\n请输入正确的操作!(0-6)\n");
scanf("%d",&choice);//记住要重新给choice赋值,不然输入错误后会无限循环
while(getchar()!='\n')continue;
}
else
switch(choice){
case 0: choice ='\0';break;
case 1: choice =Input();break;
case 2: choice =Output();break;
case 3: choice =Search_book();break;
case 4: choice =Search_writer();break;
case 5: choice =Sort_price ();break;
case 6: choice =Delete_book();break;
default:;
}
}
system("clear");
printf("\n欢迎下次使用!");
current =head;
while(current !=NULL){
free(current);
current =current->next;
}
return 0;
}
void Meau()
{
printf("***********************************************************\n");
printf("* *欢迎进入图书管理系统* *\n");
printf("* ********************** *\n");
printf("* *\n");
printf("* 1):录入图书 2):图书列表 *\n");
printf("* 3):查询图书 4):查询作者 *\n");
printf("* 5):按价格排序 6):删除图书 *\n");
printf("* 0):退出 *\n");
printf("* *\n");
printf("* *\n");
printf("***********************************************************\n");
}
int Input()
{ /**********************/
/*获得系统中的当地时间*/
/**********************/
time_t timep;//生命一个time_t结构的变量timep
struct tm *p;//声明一个存储当地时间地址的指针变量
time(&timep);//获得时间
p =localtime(&timep);//获得p结构的时间(tm结构:int tm_year,int tm_mon...
char input[SIZE];//用来判断输入的书名是否为空,空的话就停止输入
int fchoice;//返回给主函数一个操作
system("clear");
puts("请输入第一本书的信息:");
/**********************/
/*使用链表输入图书信息*/
/**********************/
printf("书 名: ");
while (fgets (input,SIZE,stdin)!=NULL && input[0] !='\n'){
for(int i=0;input[i++]!='\0';)
if(input[i]=='\n')
input[i]='\0';
current = (struct Book* )malloc(sizeof(struct Book));
if(NULL == current){
puts("内存分配错误!");
exit(EXIT_FAILURE);
}
/*判断是否为链表头*/
if(NULL ==head)
head = current;
else
/*将此时的链表地址放到上一个链表的节点处*/
prev->next = current;
/*将最后结构中的next指向空的内存*/
current->next = NULL;
strcpy(current->bkname,input);
current->number =BookNumber ++;//编号为输入顺序
printf("作 者: ");
fgets(current->writer,SIZE,stdin);
for(int i =0;current->writer[i++] !='\0';)
if( '\n'== current->writer[i]) current->writer[i] ='\0';
printf("价 格: ");
scanf("%f",¤t->price);
while(getchar()!='\n')
continue;
printf("编 号: %d\n",current->number);
/****************************************/
/*将tm的时间结构中的值赋值给图书入库时间*/
/****************************************/
current->btime.year =1899+p->tm_year;
current->btime.month =1 +p->tm_mon;
current->btime.day =p->tm_mday;
current->btime.hour =p->tm_hour;
current->btime.min =p->tm_min;
printf("入库时间: %d年%d月%d日 %d时%d分\n",current->btime.year,current->btime.month,current->btime.day,current->btime.hour,current->btime.min);
puts("请输入下一本书的信息:");
printf("书 名: ");
prev =current;
num++;
}
system("clear");//清屏
puts("录入图书完毕");
Meau();
printf("您接下来的操作是:");
scanf("%d",&fchoice);
while(getchar()!='\n')continue;
fflush(stdin);
system("clear");
return fchoice;//返回一个操作
}
//输出图书列表,传入链表的首地址head
int Output()
{
int fchoice;
if(NULL ==head){
system("clear");
printf("暂时没有图书入库\n");
}
else
printf("以下是入库图书列表,入库图书共计%d本\n\n",num);
current = head;
while(current !=NULL){
printf("编 号: %d\n",current->number);
printf("书 名: %s\n",current->bkname);
printf("作 者: %s\n",current->writer);
printf("价 格: $%.2f\n",current->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",current->btime.year,current->btime.month,current->btime.day,current->btime.hour,current->btime.min);
printf("***********************************************************\n");
current =current->next;
}
Meau();
printf("您接下来要进行的操作是:");
scanf("%d",&fchoice);
while(getchar()!='\n')continue;
system("clear");
Meau();
return fchoice;//返回一个操作
}
int Search_writer()//按作者查询
{
int fchoice;
char bwriter[SIZE];//要查询的作者
char y_n;//判断是否继续查询
while (1){
system("clear");
printf("\n请输入您要查找的作者姓名:");
//去除因为使用fgets存入数组中的\n
fgets(bwriter,SIZE,stdin);
for(int i =0;bwriter[i++] !='\0';)
if( '\n'== bwriter[i]) bwriter[i] ='\0';
current =head;
if(current ==NULL)printf("书库中暂时没有存书\n");
while(current != NULL){
int right =1;//用来判断是否有该作者信息,1为有,0为无
int i =0;
/*模糊查询作者姓名,输入头几个字母就能查询到符合信息的作者*/
while(bwriter[i] !='\0'){//只检查输入者输入的前几个字母在书库中是否有匹配的作者姓名
if(bwriter[i] == current->writer[i])
right =1;
else {
right =0;break;//**********************************
} //right为0则没有这作者信息,1则输出*
i++; //**********************************
}
if(right ==1){
printf("编 号: %d\n",current->number);
printf("书 名: %s\n",current->bkname);
printf("作 者: %s\n",current->writer);
printf("价 格: $%.2f\n",current->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",current->btime.year,current->btime.month,current->btime.day,current->btime.hour,current->btime.min);
printf("***********************************************************\n");
break; //没有break则会继续执行下面的语句
}
if(NULL ==current->next && 0== right) //right为0时则没有此作者
printf("书库中暂时没有该作者信息\n");
current =current->next;
}
/*判断客户是否需要重新查询,y为继续循环,n为跳出循环*/
printf("是否继续查询(y or n)? ");
while(scanf("%c",&y_n)!=1 || (y_n !='y' && y_n !='n')){ //在输入非字符数据或y_n不为y或n时提示错误操作
while(getchar()!='\n')continue;
printf("请输入正确的操作!(y or n) ");
}
if('n' == y_n)break;
while(getchar()!='\n')continue; //这句一定不能省略,不然当第二次循环时残存的回车键会被读入fgets里
}
system("clear");
Meau();//菜单
/*返回一个操作*/
printf("您的操作是:");
scanf("%d",&fchoice);
while(getchar()!='\n')continue;
return fchoice;
}
/************/
/*按图书查询*/
/************/
int Search_book()
{
int fchoice;
char sbook[SIZE];//要查询的图书
char y_n;//判断是否继续查询
while (1){
system("clear");
printf("\n请输入您要查找的图书:");
/*去除数组里的换行符*/
fgets(sbook,SIZE,stdin);
for(int i =0;sbook[i++] !='\0';)
if( '\n'== sbook[i]) sbook[i] ='\0';
current =head;
if(current ==NULL)printf("书库中暂时没有存书\n");
/************************/
/*遍历书库查询符合的信息*/
/************************/
while(current != NULL){
int right =1;//用来判断是否有该图书信息,1为有,0为无
int i =0;
/*模糊查询图书,输入头几个字母就能查询到符合信息的所有图书*/
while(sbook[i] !='\0'){//只检查输入者输入的前几个字母在书库中是否有匹配的图书
if(sbook[i] == current->bkname[i])
right =1;
else {
right =0;break;
}
i++;
}
if(right ==1){
printf("编 号: %d\n",current->number);
printf("书 名: %s\n",current->bkname);
printf("作 者: %s\n",current->writer);
printf("价 格: $%.2f\n",current->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",current->btime.year,current->btime.month,current->btime.day,current->btime.hour,current->btime.min);
printf("***********************************************************\n");
break; //没有break则会继续执行下面的语句
}
if(NULL ==current->next && 0== right)//right为0时则没有此作者
printf("书库中暂时没有该图书\n");
current =current->next;
}
/****************************************************/
/*判断客户是否需要重新查询,y为继续循环,n为跳出循环*/
/****************************************************/
printf("是否继续查询(y or n)? ");
while(scanf("%c",&y_n)!=1 || (y_n !='y' && y_n !='n')){ //在输入非字符数据或y_n不为y或n时提示错误操作
while(getchar()!='\n')continue;
printf("请输入正确的操作!(y or n) ");
}
if('n' == y_n)break;
while(getchar()!='\n')continue;//这句一定不能省略,不然当第二次循环时残存的回车键会被读入fgets里然后开头为换行符则结束循环
}
system("clear");
Meau();//菜单
/*返回一个操作*/
printf("您的操作是:");
scanf("%d",&fchoice);
return fchoice;
}
/******************/
/*按照价格进行排序*/
/******************/
int Sort_price()
{
system("clear");
int fchoice;
int k;//选择排序法用
struct Book s_price[num];//num的初始值为0,通过过链表的创建操作已被赋予新值
/*将链表中的数据赋值给变长数组s_price结构数组中*/
int i=0;
current =head;
while(current !=NULL){
s_price[i] =*current;
i++;
current =current->next;
}
/*按照结构数组中的价格排序*/
for(int i=0;i <num- 1;i ++){
k =i;
for(int j=i +1;j <num;j ++)
if(s_price[k].price > s_price[j].price)k =j;
if(k !=i){
struct Book t;
t =s_price[i];
s_price[i] =s_price[k];
s_price[k] =t;
}
}
/*输出排序后的结果*/
for(int i=0;i<num;i++){
printf("编 号: %d\n",s_price[i].number);
printf("书 名: %s\n",s_price[i].bkname);
printf("作 者: %s\n",s_price[i].writer);
printf("价 格: $%.2f\n",s_price[i].price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",s_price[i].btime.year,s_price[i].btime.month,s_price[i].btime.day,s_price[i].btime.hour,s_price[i].btime.min);
printf("***********************************************************\n");
}
Meau();//菜单
/*返回一个操作*/
printf("您的操作是:");
scanf("%d",&fchoice);
while(getchar()!='\n')continue;
return fchoice;
}
/**********/
/*删除图书*/
/**********/
int Delete_book()
{
int fchoice;
int delete_num;//要删除的图书的编号
struct Book* previ;//记录上一个链表的地址
struct Book* dele;//记录要删除的图书的地址
char y_n;
while(1){
printf("以下是入库图书列表,入库图书共计%d本\n\n",num);
current = head;
while(current !=NULL){
printf("编 号: %d\n",current->number);
printf("书 名: %s\n",current->bkname);
printf("作 者: %s\n",current->writer);
printf("价 格: $%.2f\n",current->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",current->btime.year,current->btime.month,current->btime.day,current->btime.hour,current->btime.min);
printf("***********************************************************\n");
current =current->next;
}
printf("请输入您要删除的图书的编号,返回主页请按q:");
if(scanf("%d",&delete_num)){
while(getchar()!='\n')continue;
if(delete_num < 15300 ){
system("clear");
printf("书库中没有该编号存书,请重新输入\n");
continue;
}
} else {
getchar(); //吸收非数字以及回车符,不然返回主页时会将q和回车输入到fchoice中
system("clear");
Meau(); //菜单
/*返回一个操作*/
printf("您的操作是:");
scanf("%d",&fchoice);
while(getchar()!='\n')continue;
return fchoice;
}
/*删除链表有以下几种情况:
* 1.只有一本书即num=1时
* 2.删除第一本书即删除head表头时
* 3.删除表尾
* 4.删除中间的链表
* 要注意的是保证上一个链表能够连接到下下一个链表*/
previ =head;
/*书库中只有一本书的情况下删除图书*/
if(delete_num ==previ->number && 1==num && NULL ==previ->next){
printf("您要删除的图书为:\n");
printf("编 号: %d\n",previ->number);
printf("书 名: %s\n",previ->bkname);
printf("作 者: %s\n",previ->writer);
printf("价 格: $%.2f\n",previ->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",previ->btime.year,previ->btime.month,previ->btime.day,previ->btime.hour,previ->btime.min);
printf("是否继续操作(y or n)");
scanf("%c",&y_n);
while(getchar()!='\n')continue;
if('y' ==y_n){
free(previ);
previ =NULL;
head = NULL; //只有一本书且被删除时记得把表头指向空指针,避免再次输出列表导致野指针的出现(还会列出删除前的书目
system("clear");
printf("图书已删除,书库已无存书\n");
num-=1;
Meau();//菜单
/*返回一个操作*/
printf("您的操作是:");
scanf("%d",&fchoice);
while(getchar()!='\n')continue;
return fchoice;
} else if('n'==y_n){
system("clear");
printf("已取消操作\n");
continue;
} else {
system("clear");
printf("输入错误,返回删除页面");
continue;
}
}
//用来判断书库中有无该编号图书,有为1,无为0
int Pd =0;
do {
if(delete_num ==previ->number || delete_num ==previ->next->number){ //使用"||"避免影响删除最后一个链表时的判断
Pd =1; break;
}
previ =previ->next;
} while(previ->next !=NULL);
if(0==Pd){
system("clear");
printf("书库中无此存书\n");
continue;
}
// 删除第一本书即删除head表头时
if(previ ==head && NULL !=previ->next && delete_num == previ->number){
printf("您要删除的图书为:\n");
printf("编 号: %d\n",previ->number);
printf("书 名: %s\n",previ->bkname);
printf("作 者: %s\n",previ->writer);
printf("价 格: $%.2f\n",previ->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",previ->btime.year,previ->btime.month,previ->btime.day,previ->btime.hour,previ->btime.min);
printf("是否继续操作(y or n)");
scanf("%c",&y_n);
while(getchar()!='\n')continue;
if('y' ==y_n){
previ =previ->next;
free(head); //释放原表头内存
head =previ; //给第二个链表内容赋值给表头,成为新表头
system("clear");
printf("图书已删除,");
num-=1;
} else if('n'==y_n){
system("clear");
printf("已取消操作\n");
continue;
} else {
system("clear");
printf("输入错误,返回删除页面");
continue;
}
}
else{
previ =head;
while(previ->next !=NULL){
/*删除表尾*/
if(delete_num ==previ->next->number && NULL ==previ->next->next){
printf("您要删除的图书为:\n");
printf("编 号: %d\n",previ->next->number);
printf("书 名: %s\n",previ->next->bkname);
printf("作 者: %s\n",previ->next->writer);
printf("价 格: $%.2f\n",previ->next->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",previ->next->btime.year,previ->next->btime.month,previ->next->btime.day,previ->next->btime.hour,previ->next->btime.min);
printf("是否继续操作(y or n)");
scanf("%c",&y_n);
while(getchar()!='\n')continue;
if('y' ==y_n){
free(previ->next);
previ->next =NULL;
system("clear");
printf("图书已删除\n");
num-=1;
break;
} else if('n'==y_n){
system("clear");
printf("已取消操作\n");
break;
} else {
system("clear");
printf("输入错误,返回删除页面\n");
break;
}
}
/*删除链表中间的内容*/
if(delete_num ==previ->next->number){
printf("您要删除的图书为:\n");
printf("编 号: %d\n",previ->next->number);
printf("书 名: %s\n",previ->next->bkname);
printf("作 者: %s\n",previ->next->writer);
printf("价 格: $%.2f\n",previ->next->price);
printf("入库时间: %d年%d月%d日 %d时%d分\n",previ->next->btime.year,previ->next->btime.month,previ->next->btime.day,previ->next->btime.hour,previ->next->btime.min);
printf("是否继续操作(y or n)");
scanf("%c",&y_n);
while(getchar()!='\n')continue;
if('y' ==y_n){
dele =previ->next;
previ->next =previ->next->next; //删除该链表后使前后链表相连
free(dele); //释放删除的链表空间(dele记录了删除的链表地址)
system("clear");
printf("图书已删除\n");
num-=1;
break;
}else if('n'==y_n){
system("clear");
printf("已取消操作\n");
break;
}else{
system("clear");
printf("输入错误,返回删除页面\n");
break;
}
}
previ =previ->next;
}
}
}
system("clear");
Meau();//菜单
/*返回一个操作*/
printf("您的操作是:");
scanf("%d",&fchoice);
return fchoice;
}
图书管理系统
最新推荐文章于 2023-07-25 09:08:21 发布