C语言图书管理系统-期末课设-学习笔记1

300行代码速通C语言指针链表、学会文件读取。多刷!!大佬的视频讲解请见参考部分。学会这个大一拿下!

系统功能包含:添加、删除、排序、查询、文件读取等。

编译器:devc++

如果遇到for循环中不能定义,即for(int i=0; i<6; i++);

请参考:Dev C++ C语言中for循环中声明循环控制变量的问题_devc++ for中设置变量-CSDN博客

0、头文件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

1、菜单

简单页面设计,可自己设计。

//1.make Menu-模块
void makeMenu() {
	printf("+---------------------------------+\n");
	printf("|     Books Management System     |\n");
	printf("+---------------------------------+\n");
	printf("0 退出系统\n");
	printf("1 登记书籍\n");  //添加
	printf("2 浏览书籍\n");  //显示
	printf("3 借阅书籍\n");  //修改
	printf("4 归还书籍\n");
	printf("5 书籍排序\n");
	printf("6 删除书籍\n");  //删除
	printf("7 查找书籍\n\n"); //查询
	printf("请选择(0~7):");
}

2、交互功能

使用switch实现选择菜单功能的效果(主框架),在后续其它功能的完善中会补充完全。

//2.做交互-按键处理-跳转
void keyDown() {
	int userKey = 0;
	scanf("%d",&userKey);
	switch(userKey) {
		case 0:
			printf("[退出成功]\n");
			break;
		case 1:
			printf("[登记]\n");
			break;
		case 2:
			printf("[浏览]\n");
			break;
		case 3:
			printf("[借阅]\n"); //书籍存在可借阅,数量-1;不存在,节约失败
			break;
		case 4:
			printf("[归还]\n"); //书籍数量+1
			break;
		case 5:
			printf("[排序]\n");
			BubbleSortList(list);
			break;
		case 6:
			printf("[删除]\n");
			break;
		case 7:
			printf("[查找]\n");
			break;
		default:
			printf("[Error! 请输入0~7之间的数字!]\n");
			break;
	}

}

3、系统设计

3.1 选择容器->链表

包含了浏览、添加、删除功能的函数编写。

//3.1 链表  =结构体变量
//3.1.1创建链表:
struct Node {
	struct bookInfo data;
	struct Node *next;
};

//3.1.2创建表头;表头就是结构体变量
struct Node* createHead() {
	//内存动态申请
	struct Node* headNode=(struct Node*)malloc(sizeof(struct Node));
	//变量的基本规则:使用前初始化
	headNode->next=NULL;
	return headNode;
}

//3.1.3创建节点(同创建表头):为插入做准备
//后面把用户的数据变为结构体变量
struct Node* createNode(Data) {
	struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));
	newNode->data=Data;
	newNode->next=NULL;
	return newNode;
}
//插入:表头插入 
void insertNodeByHead(struct Node* headNode,struct bookInfo data) {
	struct Node* newNode=createNode(data);
	newNode->next=headNode->next; 
	headNode->next=newNode;       
}


//第一次的删除写法
//问题:找删除节点和删除前一个节点
//函数名的Data为一个结构体
void deleteNodeByData(struct Node* headNode,Data) {
	struct Node* posLeftNode = headNode;
	struct Node* posNode=headNode->next;
	//当查找的数据不是要删除的数据
	while(posNode!=NULL && posNode->data!=Data) {
		posLeftNode=posNode;  //将左节点后移
		posNode=posLeftNode->next; //将当前节点后移
	}
	//讨论查找结果
	if(posNode==NULL)
		return;
	else {
		posLeftNode->next=posNode->next;
		free(posNode);
		posNode=NULL;
	}

}

//打印链表:以当前节点为头节点的链表
void printList(struct Node* headNode) {
	struct Node* pMove=headNode->next;
	printf("书名\t价格\t数量\n");
	while(pMove!=NULL) {
		printf("%s\t%.1f\t%d\n",pMove->data.name, pMove->data.price, pMove->data.num);
		pMove=pMove->next;
	}
}

