【链表实现图书信息管理系统】

@[TOC]链表实现图书信息管理系统

项目描述

使用C语言的链表实现一个简单的图书信息管理系统,主要功能包括对图书的添加、删除、修改、查询、插入、排序、显示、保存等。

结构体的声明

typedef struct book
{
	int number; //图书编号
	char name[50]; //图书名
	char lendData[50]; //借出日期
	char condition[20]; //图书状态
	int lendCount; //借阅次数
	struct book *next;
}book, *LinkBook;

函数的声明

LinkBook initLinkList();  //初始化链表
void displayLinkList(LinkBook L);  //显示图书信息
LinkBook getFinalNode(LinkBook L); //获取尾节点
void addBook(LinkBook L); //添加图书,这里是在最后添加图书
void deleteBook(LinkBook L, int num);  //根据图书的编号num进行删除图书操作
void modifyBook(LinkBook L, int num);  //根据图书的编号num对其进行修改
void findBook(LinkBook L, int num); //根据图书的编号num对其进行查找
void insertBook(LinkBook L, int i); //向指定的位置i插入一本书
void sortByNumber(LinkBook L);  //根据图书的编号进行升序排序
void interface(); //程序交互界面
void outToTxt(LinkBook L); //将链表中的图书信息保存到txt文档中

函数的定义

见后面的function.c文件。

程序界面与功能演示

程序主界面:
在这里插入图片描述
添加功能演示:
在这里插入图片描述
删除功能演示:
在这里插入图片描述
修改功能演示:
在这里插入图片描述
查询功能演示:
在这里插入图片描述
插入功能演示:
在这里插入图片描述
插入后查询的结果:
在这里插入图片描述
排序功能演示:
这里默认的是根据图书的编号进行升序排序,这里采用的方法是冒泡排序算法,具体实现代码可以查看上面的函数定义或者后面的源码
在这里插入图片描述
排序前:
在这里插入图片描述
排序后:
在这里插入图片描述
保存为txt:
在这里插入图片描述
之后会在该项目所在的路径下面生成一个book.txt的文件,用于存放之前链表中 存放的图书信息,如下图所示:
在这里插入图片描述

完整代码

function.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


typedef struct book
{
	int number; //图书编号
	char name[50]; //图书名
	char lendData[50]; //借出日期
	char condition[20]; //图书状态
	int lendCount; //借阅次数
	struct book *next;
}book, *LinkBook;


LinkBook initLinkList();  //初始化链表
void displayLinkList(LinkBook L);  //显示图书信息
LinkBook getFinalNode(LinkBook L); //获取尾节点
void addBook(LinkBook L); //添加图书,这里是在最后添加图书
void deleteBook(LinkBook L, int num);  //根据图书的编号num进行删除图书操作
void modifyBook(LinkBook L, int num);  //根据图书的编号num对其进行修改
void findBook(LinkBook L, int num); //根据图书的编号num对其进行查找
void insertBook(LinkBook L, int i); //向指定的位置i插入一本书
void sortByNumber(LinkBook L);  //根据图书的编号进行升序排序
void interface(); //程序交互界面
void outToTxt(LinkBook L); //将链表中的图书信息保存到txt文档中



function.c文件

#include"function.h"

LinkBook initLinkList()  //初始化链表
{
	LinkBook head = (LinkBook)malloc(sizeof(book));
	head->next = NULL;
	return head;
}

void displayLinkList(LinkBook L) //显示链表中图书的信息
{
	printf("图书编号\t书  名\t\t\t借出日期\t\t图书状态\t\t借阅次数\n\n");
	LinkBook p;
	p = L->next;  //p指向L头节点的下一个节点
	if (p == NULL)  //p为空,则说明链表内无图书信息
	{
		printf("暂无图书");
		return;
	}
	while (p != NULL) //遍历输出链表中的图书信息
	{
		printf("%-8d\t%-20s\t%-20s\t%-20s\t%-8d\n", p->number, p->name, p->lendData, p->condition, p->lendCount);
		//printf("%d\t%s\t%s\t%s\t%d\n", p->number, p->name, p->lendData, p->condition, p->lendCount);
		p = p->next;
	}
}

LinkBook getFinalNode(LinkBook L)  //获取链表的尾节点
{
	LinkBook p;
	p =L;
	while (p->next != NULL) //当p的下一个节点非空时,当前节点后移
		p = p->next;
	return p;   //返回尾节点
}

