一、创建图书类型(结构体)、用户操作(枚举)、文件保存位置(宏)
// 头指针指向头节点 -- 有头节点
// 头节点只要指针域,没有数据域
//图书类型
typedef struct book{
int id; // 图书编号
int bookNum; // 图书数量
char bookName[30]; // 书名
int hot; // 图书的热度
struct book *next;
struct book *last;
}BOOK;
//用户操作
typedef enum{
ADDBOOK=1,
DELBOOK,
FINBOOK,
RENTBOOK,
RETBOOK,
BEFBOOKINS,
AFTBOOKINS,
SAVEBOOK,
HOTRANK,
SHOWBOOK,
INVBOOK,
KINDBOOK,
EXISYS=0
}UserOperation;
//文件保存位置
#define bookSavePath "./books.txt"
#define readModel "r+t"
#define writeModel "w+t"
本图书管理系统使用链表进行操作--使用有头节点类的链表
二、声明函数
void showUI(void);// ui界面及逻辑
int getlenList(BOOK *h);//获取存放的了多少样图书
BOOK *createNode(void);// 创建图书节点
void findAll(BOOK *h); // 访问所有图书
void addNode(BOOK *h);// 添加图书节点
void delNode(BOOK *h,int id);//删除图书节点
void rentBook(BOOK *h,int id);// 修改图书节点 -- 借书
void returnBook(BOOK *h,int id);// 修改图书节点 -- 还书
void hotRanking(BOOK *h);// 图书热度排行榜
BOOK *getBookById(BOOK *h,int id);//查找图书
void insertAfterNode(BOOK *h,int id);//从某一个指定节点后面插入新节点
void insertBeforeNode(BOOK *h,int id);//从某一个指定节点前面插入新节点
void saveToTxt(BOOK *h);// 将整个链表的信息全部写入到文件里面去 覆盖掉的
BOOK *initLinkList(void);// 链表初始化
void inverNode(BOOK *h);//反转链表
三、主函数
调用各个子函数,利用switch-case结构启用UI界面
int main()
{
BOOK *h = initLinkList();
int choice;
int id; // 用户操作的id
int num; // -- 多少样图书
while(1)
{
showUI();
scanf("%d",&choice);
switch(choice)
{
case ADDBOOK:
addNode(h);
break;
case DELBOOK:
printf("请输入要删除的图书的id:");
scanf("%d",&id);
delNode(h,id);
break;
case FINBOOK:
printf("请输入要查找的书的id:");
scanf("%d",&id);
BOOK *b = getBookById(h,id);
if(b == NULL)
{
printf("没有找到该书籍\n");
}
else
{
printf("%-3d %-30s %d %-3d\n",b->id,b->bookName,b->hot,b->bookNum);
}
break;
case RENTBOOK:
// 借书
printf("请输入要借阅的书的id:");
scanf("%d",&id);
rentBook(h,id);
break;
case RETBOOK:
// 还书
printf("请输入要借阅的书的id:");
scanf("%d",&id);
returnBook(h,id);
break;
case BEFBOOKINS:
// 在书之前插入书
printf("请输入要插入的书的id:");
scanf("%d",&id);
insertBeforeNode(h,id);
break;
case AFTBOOKINS:
// 在书之后插入书
printf("请输入要插入的书的id:");
scanf("%d",&id);
insertAfterNode(h,id);
break;
case SAVEBOOK:
saveToTxt(h);
break;
case HOTRANK:
hotRanking(h);
printf("=======热度排行榜======");
findAll(h);
break;
case SHOWBOOK:
findAll(h);
break;
case INVBOOK:
inverNode(h);
findAll(h);
break;
case KINDBOOK:
num = getlenList(h);
printf("共有%d样图书\n",num);
break;
case EXISYS:
printf("欢迎再次光临系统!");
return 0;
default:
printf("欢迎再次光临系统!");
return 0;
}
}
return 0;
}
四、子函数
// 访问 - 函数
void findAll(BOOK *h)
{
while(h->next != NULL)
{
h = h->next;
printf("%-3d %-20s %d %-3d\n" ,h->id,h->bookName,h->hot,h->bookNum);
}
}
// 创建图书节点 - 函数
// 返回值类型 BOOK *
// 函数名:createNote
// 形参:void
BOOK *createNode(void)
{
BOOK *p = (BOOK *)malloc(sizeof(BOOK));// 动态分配 -- 空间由程序员自己生成自己释放 -- 堆区
printf("请输入图书编号:");
scanf("%d",&p->id);
printf("请输入图书名:");
scanf("%s",p->bookName);
printf("请输入图书热度:");
scanf("%d",&p->hot);
printf("请输入图书的库存:");
scanf("%d",&p->bookNum);
p->next = NULL;
return p;
}
// 添加图书节点
// 返回值类型 void
// 函数名:addNote
// 形参:BOOK *h
void addNode(BOOK *h)
{
while(h->next != NULL)
{
h = h->next;
}
// 创建一个新节点
h->next = createNode();
}
// 删除图书节点 - 通过 id 删除
// 返回值类型:void
// 函数名:delNote
// 形参:int id,BOOK *h;
void delNode(BOOK *h,int id)
{
BOOK *p = h;
while(h->next != NULL)
{
p = h;
h = h->next;
if(id == h->id){
p->next = h->next;
free(h);
h = NULL;
break;
}
}
}
// 修改图书节点 -- 借书
// 返回值类型:void
// 函数名: rentBook
// 形参:BOOK *h,int id
void rentBook(BOOK *h,int id)
{
while(h->next != NULL)
{
h = h->next;
if(h->id == id)
{
if(h->bookNum <= 0){
printf("图书库存为0,请换其他图书借取,谢谢!\n");
break;
}else{
h->bookNum = h->bookNum -1;
break;
}
}
}
}
// 修改图书节点 -- 还书
// 返回值类型:void
// 函数名: rentBook
// 形参:BOOK *h,int id
void returnBook(BOOK *h,int id)
{
while(h->next != NULL)
{
h = h->next;
if(h->id == id)
{
h->bookNum = h->bookNum +1;
break;
}
}
}
// 图书热度排行榜 - 1、将热度排序 or 2、节点排序
// 返回值类型:void
// 函数名:hotRanking
// 形参:BOOK *h
void hotRanking(BOOK *h)
{
// 如果链条为空
if(h == NULL || h->next == NULL)
{
return ; // 结束函数
}
int len = getlenList(h);
BOOK *head;
BOOK *p;
BOOK *q;
int i=0;
int j=0;
for(i=len;i>0;i--)
{
head = h;
p = h;
q = h->next;
for(j=0;j<i-1;j++)
{
// 移动指针位置 - 将节点连线
head = p;
p = q;
q = q->next;
// p->hot q->hot
if(p->hot < q->hot){
p->next = q->next;
q->next = p;
head->next = q;
// 调整prev和p的位置
BOOK *temp = p;
p = q;
q = temp;
}
}
}
}
//void hotRanking(BOOK *h)
//{
// int len = setlenlish(h);
// BOOK *q;
// q = h;
// int hotArr[k];
// int idArr[k];
// int i=0;
// while(h->next != NULL)
// {
// h = h->next;
// hotArr[i] = h->hot;
// idArr[i] = h->id;
// i++;
// }
// int *p =hotArr;
// int j;
// for(i=k;i>0;i--)
// {
// for(j=0;j<i-1;j++)
// {
// if(*(p+j) < *(p+j+1)){
// int temp = *(p+j);
// *(p+j) = *(p+j+1);
// *(p+j+1) = temp;
// temp = idArr[j];
// idArr[j] = idArr[j+1];
// idArr[j+1] = temp;
// }
// }
// }
// for(i=0;i<k;i++)
// {
// h = q;
// while(h->next != NULL)
// {
// h = h->next;
// if(hotArr[i] == h->hot && idArr[i] == h->id){
// printf("%s 热度为%d\n",h->bookName,hotArr[i]);
// break;
// }
//
// }
// }
//}
//获取存放了多少样图书
int getlenList(BOOK *h)
{
int count=0;
while(h->next != NULL)
{
h = h->next;
count++;
}
return count;
}
// 查找图书 -- id
// 返回值类型:BOOK *
// 函数名:getBookById
// 形参:BOOK *h,int id
BOOK *getBookById(BOOK *h,int id)
{
if(h == NULL || h->next == NULL)
{
return NULL;
}
while(1)
{
if(id == h->id)
{
return h;
}
}
}
// 往某个节点后面插入新节点
// 返回值类型:void
// 函数名:insertAfterNode
// 形参:BOOK *h int id
void insertAfterNode(BOOK *h,int id)
{
if(h == NULL || h->next == NULL)
{
return ;
}
while(h->next != NULL)
{
h=h->next;
if(id == h->id)
{
BOOK *newNode = createNode();
newNode->next = h->next;
h->next = newNode;
break;
}
}
}
// 往某个节点前面插入新节点
// 返回值类型:void
// 函数名:insertAfterNode
// 形参:BOOK *h int id
void insertBeforeNode(BOOK *h,int id)
{
if(h == NULL || h->next == NULL)
{
return ;
}
BOOK *p = h;
BOOK *prev =h;
while(p != NULL)
{
prev = p;
p = p->next;
if(id == p->id)
{
BOOK *newNode = createNode();
prev->next = newNode;
newNode->next = p;
break;
}
}
}
// 将整个链表的信息全部写入到文件里面去 覆盖掉的
// 返回值类型:void
// 函数名:saveToTxt
// 形参:BOOK *h
void saveToTxt(BOOK *h)
{
FILE *fp = fopen(bookSavePath,writeModel);
if(fp == NULL){
printf("文件打开失败!");
return ;
}
while(h->next != NULL)
{
h = h->next;
fprintf(fp,"%3d %20s %d %3d\n",h->id,h->bookName,h->hot,h->bookNum);
}
}
// 链表的初始化
// 返回值类型:BOOK *
// initLinkList
// 形参:void
BOOK *initLinkList(void)
{
char ch;
//生成头结点
BOOK *h = (BOOK *)malloc(sizeof(BOOK));
h->next = NULL;
BOOK *p = h;
//文件里面读取信息挂在到头节点的后面
FILE *fp = fopen(bookSavePath,readModel);
if(fp == NULL){
return NULL;
}
ch = fgetc(fp);
// 到文件的结尾
// 检测文件是否为空
if(ch == EOF)
{
fclose(fp);
return h;
}
rewind(fp);
while(feof(fp) == 0)
{
BOOK *newNode = (BOOK *)malloc(sizeof(BOOK));
newNode->next = NULL;
fscanf(fp,"%3d %20s %d %3d\n",&newNode->id,newNode->bookName,&newNode->hot,&newNode->bookNum);
p->next = newNode;
p = newNode;
}
fclose(fp);
return h;
}
//UI界面设计
void showUI(void)
{
printf("================欢迎来到图书管理系统=================\n");
printf("================[1]添加 [2]删除图书==============\n");
printf("================[3]检索 [4]借书==================\n");
printf("================[5]还书 [6]前插入================\n");
printf("================[7]后插入 [8]保存==================\n");
printf("================[9]热度排行榜 [10]查看所有图书=======\n");
printf("==============[11]反转图书列表[12]获取图书数量=======\n");
printf("请选择:");
}
//反转整个图书的排序
void inverNode(BOOK *h)
{
if( h == NULL || h->next == NULL || h->next->next == NULL)
{
return ;
}
BOOK *q = h;
BOOK *p = h->next;
BOOK *prev = h->next->next;
// h->next->next = NULL;
// h->next = p;
while(1)
{
// 改变方向
p->next = q;
if(prev == NULL){
h->next->next = NULL;
h->next = p;
break;
}
// 三个指针移动
q = p;
p = prev;
prev = prev->next;
}
}