3.2 数据结构设计

图书包含的信息可以自行添加,但要在对应的函数以及输出中进行相应的修改。

//3.2图书信息  书名、价格、数量
struct bookInfo {
	char name[20];
	float price;
	int num;
};

4、文件操作

//4.文件操作-> 对 list
//4.1 存(写)操作
void saveInfoToFile(const char* fileName, struct Node* headNode) {
	FILE *fp=fopen(fileName,"w"); //打开文件 只写
	struct Node* pMove= headNode->next;
	while(pMove!=NULL) {
		fprintf(fp,"%s\t%.1f\t%d\n",pMove->data.name,pMove->data.price,pMove->data.num);
		pMove = pMove->next;
	}
	fclose(fp);  //关闭文件
}

//4.2 读操作
void readInfoFromFile(const char *fileName,struct Node* headNode) {
	FILE *fp=fopen(fileName,"r");  //只读
	if(fp==NULL) {
		//第一次打开 不存在就创建
		fp=fopen(fileName,"w+");
	}
	struct bookInfo tempData;
	while(fscanf(fp,"%s\t%f\t%d\n",tempData.name,&tempData.price,&tempData.num)!=EOF) {
		insertNodeByHead(list,tempData);  //读一个信息插入链表
	}
	fclose(fp);
}

5、排序(冒泡)

//5.使用价格排序  冒泡->相邻的相比较
void BubbleSortList(struct Node* headNode) {
	struct Node* p;
	struct Node* q;

	for(p=headNode->next; p!=NULL; p=p->next) {
		for(q=headNode->next; q->next!=NULL; q=q->next) {
			if(q->data.price > q->data.price) {

				struct bookInfo tempData=q->data;
				q->data=q->next->data;
				q->next->data=tempData;
			}
		}
	}
	printList(headNode);
}

6、查找

函数的定义类型即结构体指针,void无返回类型,不能用return。

//6.函数类型:结构体指针 -> 查找  -> 链表的查找
//借阅和归还使用查找功能写
struct Node* searchByName(struct Node* headNode,char *bookname) {
	struct Node* posNode=headNode->next;
	while(posNode!=NULL && strcmp(posNode->data.name,bookname)) {
		posNode = posNode->next;  
	}
	return posNode; 
}

7、完整代码实现

无报错,可运行。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//3.数据设计(C自定义链表) 
//3.2图书信息  书名、价格、数量
struct bookInfo {
	char name[20];
	float price;
	int num;
};

struct Node* list=NULL;//全局链表

//3.1 链表  =结构体变量
//创建链表:
struct Node {
	struct bookInfo data;
	struct Node *next;
};

// 创建表头;表头就是结构体变量
struct Node* createHead() {
	//内存动态申请
	struct Node* headNode=(struct Node*)malloc(sizeof(struct Node));
	headNode->next=NULL;
	return headNode;
}

//创建节点(同创建表头):为插入做准备
struct Node* createNode(struct bookInfo data) {
	struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));
	newNode->data=data;
	newNode->next=NULL;
	return newNode;
}
//插入:表头插入 
void insertNodeByHead(struct Node* headNode,struct bookInfo data) {
	struct Node* newNode=createNode(data);
	newNode->next=headNode->next;  
	headNode->next=newNode;       
}


//指定位置删除posleft->next=pos->next and free(pos) and pso=NULL
//书名删除->  字符串的删除,字符比较函数
void deleteNodeByName(struct Node* headNode,char *bookname) {
	struct Node* posLeftNode = headNode;
	struct Node* posNode=headNode->next;
	//当查找的数据不是要删除的数据
	while(posNode!=NULL && strcmp(posNode->data.name,bookname)) {
		posLeftNode=posNode;  //将左节点后移
		posNode=posLeftNode->next; //将当前节点后移
	}
	//讨论查找结果
	if(posNode==NULL)
		return;
	else {
		printf("删除成功!");
		posLeftNode->next=posNode->next;
		free(posNode);
		posNode=NULL;
	}
}

