C语言实战项目--图书管理系统(附带全套源代码)
●VON 2024-07-29 14:35:01 阅读 86
一、项目简介
该项目适用于大一大二实训作业,所用到的知识全都是课堂中老师要求掌握的,该项目有运行截图可以直接进行应用。实现了对图书的增、删、改、查的操作。图书的信息包括名称、单价、数量。运用链表来保存图书信息,再对链表进行读取,保存至文件当中。
注:使用前要先在该项目下创建“booksave.txt”文本文件,如果不想应用文件操作可以删除对应函数及函数的调用操作。
二、项目应用技术
1、动态内存分配与释放
使用 <code>malloc 分配内存来存储 BOOKINFO
结构体类型的数据。
在退出系统时通过 delinit
函数释放链表节点占用的内存。
2、结构体和指针
BOOKINFO
结构体用于存储图书的名称、价格和数量。
BOOKINFO*
类型的指针 p_info
用于动态创建新的图书信息。
3、链表操作
booklink* lnk
是一个指向图书链表头的指针,用于操作和管理图书的插入、删除、查找等操作。
函数 bookinsert
、bookdelete
、booksearch
用于在链表中插入、删除和查找图书信息。
4、文件操作
savebook
函数可能用于将当前图书链表的信息保存到文件中,以便在程序重新运行时可以恢复数据。
5、用户交互
使用 scanf
函数接收用户输入的操作选择和相关参数。
通过 switch
语句根据用户输入执行相应的操作:登记新书、浏览书籍、借阅书籍、归还书籍、查找书籍、删除书籍、退出系统等。
6、错误处理
在内存分配失败时输出错误信息。
在未找到相关书籍或操作非法时,输出相应的提示信息。
7、功能实现细节
在插入图书时,允许用户指定插入位置,并保存修改后的链表状态。
借阅和归还书籍时,根据库存数量进行相应的操作,并保存更新后的信息。
三、项目运行展示
1、booksave.txt
2、books.cpp
四、项目构建思路及其代码展示
1.结构体和头文件的使用
预处理指令 (<code>#define _CRT_SECURE_NO_WARNINGS)
这是针对使用 Visual Studio 编译器的预处理指令,用于忽略某些与标准C库函数相关的警告。
头文件包含
#include<stdio.h>
:标准输入输出库,包含了输入输出函数的声明。
#include<stdlib.h>
:标准库,包含了内存分配、类型转换、数学函数等。
#include<string.h>
:标准字符串处理库,包含了字符串操作函数的声明。
#include<stdbool.h>
:标准布尔类型库,包含了bool
类型和true/false
宏定义。
结构体定义 (
typedef struct ...
)
typedef struct bookinfo
:定义了名为bookinfo
的结构体,用于存储图书的信息。
char name[20]
:存储图书名称的字符数组,最大长度为 19 个字符(加上结尾的空字符\0
)。
float price
:存储图书价格的浮点数。
int num
:存储图书数量的整数。
struct bookinfo* next
:指向下一个bookinfo
结构体的指针,用于构建链表。
typedef struct link
:定义了名为link
的结构体,用于表示一个链表。
BOOKINFO head
:链表的头部,存储一个BOOKINFO
结构体,可能作为链表的起始点。
BOOKINFO tail
:链表的尾部,存储一个BOOKINFO
结构体,可能作为链表的结束点。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
//定义图书信息
typedef struct bookinfo
{
char name[20];
float price;
int num;
struct bookinfo* next;
}BOOKINFO;
//链表
typedef struct link
{
BOOKINFO head;//头部
BOOKINFO tail;//尾部
}booklink;
2.初始化链表
指针操作
p_link
是一个指向booklink
结构的指针,用来操作传入的链表结构。
结构体成员访问
p_link->head
和p_link->tail
分别访问了booklink
结构体中的head
和tail
成员。
链表初始化
p_link->head.next = &(p_link->tail);
将
head
结构体中的next
成员指向tail
结构体的地址。这表示链表的头部的下一个节点是尾部,这是一个常见的初始化操作,使得链表在初始状态下只有头部一个节点。
p_link->tail.next = NULL;
将
tail
结构体中的next
成员设置为NULL
,表示链表的尾部节点没有下一个节点,即链表结束。
//初始化
void linkinit(booklink* p_link)
{
p_link->head.next = &(p_link->tail);
p_link->tail.next = NULL;
}
3.释放结点空间
指针操作
BOOKINFO* p_first = &(p_link->head);
将
p_first
指针指向链表头部节点。
BOOKINFO* p_mid = p_first->next;
p_mid
指向头部节点的下一个节点,即链表中的第一个实际节点。
BOOKINFO* p_last = p_mid->next;
p_last
指向p_mid
节点的下一个节点,即要删除的节点的下一个节点。
节点释放
p_first->next = p_last;
将头部节点的
next
指针指向要删除节点的下一个节点,从而维持链表的连续性。
free(p_mid);
释放
p_mid
指向的节点的内存空间,即删除链表中的一个节点。
//释放结点空间
void delinit(booklink* p_link)
{
while (p_link->head.next != &(p_link->tail))
{
BOOKINFO* p_first = &(p_link->head);
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
p_first->next = p_last;
free(p_mid);
p_mid = NULL;
}
}
4.统计图书数量
指针操作
const BOOKINFO* p_first = p_node;
将
p_first
指针指向当前循环节点p_node
,表示当前节点。
const BOOKINFO* p_mid = p_first->next;
p_mid
指向p_first
节点的下一个节点,即链表中的第一个实际节点。
const BOOKINFO* p_last = p_mid->next;
p_last
指向p_mid
节点的下一个节点,用于检查是否到达链表的尾部。
条件判断
if (p_mid != &(p_link->tail)) cut++;
检查
p_mid
是否指向链表尾部节点。如果不是尾部节点,即p_mid
是一个有效的书籍节点,那么增加cut
计数器的值。
计数器
int cut = 0;
cut
用来记录链表中实际书籍节点的数量,每次遇到一个有效节点时增加。
//统计图书数量
int booksize(const booklink*p_link)
{
int cut = 0;
for (const BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next)
{
const BOOKINFO* p_first = p_node;
const BOOKINFO* p_mid = p_first->next;
const BOOKINFO* p_last = p_mid->next;
if (p_mid != &(p_link->tail))cut++;
}
return cut;
}
5.插入图书信息
BOOKINFO* p_first = p_node;
将
p_first
指针指向当前循环节点p_node
,表示当前节点。
BOOKINFO* p_mid = p_first->next;
p_mid
指向p_first
节点的下一个节点,即链表中的第一个实际节点。
BOOKINFO* p_last = p_mid->next;
p_last
指向p_mid
节点的下一个节点,用于插入新节点时的连接操作。
if (location == i)
检查当前迭代到的位置
i
是否与要插入的位置location
相等。
p_info->next = p_mid;
将要插入的书籍节点
p_info
的next
指针指向当前位置的节点p_mid
,使其成为链表中的下一个节点。
p_first->next = p_info;
将当前节点
p_first
的next
指针指向要插入的书籍节点p_info
,完成插入操作。
*size += 1;
更新书籍链表的大小,即增加
size
指向的整数值,表示链表中书籍数量增加了一个。
void bookinsert(booklink* p_link, BOOKINFO* p_info, int location, int* size)
{
int i = 0;
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
{
BOOKINFO* p_first = p_node;
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
if (location == i)
{
p_info->next = p_mid;
p_first->next = p_info;
*size += 1;
break;
}
}
}
6.打印图书信息
const BOOKINFO* p_first = p_node;
将
p_first
指针指向当前循环节点p_node
,表示当前节点。
const BOOKINFO* p_mid = p_first->next;
p_mid
指向p_first
节点的下一个节点,即链表中的第一个实际节点。
const BOOKINFO* p_last = p_mid->next;
p_last
指向p_mid
节点的下一个节点,用于判断是否到达链表尾部。
打印图书信息
if (p_mid != &(p_link->tail))
检查
p_mid
是否指向链表尾部节点,确保不打印尾部哨兵节点的信息。
printf("第%d本图书的信息为:\n", i + 1);
打印当前图书在链表中的位置。
printf("名字:%s,价格:%.2f,数量:%d\n", p_mid->name, p_mid->price, p_mid->num);
输出当前图书节点中存储的名称、价格和数量信息。
void bookprint(const booklink* p_link, int* size)
{
int i = 0;
if (*size == 0)
{
printf("当前没有图书信息,请先插入图书信息\n");
return;
}
for (const BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
{
const BOOKINFO* p_first = p_node;
const BOOKINFO* p_mid = p_first->next;
const BOOKINFO* p_last = p_mid->next;
if (p_mid != &(p_link->tail))
{
printf("第%d本图书的信息为:\n", i + 1);
printf("名字:%s,价格:%.2f,数量:%d\n", p_mid->name, p_mid->price, p_mid->num);
}
}
}
7.查询图书信息
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next)
使用
for
循环遍历链表,从链表的头部节点开始 (&(p_link->head)
),直到遇到尾部节点 (&(p_link->tail)
)。p_node
每次迭代指向当前节点的下一个节点 (p_node->next
)。
BOOKINFO* p_first = p_node;
将
p_first
指针指向当前循环节点p_node
,表示当前节点。
BOOKINFO* p_mid = p_first->next;
p_mid
指向p_first
节点的下一个节点,即链表中的第一个实际节点。
BOOKINFO* p_last = p_mid->next;
p_last
指向p_mid
节点的下一个节点,用于判断是否到达链表尾部。
字符串比较
if (strcmp(bookName, p_mid->name) == 0) return p_mid;
使用
strcmp
函数比较参数bookName
和当前节点p_mid
的书名 (p_mid->name
)。如果两者相等,表示找到了目标图书节点,直接返回该节点的指针p_mid
。
BOOKINFO* booksearch(booklink* p_link, char* bookName)
{
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next)
{
BOOKINFO* p_first = p_node;
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
if (strcmp(bookName, p_mid->name) == 0) return p_mid;
}
return NULL;
}
8.删除图书信息
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
使用
for
循环遍历链表,从链表的头部节点开始 (&(p_link->head)
),直到遇到尾部节点 (&(p_link->tail)
)。p_node
每次迭代指向当前节点的下一个节点 (p_node->next
),同时通过i
计数器记录当前节点的位置。
BOOKINFO* p_first = p_node;
将
p_first
指针指向当前循环节点p_node
,表示当前节点。
BOOKINFO* p_mid = p_first->next;
p_mid
指向p_first
节点的下一个节点,即链表中的第一个实际节点。
BOOKINFO* p_last = p_mid->next;
p_last
指向p_mid
节点的下一个节点,用于删除操作时的重新连接。
删除操作
if (location == i)
判断当前节点的位置是否与目标删除位置
location
相同。
p_first->next = p_last;
将当前节点
p_first
的下一个节点指针next
更新为p_last
,跳过了中间节点p_mid
,实现删除操作。
free(p_mid);
释放被删除的中间节点
p_mid
的内存空间,防止内存泄漏。
*size -= 1;
更新链表大小变量
size
,减少一个节点的大小计数。
void bookdelete(booklink* p_link, int location, int* size)
{
int i = 0;
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
{
BOOKINFO* p_first = p_node;
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
if (location == i)
{
p_first->next = p_last;
free(p_mid);
*size -= 1;
break;
}
}
}
9.保存文件
文件操作
FILE* fp = fopen("booksave.txt", "w");
使用
fopen
函数以写入模式 ("w"
) 打开名为 "booksave.txt" 的文件。如果文件打开失败 (fp == NULL
),则输出错误信息并返回,表示无法继续操作。
BOOKINFO* p_tem = p_link->head.next;
初始化
p_tem
指针,指向链表的第一个实际节点,即头节点的下一个节点。
循环写入文件
while (p_tem != &p_link->tail)
使用
while
循环遍历链表,条件是p_tem
不等于尾部节点 (&p_link->tail
)。这种尾部节点的设计常见于链表的哨兵节点或者尾节点。
文件写入
fprintf(fp, "%s %f %d\n", p_tem->name, p_tem->price, p_tem->num);
使用
fprintf
函数将每个节点的图书信息按指定格式写入文件中,包括图书名称 (name
)、价格 (price
) 和数量 (num
)。
关闭文件
fclose(fp);
使用
fclose
函数关闭文件流,确保写入操作完成并释放文件资源。
//保存文件
void savebook(booklink* p_link)
{
FILE* fp = fopen("booksave.txt", "w");
if (fp == NULL)
{
printf("无法打开文件!\n");
return;
}
BOOKINFO* p_tem = p_link->head.next;
while (p_tem != &p_link->tail)
{
fprintf(fp, "%s %f %d\n", p_tem->name, p_tem->price, p_tem->num);
p_tem = p_tem->next;
}
printf("保存图书信息成功!\n");
fclose(fp);
}
10.读取文件
文件操作
FILE* fp = fopen("booksave.txt", "r");
使用
fopen
函数以只读模式 ("r"
) 打开名为 "booksave.txt" 的文件。如果文件打开失败 (fp == NULL
),则输出错误信息并返回,表示无法继续操作。
内存动态分配
BOOKINFO* p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
使用
malloc
函数动态分配内存来存储每个图书信息。这里假设BOOKINFO
是一个结构体或者类型,用于存储图书的名称 (name
)、价格 (price
) 和数量 (num
)。
循环读取文件
while (fscanf(fp, "%s%f%d", p_info->name, &p_info->price, &p_info->num) != EOF)
使用
while
循环结合fscanf
函数从文件中逐行读取图书信息,直到文件结尾 (EOF
)。每次成功读取一行数据后,将其打印出来以确认读取的正确性,并调用bookinsert
函数将读取到的图书信息插入到链表中。
链表操作
bookinsert(p_link, p_info, location, size);
假设
bookinsert
是一个函数,用于将p_info
指向的图书信息节点插入到链表p_link
的指定位置 (location
),并更新链表的大小 (size
)。
内存释放
free(p_info);
在循环结束后,释放最后一次
malloc
分配的内存,避免内存泄漏。
关闭文件
fclose(fp);
使用
fclose
函数关闭文件流,确保读取操作完成并释放文件资源。
//读取文件
void readbook(booklink* p_link,int *size)
{
FILE* fp = fopen("booksave.txt", "r");
if (fp == NULL)
{
printf("无法打开文件!\n");
return;
}
BOOKINFO* p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
int location = 0;
while (fscanf(fp, "%s%f%d", p_info->name, &p_info->price, &p_info->num) != EOF)
{
printf("%s %f %d\n", p_info->name, p_info->price, p_info->num);
bookinsert(p_link, p_info, location, size);
p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
}
free(p_info);
p_info = NULL;
printf("读取信息成功!\n");
fclose(fp);
}
11.功能函数
//功能
void book_keydown(booklink*lnk,int *size)
{
int userkey = 0;
int location = 0;
char bookname[20] = { 0 };
BOOKINFO *result = NULL;
BOOKINFO* p_info; // 将 p_info 的定义提前到 switch 之前
scanf("%d", &userkey);
switch (userkey)
{
case 0:
printf("登记\n");
p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
if (p_info == NULL) {
printf("内存分配失败!\n");
break;
}
printf("请输入要插入图书的信息(名称,价格,数量):\n");
scanf("%s%f%d", p_info->name, &p_info->price, &p_info->num);
printf("请输入要插入的位置:\n");
scanf("%d", &location);
if (location > *size || location==0) location = *size;
bookinsert(lnk, p_info, location, size);
savebook(lnk);
break;
case 1:
printf("【浏览】\n");
bookprint(lnk, size);
break;
case 2:
printf("【借阅】\n");
printf("请输入你要借阅的书名:");
scanf("%20s", bookname);
result = booksearch(lnk, bookname);
if (result == NULL) printf("未找到相关结果!\n");
else
{
if (result->num > 0)
{
result->num--;
printf("借阅成功!\n");
savebook(lnk);
}
else printf("当前书籍无库存,借阅失败!\n");
}
break;
case 3:
printf("【归还】\n");
printf("请输入你要归还的书名:");
scanf("%20s", bookname);
result = booksearch(lnk, bookname);
if (result == NULL) printf("书籍来源非法,归还失败!\n");
else
{
if (result->num > 0)
{
result->num++;
printf("归还成功!\n");
savebook(lnk);
}
}
break;
case 4:
printf("【查找】\n");
printf("请输入你要查找的书名:");
scanf("%20s", bookname);
result = booksearch(lnk, bookname);
if (result == NULL) printf("未找到相关结果!\n");
else printf("书名:%s\t,价格:%.2f\t,数量:%d\t\n", result->name, result->price, result->num);
break;
case 5:
printf("删除\n");
printf("请输入要删除的位置:");
scanf("%d", &location);
if (location > *size) location = *size;
bookdelete(lnk, location, size);
savebook(lnk);
break;
case 6:
delinit(lnk);
printf("已退出系统\n");
exit(0);
break;
default:
printf("输入有误,请重新输入!!!\n");
break;
}
}
12.主函数
int main()
{
booklink lnk = { 0 };
linkinit(&lnk);
int size = booksize(&lnk);
readbook(&lnk, &size);
while (1)
{
bookmenu();
book_keydown(&lnk,&size);
}
return 0;
}
五、项目完整代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
//定义图书信息
typedef struct bookinfo
{
char name[20];
float price;
int num;
struct bookinfo* next;
}BOOKINFO;
//链表
typedef struct link
{
BOOKINFO head;//头部
BOOKINFO tail;//尾部
}booklink;
//初始化
void linkinit(booklink* p_link)
{
p_link->head.next = &(p_link->tail);
p_link->tail.next = NULL;
}
//释放结点空间
void delinit(booklink* p_link)
{
while (p_link->head.next != &(p_link->tail))
{
BOOKINFO* p_first = &(p_link->head);
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
p_first->next = p_last;
free(p_mid);
p_mid = NULL;
}
}
//统计图书数量
int booksize(const booklink*p_link)
{
int cut = 0;
for (const BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next)
{
const BOOKINFO* p_first = p_node;
const BOOKINFO* p_mid = p_first->next;
const BOOKINFO* p_last = p_mid->next;
if (p_mid != &(p_link->tail))cut++;
}
return cut;
}
//菜单
void bookmenu()
{
printf("----------图书管理系统V1.0----------\n\n");
printf("------------0.登记新书--------------\n");
printf("------------1.浏览全部书籍----------\n");
printf("------------2.借阅书籍--------------\n");
printf("------------3.归还书籍--------------\n");
printf("------------4.查询书籍--------------\n");
printf("------------5.删除书籍--------------\n");
printf("------------6.退出系统--------------\n");
printf("------------------------------------\n");
}
//功能函数
//0.插入
void bookinsert(booklink* p_link, BOOKINFO* p_info, int location, int* size)
{
int i = 0;
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
{
BOOKINFO* p_first = p_node;
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
if (location == i)
{
p_info->next = p_mid;
p_first->next = p_info;
*size += 1;
break;
}
}
}
//1.打印图书有效信息
void bookprint(const booklink* p_link, int* size)
{
int i = 0;
if (*size == 0)
{
printf("当前没有图书信息,请先插入图书信息\n");
return;
}
for (const BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
{
const BOOKINFO* p_first = p_node;
const BOOKINFO* p_mid = p_first->next;
const BOOKINFO* p_last = p_mid->next;
if (p_mid != &(p_link->tail))
{
printf("第%d本图书的信息为:\n", i + 1);
printf("名字:%s,价格:%.2f,数量:%d\n", p_mid->name, p_mid->price, p_mid->num);
}
}
}
//2.查询书籍
BOOKINFO* booksearch(booklink* p_link, char* bookName)
{
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next)
{
BOOKINFO* p_first = p_node;
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
if (strcmp(bookName, p_mid->name) == 0) return p_mid;
}
return NULL;
}
//3.删除图书信息
void bookdelete(booklink* p_link, int location, int* size)
{
int i = 0;
for (BOOKINFO* p_node = &(p_link->head); p_node != &(p_link->tail); p_node = p_node->next, i++)
{
BOOKINFO* p_first = p_node;
BOOKINFO* p_mid = p_first->next;
BOOKINFO* p_last = p_mid->next;
if (location == i)
{
p_first->next = p_last;
free(p_mid);
*size -= 1;
break;
}
}
}
//保存文件
void savebook(booklink* p_link)
{
FILE* fp = fopen("booksave.txt", "w");
if (fp == NULL)
{
printf("无法打开文件!\n");
return;
}
BOOKINFO* p_tem = p_link->head.next;
while (p_tem != &p_link->tail)
{
fprintf(fp, "%s %f %d\n", p_tem->name, p_tem->price, p_tem->num);
p_tem = p_tem->next;
}
printf("保存图书信息成功!\n");
fclose(fp);
}
//读取文件
void readbook(booklink* p_link,int *size)
{
FILE* fp = fopen("booksave.txt", "r");
if (fp == NULL)
{
printf("无法打开文件!\n");
return;
}
BOOKINFO* p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
int location = 0;
while (fscanf(fp, "%s%f%d", p_info->name, &p_info->price, &p_info->num) != EOF)
{
printf("%s %f %d\n", p_info->name, p_info->price, p_info->num);
bookinsert(p_link, p_info, location, size);
p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
}
free(p_info);
p_info = NULL;
printf("读取信息成功!\n");
fclose(fp);
}
//功能
void book_keydown(booklink*lnk,int *size)
{
int userkey = 0;
int location = 0;
char bookname[20] = { 0 };
BOOKINFO *result = NULL;
BOOKINFO* p_info; // 将 p_info 的定义提前到 switch 之前
scanf("%d", &userkey);
switch (userkey)
{
case 0:
printf("登记\n");
p_info = (BOOKINFO*)malloc(sizeof(BOOKINFO));
if (p_info == NULL) {
printf("内存分配失败!\n");
break;
}
printf("请输入要插入图书的信息(名称,价格,数量):\n");
scanf("%s%f%d", p_info->name, &p_info->price, &p_info->num);
printf("请输入要插入的位置:\n");
scanf("%d", &location);
if (location > *size || location==0) location = *size;
bookinsert(lnk, p_info, location, size);
savebook(lnk);
break;
case 1:
printf("【浏览】\n");
bookprint(lnk, size);
break;
case 2:
printf("【借阅】\n");
printf("请输入你要借阅的书名:");
scanf("%20s", bookname);
result = booksearch(lnk, bookname);
if (result == NULL) printf("未找到相关结果!\n");
else
{
if (result->num > 0)
{
result->num--;
printf("借阅成功!\n");
savebook(lnk);
}
else printf("当前书籍无库存,借阅失败!\n");
}
break;
case 3:
printf("【归还】\n");
printf("请输入你要归还的书名:");
scanf("%20s", bookname);
result = booksearch(lnk, bookname);
if (result == NULL) printf("书籍来源非法,归还失败!\n");
else
{
if (result->num > 0)
{
result->num++;
printf("归还成功!\n");
savebook(lnk);
}
}
break;
case 4:
printf("【查找】\n");
printf("请输入你要查找的书名:");
scanf("%20s", bookname);
result = booksearch(lnk, bookname);
if (result == NULL) printf("未找到相关结果!\n");
else printf("书名:%s\t,价格:%.2f\t,数量:%d\t\n", result->name, result->price, result->num);
break;
case 5:
printf("删除\n");
printf("请输入要删除的位置:");
scanf("%d", &location);
if (location > *size) location = *size;
bookdelete(lnk, location, size);
savebook(lnk);
break;
case 6:
delinit(lnk);
printf("已退出系统\n");
exit(0);
break;
default:
printf("输入有误,请重新输入!!!\n");
break;
}
}
int main()
{
booklink lnk = { 0 };
linkinit(&lnk);
int size = booksize(&lnk);
readbook(&lnk, &size);
while (1)
{
bookmenu();
book_keydown(&lnk,&size);
}
return 0;
}
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。