void addBook(LinkBook L)  //添加图书
{
	LinkBook p,s;
	int number; //图书编号
	char name[50]; //图书名
	char lendData[50]="2024-1-1"; //借出日期,添加进来默认为2024-1-1
	char condition[20]="在馆"; //图书状态,添加进来默认在馆
	int lendCount=0; //添加进来借阅次数默认为0
	p = getFinalNode(L);  //用p存放L的尾节点,目的是为了每次都在末尾插入图书信息
	s = (LinkBook)malloc(sizeof(book));//s用来存放添加的图书信息
	printf("请输入图书编号:");
	scanf("%d", &number);
	printf("\n请输入图书名:");
	scanf("%s", name);

	//s存放添加图书的信息
	s->number = number;
	strcpy(s->name, name);
	strcpy(s->lendData, lendData);
	strcpy(s->condition, condition);
	s->lendCount = lendCount;

	p->next = s; //将尾节点的下一个节点指向s
	s->next = NULL;//令s的next指针为空,这样添加的图书就作为尾节点加入到原来的链表中
	printf("\n图书已添加");
}

void deleteBook(LinkBook L, int num)  //删除图书编号为num的图书信息
{
	LinkBook p,q;
	p = L;
	while (p->next != NULL && p->next->number != num)//寻找图书编号为num的节点的前一个节点
		p = p->next;
	if (p->next == NULL && p->number != num) //如果找到最后一个节点都没有找到编号为num的节点,则说明不存在这样一本图书
	{
		printf("该图书不存在!");
		return;
	}
	q = p->next;  //用q存储编号为num的节点,p相当于是编号为num节点的前一个节点
	p->next = q->next; //相当于直接跳过编号为num的节点,指向它的后一个节点,这样就达到了删除num节点的目的
	printf("\n图书已被删除");
}

void modifyBook(LinkBook L, int num)  //修改图书编号为num的图书信息 
{
	LinkBook p;
	p = L;
	int number; //图书编号
	char name[50]; //图书名
	char lendData[50]; //借出日期
	char condition[20]; //图书状态
	int lendCount; //借阅次数
	while (p->next != NULL && p->number != num) //寻找编号为num的节点
		p = p->next;
	if (p->next == NULL && p->number != num)
	{
		printf("该图书不存在!");
		return;
	}
	//输入修改的信息
	printf("输入要修改的图书编号:");
	scanf("%d", &number);
	printf("输入要更改的书名:");
	scanf("%s", name);
	printf("输入要更改的借出日期:");
	scanf("%s", lendData);
	printf("输入要更改的图书状态:");
	scanf("%s", condition);
	printf("输入要更改的借阅次数:");
	scanf("%d", &lendCount);

	//找到之后,直接修改这个节点的信息
	p->number = number;
	strcpy(p->name, name);
	strcpy(p->lendData, lendData);
	strcpy(p->condition, condition);
	p->lendCount = lendCount;
	
	printf("\n图书已被修改");
}

void findBook(LinkBook L, int num)  //查询编号为num的图书信息
{
	printf("\n查询结果如下:\n");
	LinkBook p;
	p = L;
	while (p->next != NULL && p->number != num)//寻找编号为num的节点
		p = p->next;
	if (p->next == NULL && p->number != num)
	{
		printf("该图书不存在!");
		return;
	}

	//找到目标节点之后,打印出该图书的信息
	printf("图书编号\t书  名\t\t\t借出日期\t\t图书状态\t\t借阅次数\n\n");
	printf("%-8d\t%-20s\t%-20s\t%-20s\t%-8d\n", p->number, p->name, p->lendData, p->condition, p->lendCount);
}

void insertBook(LinkBook L, int i) //在指定位置i插入一本图书
{
	//用于存储插入图书的信息
	int count = 1; //用count来记录节点的位置
	int number; //图书编号
	char name[50]; //图书名
	char lendData[50]; //借出日期
	char condition[20]; //图书状态
	int lendCount; //借阅次数

	LinkBook p,s;
	s = (LinkBook)malloc(sizeof(book));//s用于存放插入图书的信息
	p = L;
	while (p->next != NULL && count < i) //当指针还没有到达指定的位置i时,继续往后面移动
	{
		p = p->next;
		count++; //每往后面移动一步,count加1记录一步
	}
	if (p->next == NULL && count < i)  
	{
		printf("位置不存在!");
		return;
	}

	//输入插入图书的信息
	printf("输入要插入图书的编号:");
	scanf("%d", &number);
	printf("输入要插入图书的书名:");
	scanf("%s", name);
	printf("输入要插入图书的借出日期:");
	scanf("%s", lendData);
	printf("输入要插入图书的图书状态:");
	scanf("%s", condition);
	printf("输入要插入图书的借阅次数:");
	scanf("%d", &lendCount);

	//用s来存储插入图书的信息
	s->number = number;
	strcpy(s->name, name);
	strcpy(s->lendData, lendData);
	strcpy(s->condition, condition);
	s->lendCount = lendCount;
	s->next = p->next; //s的next指针指向目标位置后面的节点
	p->next = s;  //然后s充当目标位置i上的节点

	printf("\n图书插入完毕!");
}