//6.函数类型:结构体指针 -> 查找  -> 链表的查找
//借阅和归还使用查找功能写
struct Node* searchByName(struct Node* headNode,char *bookname) {
	struct Node* posNode=headNode->next;
	//strcmp 0相等  >0前面的大  <0后面的大
	while(posNode!=NULL && strcmp(posNode->data.name,bookname)) {
		posNode = posNode->next;  //不相等
	}
	return posNode; //非空->找到了
}



//打印链表:以当前节点为头节点的链表
void printList(struct Node* headNode) {
	struct Node* pMove=headNode->next;
	printf("书名\t价格\t数量\n");
	while(pMove!=NULL) {
		printf("%s\t%.1f\t%d\n",pMove->data.name, pMove->data.price, pMove->data.num);
		pMove=pMove->next;
	}
}


//1.make Menu-模块
void makeMenu() {
	printf("+---------------------------------+\n");
	printf("|     Books Management System     |\n");
	printf("+---------------------------------+\n");
	printf("0 退出系统\n");
	printf("1 登记书籍\n"); 
	printf("2 浏览书籍\n"); 
	printf("3 借阅书籍\n");  
	printf("4 归还书籍\n");
	printf("5 书籍排序\n");
	printf("6 删除书籍\n");  
	printf("7 查找书籍\n\n"); 
	printf("请选择(0~7):");
}

//4.文件操作-> 对 list
//4.1 存(写)操作
void saveInfoToFile(const char* fileName, struct Node* headNode) {
	FILE *fp=fopen(fileName,"w"); //打开文件 只写
	struct Node* pMove= headNode->next;
	while(pMove!=NULL) {
		fprintf(fp,"%s\t%.1f\t%d\n",pMove->data.name,pMove->data.price,pMove->data.num);
		pMove = pMove->next;
	}
	fclose(fp);  //关闭文件
}

//4.2 读操作
void readInfoFromFile(const char *fileName,struct Node* headNode) {
	FILE *fp=fopen(fileName,"r");  //只读
	if(fp==NULL) {
		//第一次打开 不存在就创建
		fp=fopen(fileName,"w+");
	}
	struct bookInfo tempData;
	while(fscanf(fp,"%s\t%f\t%d\n",tempData.name,&tempData.price,&tempData.num)!=EOF) {
		insertNodeByHead(list,tempData);
	}
	fclose(fp);
}

//5.排序  冒泡->相邻的相比较
void BubbleSortList(struct Node* headNode) {
	struct Node* p;
	struct Node* q;

	for(p=headNode->next; p!=NULL; p=p->next) {
		for(q=headNode->next; q->next!=NULL; q=q->next) {
			//价格排序
			if(q->data.price > q->data.price) {

				struct bookInfo tempData=q->data;
				q->data=q->next->data;
				q->next->data=tempData;
			}
		}
	}
	printList(headNode);
}


