#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Link
{
struct Link * prior;//指向直接前趋
char type[20];//类别
char bookNumber[10];//书号
char bookName[20];//书名
int quantityLent;//已借出的数量
int quantityNotLent;//未借出的数量
struct Link * next;//指向直接后继
}Link;//图书信息
//导入图书信息
Link* Write(Link* head)//从图书信息文件读取到链表里,此函数返回一个指向链表头的指针
{
head = NULL;
FILE *fp = fopen("D:\\books.txt", "r");//打开文件
if (fp == NULL)
{
printf("文件打开失败!\n");
exit(0);
}
Link *newbook, *p=NULL;
while (!feof(fp))//读取文件信息
{
newbook = (Link *)malloc(sizeof(Link));//开辟动态存储区,起始地址赋给newbook
char str[1024];
fgets(str, 1024, fp);
//printf("%s\n", str);
char *token;
const char * split = " ";
token = strtok(str, split);
strcpy(newbook->type, token);
token = strtok(NULL, split);
strcpy(newbook->bookNumber, token);
token = strtok(NULL, split);
strcpy(newbook->bookName, token);
token = strtok(NULL, split);
newbook->quantityLent = *token - '0';
token = strtok(NULL, split);
newbook->quantityNotLent = *token - '0';
//printf("%s %s %s %d %d", newbook->type,
// newbook->bookNumber,
// newbook->bookName,
// newbook->quantityLent,
// newbook->quantityNotLent);
if (head == NULL)
head = newbook;
else
{
p->next = newbook;
newbook->prior = p;
}
p= newbook;
p->next = NULL;
}
fclose(fp);//关闭文件
return head;
}
//新增图书
Link* InsertElem(Link* head)
{
printf("新增图书信息,请输入:\n");
//创建插入结点c
Link* c = (Link*)malloc(sizeof(Link));
printf("图书类别 书号 书名 已借出的数量 未借出的数量\n");
scanf("%s %s %s %d %d", c->type, c->bookNumber, c->bookName, &c->quantityLent, &c->quantityNotLent);
c->next = NULL;
Link* temp = head;//创建临时结点temp
//找链表最末端
if (temp == NULL)//链表本就空的,考虑特殊情况
head = c;
else
{
while (temp->next != NULL)
temp = temp->next;
//插入链表
temp->next = c;
c->prior = temp;
}
return head;
}
//更改图书信息
void ChangeBooks(Link* head)
{
Link* temp = head;
char num[10];
printf("输入你要修改的书号:\n");
scanf("%s", num);
if (temp != NULL)
{
while (strcmp(temp->bookNumber, num) != 0 && temp!=NULL)
temp = temp->next;
if (temp == NULL)
{
printf("未找到相关图书信息\n");
return;
}
printf("图书类别 书号 书名 已借出的数量 未借出的数量\n");
printf("%s %s %s %d %d\n", temp->type, temp->bookNumber, temp->bookName, temp->quantityLent, temp->quantityNotLent);
printf("输入更改后的信息\n");
printf("图书类别 书号 书名 已借出的数量 未借出的数量\n");
scanf("%s %s %s %d %d", temp->type, temp->bookNumber, temp->bookName, &temp->quantityLent, &temp->quantityNotLent);
printf("================修改完毕================\n");
}
else
printf("图书信息为空!\n");
}
//删除图书信息
Link* DeleteBooks(Link* head)
{
Link * temp = head;
char num[10];
printf("输入你要删除的书号:\n");
scanf("%s", num);
if (temp != NULL)
{
while (strcmp(temp->bookNumber, num) != 0 && temp != NULL)
temp = temp->next;
if (temp == NULL)
{
printf("未找到相关图书信息\n");
return;
}
printf("图书类别 书号 书名 已借出的数量 未借出的数量\n");
printf("%s %s %s %d %d\n", temp->type, temp->bookNumber, temp->bookName, temp->quantityLent, temp->quantityNotLent);
if (temp == head)
{
head = temp->next;
head->prior = NULL;
free(temp);
}
else if (temp->next == NULL)//最后一个结点
{
temp->prior->next = NULL;
free(temp);
}
else
{
temp->prior->next = temp->next;
temp->next->prior = temp->prior;
free(temp);//删除该结点
}
printf("================删除完毕================\n");
}
else
printf("图书信息为空!\n");
return head;
}
//查找图书
void FindBooks(Link* head)
{
printf("选择查找方式:书名查找按1,类别查找按2,书号查找按3:");
int option;
scanf("%d", &option);
switch (option)
{
case 1:printf("请输入你想要查找的书名:"); break;
case 2:printf("请输入你想要查找的类别:"); break;
case 3:printf("请输入你想要查找的书号:"); break;
}
char inputO[20];
scanf("%s", inputO);
Link* temp = head;//开始根据要求查找
while (temp != NULL)//字符串比较
{
if (strcmp(temp->bookName, inputO) == 0 || strcmp(temp->bookNumber, inputO) == 0 || strcmp(temp->type, inputO) == 0)
{
printf("图书类别 书号 书名 已借出的数量 未借出的数量\n");
printf("%s %s %s %d %d\n", temp->type, temp->bookNumber, temp->bookName, temp->quantityLent, temp->quantityNotLent);
}
temp = temp->next;
}
}
//显示所有图书信息
void display(Link* head)
{
if (head == NULL)
{
printf("图书信息为空.\n");
return;
}
printf("图书类别 书号 书名 已借出的数量 未借出的数量\n");
Link* temp = head;
while (temp != NULL)//字符串比较
{
printf("%s %s %s %d %d\n", temp->type, temp->bookNumber, temp->bookName, temp->quantityLent, temp->quantityNotLent);
temp = temp->next;
}
}
//全删当前数据
Link* ClearAll(Link* head)
{
Link* pListNodeTmp = NULL;
if (head == NULL)
{
printf("The list is empty, no need to clear.\n");
return;
}
// 循环释放链表中的结点所占内存,清空结束后
while (head->next != NULL)
{
pListNodeTmp = head->next;
free(head);
head = pListNodeTmp;
}
// 清除最后一个结点
if (head != NULL)
{
free(head);
head = NULL;
}
printf("================已经全删================\n");
return head;
}
//图书管理系统菜单
int menu()
{
int m;
do{
printf("欢迎进入图书管理系统,按1进入管理员系统,按2进入用户系统:");
scanf("%d", &m);
} while (m !=1 && !m==2);//菜单选项外跳出
return m;
}
//管理员系统菜单
int menu_M()
{
int m;
do{
printf("\t================图书维护系统================\n\n");
printf("\t\t1. 新增图书\n");
printf("\t\t2. 更改图书信息\n");
printf("\t\t3. 删除图书信息\n");
printf("\t\t4. 查找图书\n");
printf("\t\t5. 显示所有图书信息\n");
printf("\t\t6. 全删当前数据\n");
printf("\t\t0. 退出\n\n");
printf("\t================请选择================\n\n");
scanf("%d", &m);
} while (m < 0 && m>6);//菜单选项外跳出
return m;
}
typedef struct LinkU
{
struct LinkU * prior;//指向直接前趋
char studentNumber[10];//学号
char name[20];//姓名
int quantityLent;//已借出的数量
int maxLendingVolume;//最大借书量
char c[5][20];//借书项目
struct LinkU * next;//指向直接后继
}LinkU;//用户信息
//导入用户信息
LinkU* WriteUsers(LinkU* head)//从图书信息文件读取到链表里,此函数返回一个指向链表头的指针
{
FILE *fp = fopen("D:\\Users.txt", "r");//打开文件
if (fp == NULL)
{
printf("文件打开失败!\n");
exit(0);
}
LinkU *newUser, *p = NULL;
FILE *fp_temp = fopen("D:\\Users.txt", "r");
while (!feof(fp))//读取文件信息
{
newUser = (LinkU *)malloc(sizeof(LinkU));//开辟动态存储区,起始地址赋给newUser
int quantityLent_temp;
fscanf(fp_temp, "%*s %*s %d", &quantityLent_temp);
if (quantityLent_temp == 0)
fscanf(fp, "%s %s %d %d", newUser->studentNumber, newUser->name, &newUser->quantityLent, &newUser->maxLendingVolume);
else if (quantityLent_temp == 1)
fscanf(fp, "%s %s %d %d %s", newUser->studentNumber, newUser->name, &newUser->quantityLent, &newUser->maxLendingVolume, newUser->c[0]);
else if (quantityLent_temp == 2)
fscanf(fp, "%s %s %d %d %s %s", newUser->studentNumber, newUser->name, &newUser->quantityLent, &newUser->maxLendingVolume, newUser->c[0], newUser->c[1]);
else if (quantityLent_temp == 3)
fscanf(fp, "%s %s %d %d %s %s %s", newUser->studentNumber, newUser->name, &newUser->quantityLent, &newUser->maxLendingVolume, newUser->c[0], newUser->c[1], newUser->c[2]);
else if (quantityLent_temp == 4)
fscanf(fp, "%s %s %d %d %s %s %s %s", newUser->studentNumber, newUser->name, &newUser->quantityLent, &newUser->maxLendingVolume, newUser->c[0], newUser->c[1], newUser->c[2], newUser->c[3]);
else if (quantityLent_temp == 5)
fscanf(fp, "%s %s %d %d %s %s %s %s %s", newUser->studentNumber, newUser->name, &newUser->quantityLent, &newUser->maxLendingVolume, newUser->c[0], newUser->c[1], newUser->c[2], newUser->c[3], newUser->c[4]);
if (head == NULL)
head = newUser;
else
{
p->next = newUser;
newUser->prior = p;
}
p = newUser;
p->next = NULL;
}
fclose(fp_temp);//关闭文件
fclose(fp);//关闭文件
return head;
}
//用户系统菜单
LinkU* menu_StuPick(LinkU* head)//检验用户是否存在
{
head = WriteUsers(head);//导入用户数据
LinkU * temp = head;
char sNumber[10];//学号
printf("用户请输入学号登录:");
scanf("%s", sNumber);
while ((strcmp(temp->studentNumber, sNumber) != 0) && temp != NULL)
temp = temp->next;
if (temp == NULL)
{
printf("未找到相关用户信息\n");
return;
}
head = temp;
return head;
}
int menu_S()
{
int m;
do{
printf("\t================图书维护系统================\n\n");
printf("\t\t1. 借阅图书\n");
printf("\t\t2. 归还图书\n");
printf("\t\t3. 查看所有图书\n");
printf("\t\t4. 查找图书\n");
printf("\t\t5. 显示我的信息\n");
printf("\t\t0. 退出\n\n");
printf("\t================请选择================\n\n");
scanf("%d", &m);
} while (m < 0 && m>5);//菜单选项外跳出
return m;
}
//借阅图书
LinkU* BorrowBooks(LinkU* head)
{
printf("================书籍借阅系统================\n");
if (head->quantityLent >= 5)
{
printf("已超出最大借书数量\n");
return -1;
}
printf("请输入你想要借阅的书号:");
scanf("%s", head->c[head->quantityLent]);
head->quantityLent++;//借阅数量+1
printf("借阅成功\n");
printf("============================================\n");
return head;
}
//归还图书
LinkU* ReturnBooks(LinkU* head)
{
printf("================书籍借阅系统================\n");
printf("请输入你想要归还的书号:");
char bookN[20];
scanf("%s", bookN);
for (int i = 0; i < head->quantityLent; i++)
{
if ((strcmp(head->c[i], bookN) == 0))
{
for (int j = i; j < head->quantityLent - 1; j++)
{
strcpy(head->c[i], head->c[i+1]);
}
head->quantityLent--;
}
}
printf("归还成功\n");
printf("============================================\n");
return head;
}
//显示我的信息
void displayMine(LinkU* head)
{
if (head == NULL)
{
printf("我的信息为空.\n");
return -1;
}
printf("学号 姓名 已借出的数量 最大借书数量 借书项目\n");
printf("%s %s %d %d ", head->studentNumber, head->name, head->quantityLent, head->maxLendingVolume);
for (int i = 0; i < head->quantityLent; i++)
printf("%s ", head->c[i]);
printf("\n");
}
int main()//主函数
{
Link *head = NULL;
LinkU *headU = NULL;
for (;;)//死循环
{
switch (menu())
{
case 1:
for (;;)
{
switch (menu_M())
{
case 1:head = Write(head); head = InsertElem(head); break;
case 2:ChangeBooks(head); break;
case 3:head = DeleteBooks(head); break;
case 4:FindBooks(head); break;
case 5:display(head); break;
case 6:head = ClearAll(head); break;
case 0:exit(0); break;
default:printf("================输入错误================\n"); break;
}
}
case 2:
headU = menu_StuPick(headU);
for (;;)
{
switch (menu_S())
{
case 1:headU = BorrowBooks(headU); break;
case 2:headU = ReturnBooks(headU); break;
case 3:head = Write(head); display(head); break;
case 4:head = Write(head); FindBooks(head); break;
case 5:displayMine(headU); break;
case 0:exit(0); break;
default:printf("================输入错误================\n"); break;
}
}
default:printf("================输入错误================\n"); break;
}
}
return 0;
}
Books.txt
科幻 1001001 未来1 5 1
科幻 1001002 未来2 1 6
教科 1002102 语文 1 0
科幻 1002309 我在火星 5 2
Users.txt
104173101 张三 4 5 1001002 1001002 1001001 1002309