void sortByNumber(LinkBook L)  //根据图书的编号进行升序排序
{
	int flag;  //用于标记是否已经排序完毕
	LinkBook p, pre, tail;
	tail = NULL;  //tail指针来标记排好序的位置,tail往后的位置都是排好的,初始时没有排序,所以为空
	
	while (1)
	{
		flag = 1;  
		//每次从L->next开始遍历,直到tail结束,pre是p的前驱节点
		for (pre = L, p = L->next; p&&p->next != tail; pre = pre->next)
		{
			if (p->number > p->next->number) //前一个值大于后一个时
			{
				flag = 0; //flag设置为0,表示本轮循环发生交换
				pre->next = p->next; //前驱直接指向后驱节点
				p->next = p->next->next; //后驱节点指向后驱节点的后驱节点
				pre->next->next = p;//相当于将当前节点变成其后驱节点
			}
			else
			{
				p = p->next;
			}
		}

		if (flag)
			break;

		tail = p; //每一轮循环都有一个节点到正确的位置上,所以tail需要前移一个位置
		
	}

	printf("\n图书排序完毕");
}

void interface()  //图书管理系统的交互界面设计
{
	printf("\n\n=========图书管理系统=========");
	printf("\n\n---------功能选择-----------");
	printf("\n\n     --->1.添加图书");
	printf("\n     --->2.删除图书");
	printf("\n     --->3.修改图书");
	printf("\n     --->4.查询图书");
	printf("\n     --->5.插入图书");
	printf("\n     --->6.排序图书");
	printf("\n     --->7.显示图书");
	printf("\n     --->8.保存为txt");
	printf("\n     --->9.退    出");
}

void outToTxt(LinkBook L)  //将链表中存放的图书信息全部保存到.txt文件中
{
	FILE *fp = NULL;
	fp = fopen("book.txt", "a"); //打开book.txt,如果没有,会自动生成一个book.txt文件
	if (fp == NULL)
	{
		printf("\n路径读取出错");
		return;
	}

	//在book.txt中写入图书的各类信息的标题
	fprintf(fp, "图书编号\t书  名\t\t\t借出日期\t\t图书状态\t\t借阅次数\n\n");
	fflush(fp);

	LinkBook p;
	p = L->next;
	while (p != NULL) //遍历链表,将每一条图书信息都写到book.txt文件中
	{
		fprintf(fp, "%-8d\t%-20s\t%-20s\t%-20s\t%-8d\n", p->number, p->name, p->lendData, p->condition, p->lendCount);
		fflush(fp);
		p = p->next;
	}

	fclose(fp);
}

main.c文件

#include"function.h"

int main()
{
	int choice;  //用于菜单操作的选择
	int flag = 1; //用于终止程序
	LinkBook L;  //声明一个链表,用于存放图书信息
	L = initLinkList(); //初始化链表
	while (flag)  //循环启动图书管理系统
	{
		int num;  //用于存放修改、删除、查询的编号和插入的位置
		interface(); //启动管理系统的交互界面
		printf("\n请选择你的操作:");  
		scanf("%d", &choice);
		switch (choice)  //根据选择的操作,跳转到执行相应的功能
		{
		case 1:  //执行添加图书操作
			addBook(L);
			break;
		case 2:  //执行删除图书操作
			printf("请输入要删除图书的编号:");
			scanf("%d", &num);
			deleteBook(L, num); //删除指定图书编号的图书信息
			break;
		case 3:  //执行修改图书操作
			printf("请输入要修改的图书编号:");
			scanf("%d", &num);
			modifyBook(L, num); //修改指定图书编号对应的图书信息
			break;
		case 4:  //执行查询图书操作
			printf("请输入要查询的图书编号:");
			scanf("%d", &num); 
			findBook(L, num); //根据给定的图书编号进行图书查询
			break;
		case 5:  //执行指定位置插入图书
			printf("请输入要插入的位置:");
			scanf("%d", &num);
			insertBook(L, num); //这里的num表示指定的位置
			break;
		case 6: //执行排序操作
			sortByNumber(L); //根据图书的编号对其进行升序排序
			break;
		case 7:  //执行显示图书操作
			displayLinkList(L);
			break;
		case 8:  //执行输出图书信息到.txt文件的操作
			outToTxt(L);
			break;
		case 9: //退出系统,将flag设为0
			flag = 0;
			break;
		default:  //不是上述的功能,则提示出错
			printf("\n输入错误,没有此功能");
			break;
		}
	}
	
	return 0;
}

需要源码的可以自行下载:C语言链表实现图书信息管理系统

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值