//2.做交互-按键处理-跳转
void keyDown() {
	int userKey = 0;

	struct bookInfo tempBook; //产生临时的变量存储书籍信息
	struct Node* result =NULL; //临时指针->书籍查询结果

	scanf("%d",&userKey);
	switch(userKey) {
		case 0:
			printf("[退出成功]\n");
			exit(0);
			break;
		case 1:
			printf("[登记]\n");
			printf("请输入书籍信息:书名,价格,数量\n");
			//字符串不用&
			scanf("%s%f%d",tempBook.name, &tempBook.price, &tempBook.num);
			insertNodeByHead(list,tempBook);
			saveInfoToFile("bookInfo.txt",list);
			break;
		case 2:
			printf("[浏览]\n");
			printList(list);
			break;
		case 3:
			printf("[借阅]\n"); 
			printf("请输入借阅的书名:");
			scanf("%s",tempBook.name);
			result=searchByName(list,tempBook.name);
			if(result==NULL) {
				printf("目前没有该书,敬请期待!");
			} else {
				if(result->data.num>0) {
					result->data.num--;
					printf("借阅成功!\n");
				} else {
					printf("当前书籍无库存,无法借阅");
				}
			}
			break;
		case 4:
			printf("[归还]\n"); 
			printf("请输入归还的书名:");
			scanf("%s",tempBook.name);
			result=searchByName(list,tempBook.name);
			if(result==NULL) {
				printf("该书不属于本馆!");
			} else {
				result->data.num++;
				printf("归还成功!\n");
			}
			break;
		case 5:
			printf("[排序]\n");
			BubbleSortList(list);
			break;
		case 6:
			printf("[删除]\n");
			printf("请输入要删除的书名:");
			scanf("%s",tempBook.name);
			deleteNodeByName(list,tempBook.name);
			//修改数据要同步到文件-> 保存到文件 -> 写文件
			saveInfoToFile("bookIbgo.txt",list);
			break;
		case 7:
			printf("[查找]\n");
			printf("请输入要查找的书名:");
			scanf("%s",tempBook.name);
			result = searchByName(list,tempBook.name);
			if(result==NULL) {
				printf("查无此寻!");
			} else {
				printf("书名\t价格\t数量\n");
				printf("%s\t%.1f\t%d\n",result->data.name,result->data.price,result->data.num);
			}
			break;
		default:
			printf("[Error! 请输入0~7之间的数字!]\n");
			break;
	}

}


int main() {

	list = createHead(); //链表初始化
	readInfoFromFile("bookinfo.txt",list);

	while(1) {
		makeMenu();
		keyDown();

		system("pause");
		system("cls");
	}

	system("pause");
	return 0;
}

8、学习笔记(含注释)

注释包含敲代码的过程以及简单的知识点记录。

#include<stdio.h>  //input and outut 
#include<stdlib.h>  //strings
#include<string.h>

//3.数据设计(C自定义链表) 
//3.1 先      程序用什么东西处理数据(数组、链表) ->用什么装数据
//3.2 在定义  数据结构

//3.3 另一部分 用户信息(未包含)  C++ 
//图书管理、登录模块(获取用户基本信息)、用户管理(文件操作) 
//#include<iostream>
//#include<list>
//using namespace std;
 
//struct student{
//	char sname[20];
//	char tel[20];
//	int num;
//	struct bookInfo userBook[3];
//};


//3.2图书信息  书名、价格、数量 -->修改节点data类型 and 打印 and 删除data类型
struct bookInfo {
	char name[20];
	float price;
	int num;
};

struct Node* list=NULL;//全局链表

//3.1 链表  =结构体变量
//创建链表:
struct Node {
	struct bookInfo data;
	struct Node *next;
};

// 创建表头;表头就是结构体变量
struct Node* createHead() {
	//内存动态申请
	struct Node* headNode=(struct Node*)malloc(sizeof(struct Node));
	//变量的基本规则:使用前初始化
	headNode->next=NULL;
	return headNode;
}

//创建节点(同创建表头):为插入做准备
//把用户的数据变为结构体变量
struct Node* createNode(struct bookInfo data) {
	struct Node* newNode=(struct Node*)malloc(sizeof(struct Node));
	newNode->data=data;
	newNode->next=NULL;
	return newNode;
}
//插入:表头插入  1.让newnext指向下一个next  2. 头haednext->newNode(新节点)
void insertNodeByHead(struct Node* headNode,struct bookInfo data) {
	struct Node* newNode=createNode(data);
	newNode->next=headNode->next;  //1
	headNode->next=newNode;        //2
}
//尾插pMove->next=NULL and oMove->next=newNode;
//void insertNodeByTail(struct Node* headNode,int data) {
//	struct Node* pMove= headNode;
//	while(pMove->next!=NULL) {
//		pMove=pMove->next;
//	}
//	struct Node* newNode=createNode(data);
//	pMove->next=newNode;
//}


//指定位置删除posleft->next=pos->next and free(pos) and pso=NULL
//书名删除->  字符串的删除,字符比较函数
void deleteNodeByName(struct Node* headNode,char *bookname) {
	struct Node* posLeftNode = headNode;
	struct Node* posNode=headNode->next;
	//当查找的数据不是要删除的数据
	while(posNode!=NULL && strcmp(posNode->data.name,bookname)) {
		posLeftNode=posNode;  //将左节点后移
		posNode=posLeftNode->next; //将当前节点后移
	}
	//讨论查找结果
	if(posNode==NULL)
		return;
	else {
		printf("删除成功!");
		posLeftNode->next=posNode->next;
		free(posNode);
		posNode=NULL;
	}
}

//6.函数类型:结构体指针 -> 查找  -> 链表的查找
//借阅和归还使用查找功能写
struct Node* searchByName(struct Node* headNode,char *bookname) {
	struct Node* posNode=headNode->next;
	//strcmp 0相等  >0前面的大  <0后面的大
	while(posNode!=NULL && strcmp(posNode->data.name,bookname)) {
		posNode = posNode->next;  //不相等
	}
	return posNode; //非空->找到了
}

//第一次的删除写法
//问题:找删除节点和删除前一个节点
//函数名的Data为一个结构体
//void deleteNodeByData(struct Node* headNode,struct bookInfo posData) {
//	struct Node* posLeftNode = headNode;
//	struct Node* posNode=headNode->next;
//	//当查找的数据不是要删除的数据
//	while(posNode!=NULL && posNode->data!=posData) {
//		posLeftNode=posNode;  //将左节点后移
//		posNode=posLeftNode->next; //将当前节点后移
//	}
//	//讨论查找结果
//	if(posNode==NULL)
//		return;
//	else {
//		posLeftNode->next=posNode->next;
//		free(posNode);
//		posNode=NULL;
//	}
//
//}


//打印链表:以当前节点为头节点的链表
void printList(struct Node* headNode) {
	struct Node* pMove=headNode->next;
	printf("书名\t价格\t数量\n");
	while(pMove!=NULL) {
		//剥洋葱方式显示
//		printf("%d\t",pMove->data);
		printf("%s\t%.1f\t%d\n",pMove->data.name, pMove->data.price, pMove->data.num);
		pMove=pMove->next;
	}
}


//1.make Menu-模块
void makeMenu() {
	printf("+---------------------------------+\n");
	printf("|     Books Management System     |\n");
	printf("+---------------------------------+\n");
	printf("0 退出系统\n");
	printf("1 登记书籍\n");  //添加
	printf("2 浏览书籍\n");  //显示
	printf("3 借阅书籍\n");  //修改
	printf("4 归还书籍\n");
	printf("5 书籍排序\n");
	printf("6 删除书籍\n");  //删除
	printf("7 查找书籍\n\n"); //查询
	printf("请选择(0~7):");
}

//4.文件操作-> 对 list
//const 定义常量,不允许被改变
//4.1 存(写)操作
void saveInfoToFile(const char* fileName, struct Node* headNode) {
	FILE *fp=fopen(fileName,"w"); //打开文件 只写
	//写操作-> 将链表的信息打印到文件中
	struct Node* pMove= headNode->next;
	while(pMove!=NULL) {
		fprintf(fp,"%s\t%.1f\t%d\n",pMove->data.name,pMove->data.price,pMove->data.num);
		pMove = pMove->next;
	}
	fclose(fp);  //关闭文件
}

//4.2 读操作
void readInfoFromFile(const char *fileName,struct Node* headNode) {
	FILE *fp=fopen(fileName,"r");  //只读
	if(fp==NULL) {
		//第一次打开 不存在就创建
		fp=fopen(fileName,"w+");
	}
	//把文件当输入  name数组名本身表示取地址符
	struct bookInfo tempData;
	while(fscanf(fp,"%s\t%f\t%d\n",tempData.name,&tempData.price,&tempData.num)!=EOF) {
		insertNodeByHead(list,tempData);  //读一个信息插入链表
	}
	fclose(fp);
}

//5.排序  冒泡->相邻的相比较
void BubbleSortList(struct Node* headNode) {
	struct Node* p;
	struct Node* q;

	for(p=headNode->next; p!=NULL; p=p->next) {
		for(q=headNode->next; q->next!=NULL; q=q->next) {
			//价格排序
			if(q->data.price > q->data.price) {

				struct bookInfo tempData=q->data;
				q->data=q->next->data;
				q->next->data=tempData;
			}
		}
	}
	printList(headNode);
}


//2.做交互-按键处理-跳转
void keyDown() {
	int userKey = 0;

	struct bookInfo tempBook; //产生临时的变量存储书籍信息
	struct Node* result =NULL; //临时指针->书籍查询结果

	scanf("%d",&userKey);
	switch(userKey) {
		case 0:
			printf("[退出成功]\n");
			exit(0);
			break;
		case 1:
			printf("[登记]\n");
			printf("请输入书籍信息:书名,价格,数量\n");
			//字符串不用&
			scanf("%s%f%d",tempBook.name, &tempBook.price, &tempBook.num);
			insertNodeByHead(list,tempBook);
			saveInfoToFile("bookInfo.txt",list);
			break;
		case 2:
			printf("[浏览]\n");
			printList(list);
			break;
		case 3:
			printf("[借阅]\n"); //书籍存在可借阅,数量-1;不存在,节约失败
			printf("请输入借阅的书名:");
			scanf("%s",tempBook.name);
			result=searchByName(list,tempBook.name);
			if(result==NULL) {
				printf("目前没有该书,敬请期待!");
			} else {
				if(result->data.num>0) {
					result->data.num--;
					printf("借阅成功!\n");
				} else {
					printf("当前书籍无库存,无法借阅");
				}
			}
			break;
		case 4:
			printf("[归还]\n"); //书籍数量+1
			printf("请输入归还的书名:");
			scanf("%s",tempBook.name);
			result=searchByName(list,tempBook.name);
			if(result==NULL) {
				printf("该书不属于本馆!");
			} else {
				result->data.num++;
				printf("归还成功!\n");
			}
			break;
		case 5:
			printf("[排序]\n");
			BubbleSortList(list);
			break;
		case 6:
			printf("[删除]\n");
			printf("请输入要删除的书名:");
			scanf("%s",tempBook.name);
			deleteNodeByName(list,tempBook.name);
			//修改数据要同步到文件-> 保存到文件 -> 写文件
			saveInfoToFile("bookIbgo.txt",list);
			break;
		case 7:
			printf("[查找]\n");
			printf("请输入要查找的书名:");
			scanf("%s",tempBook.name);
			result = searchByName(list,tempBook.name);
			if(result==NULL) {
				printf("查无此寻!");
			} else {
				printf("书名\t价格\t数量\n");
				printf("%s\t%.1f\t%d\n",result->data.name,result->data.price,result->data.num);
			}
			break;
		default:
			printf("[Error! 请输入0~7之间的数字!]\n");
			break;
	}

}


int main() {

	//测试链表
//	struct Node* list=creatHead();
//	int i;
//	for(i=0; i<3; i++) {
//		insertNodeByHead(list,i);  //前插
		insertNodeByTail(list,i);  //尾插
//	}
	deleteNodeByData(list,1);      //删除
//	printList(list);

	list = createHead(); //链表初始化
	readInfoFromFile("bookinfo.txt",list);

	while(1) {
		makeMenu();
		keyDown();

		system("pause");
		system("cls");
	}

	system("pause");
	return 0;
}

参考:

感谢大佬的细心录制!!!真的很清楚明白!

C/C++知识项目教程:图书管理系统!手把手教你写出大学C语言图书管理系统,简单易上手,大学C语言必会!_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值