0
点赞
收藏
分享

微信扫一扫

数据库系统 图书管理系统 C语言

浮游图灵 2022-05-01 阅读 95

浙江大学实验报告

1. 实验目的和要求

  1. 设计并实现一个精简的图书管理系统,要求具有图书入库、查询、借书、还书、借书证管理等功能。
  2. 通过该图书馆系统的设计与实现,提高学生的系统编程能力,加深对数据库系统原理及应用的理解。

2. 实验内容和原理

  1. 自行设计数据库系统结构以完成相关需求。
  2. 使用C语言编码和mysql.h头文件函数。

3. 主要仪器设备

安装有MySQL和Visual Studio的电脑。

4. 操作方法和实验步骤

4.1 总体设计

image-20220419143120954

4.1.1 系统架构

  1. 在数据库中规定过的管理员们可以对book,borrow,card三个表进行增删改查操作。
  2. 其余用户(无论是否有借书证)都可以查询图书馆里的书目藏书情况。其中可以进行复合多条件查询,并且自定义排序方式。

4.1.2 表结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0c7lzbBt-1651337582552)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419141307.png)]

根据需求创建表结构:

CREATE TABLE book (
	bno INT PRIMARY KEY,
	category CHAR ( 10 ),
	title VARCHAR ( 40 ),
	press VARCHAR ( 40 ),
	YEAR INT,
	author VARCHAR ( 20 ),
	price DECIMAL ( 7, 2 ),
	total INT CHECK ( total > 0 ),
	stock INT CHECK ( stock >= 0 ) 
);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a64LluOx-1651337582552)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419141652.png)]

CREATE TABLE borrow ( 
cno CHAR ( 7 ) PRIMARY KEY, 
bno INT, borrow_date date, 
return_date date, 
sa INT );

image-20220419141829467

CREATE TABLE card (
	cno CHAR ( 7 ) PRIMARY KEY,
	NAME VARCHAR ( 10 ),
	department VARCHAR ( 40 ),
type CHAR ( 1 ) CHECK ( type = 'U' OR type = 'T' OR type = 'G' OR type = 'O' ) 
);

image-20220419142101351

CREATE TABLE sa ( 
id INT, 
pas VARCHAR ( 30 ), 
NAME VARCHAR ( 30 ), 
telephone VARCHAR ( 11 ) 
);

image-20220419142253025

4.2 详细设计

4.2.1 使用开发平台

Visual Studio 2022以及MySQL.

配置环境过程:

  1. 下载并安装MySQL。

  2. 下载并安装Navicat Premium使SQL可视化更方便。

  3. 将VS和MySQL进行连接,步骤如下:

    1. 打开项目属性

      image-20220419143933932
    2. C/C++—常规—附加包含目录—添加MySQL include路径

      image-20220419144117372

    3. 连接器—常规—附加库目录—添加lib路径

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wldvMbOl-1651337582554)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419144223.png)]

    4. 链接器—输入—附加依赖项—添加libmysql.lib

      image-20220419144321451

    5. 后续在代码中添加#include "mysql.h"即可使用MySQL库。

4.2.2 mysql.h中的库函数

mysql_init

获得或初始化一个MYSQL结构。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0ygi2ty-1651337582555)(C:/Users/86186/AppData/Roaming/Typora/typora-user-images/image-20220419145951845.png)]

mysql_real_connect

连接一个MySQL服务器。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N9jf8q9m-1651337582555)(C:/Users/86186/AppData/Roaming/Typora/typora-user-images/image-20220419150049100.png)]

mysql_query

执行指定为一个空结尾的字符串的SQL查询。

后续的每一个具体模块都是通过此函数在MySQL中执行语句,需要实现的就是创建MySQL语句字符串即可,需要注意字符串结尾不是;而是\0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3mea11O-1651337582555)(C:/Users/86186/AppData/Roaming/Typora/typora-user-images/image-20220419150203987.png)]

mysql_store_result

检索一个完整的结果集合给客户。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gDTPT56u-1651337582556)(C:/Users/86186/AppData/Roaming/Typora/typora-user-images/image-20220419150249685.png)]

mysql_query(&mysql, "set names gbk")

防止中文查询结果乱码。

mysql_query(&mysql, "SET CHARACTER SET GBK")

保证插入成功。

4.2.3 连接数据库

bool ConnectDatabase() 函数

设置好相关信息,直接连接数据库。

bool ConnectDatabase() {
	mysql_init(&mysql);
	const char host[] = "localhost";//在本地创建的数据库
	const char table[] = "library";//数据库的名称
	const char user[] = "root";//设置的登录用户名
	const char psw[] = "111111";//设置的登录密码
	const int port = 3306;//端口
    
    //使用库函数mysql_real_connect进行数据库连接
	if (!(mysql_real_connect(&mysql, host, user, psw, table, port, NULL, 0))) {
		printf("连接失败!!\n");
		return false;
	}
	else {
		printf("成功连接~\n");
		return true;
	}
}

4.2.4 管理员登录

void login() 函数

如果成功登录管理员,则返回true;如果是普通用户,则返回false。

bool login() {
	int choice;
	choice = 0;
	do {
		printf("请选择登录模式:1 普通用户  2 管理员 -1 退出\n");
		scanf("%d", &choice);
		if (choice == 1) {
			return false;
		}
		else if (choice == 2) {
			char pass[30];
			printf("请输入编号:");
			scanf("%s", &user);
			printf("请输入密码:");
			scanf("%s", &pass);
			strcpy(query, "select * from sa where id = ");
			strcat(query, user);
			strcat(query, " and pas = '");
			strcat(query, pass);
			strcat(query, "'");
			mysql_query(&mysql, "set names gbk");
			mysql_query(&mysql, query);
			char* str_field[32];  //定义一个字符串数组存储字段信息
			res = mysql_store_result(&mysql);
			for (int i = 0; i < 4; i++)   //在已知字段数量的情况下获取字段名 
			{
				str_field[i] = mysql_fetch_field(res)->name;	//返回一个所有字段结构的数组。
			}
			//打印获取的数据  
			column = mysql_fetch_row(res);  //在已知字段数量情况下,获取并打印下一行  
			if (column==nullptr) {
				printf("请检查输入的账号密码或重新选择登录模式!!\n");
				continue;
			}
			else {
				printf("登陆成功~\n");
				return true;
			}
		}
	} while (choice != -1);
}

4.2.5 图书入库

void insertbook 函数
void insertbook() {
	int num;
	printf("请输入你要插入的书的个数:");
	scanf("%d", &num);
	char query[1000];
	char values[100];
	getchar();
	int i;
	for (i = 0; i < num; i++) {
		gets_s(values);
		mysql_query(&mysql, "SET CHARACTER SET GBK");
		strcpy(query, "INSERT INTO book values");
		strcat(query, values);
		if (mysql_query(&mysql, query)) {
			printf("插入成功!\n");
		}
		else {
			printf("第%d条数据插入失败,请检查。\n", i + 1);
		}
	}
}
MySQL语句格式
INSERT INTO book values(....)

4.2.6 图书查询

findbook函数(支持复合查询)
MySQL语句格式
SELECT * FROM book where (条件) order by () asc/desc #升序/降序

4.2.7 借书

borrowbook函数
void borrowbook() {
    //输入借书证号返回所有已借的书
	printf("请输入借书证号:");
	char num[20];
	scanf("%s", &num);
	strcpy(query, "select * from card cno = '");
	strcat(query, num);
	strcat(query, "'");
	mysql_query(&mysql, "set names gbk");
	mysql_query(&mysql, query);
	if (!(res = mysql_store_result(&mysql)))    //获得sql语句结束后返回的结果集  
	{
		printf("请输入正确的结束证号!\n");
	}
	strcpy(query, "select * from borrow where borrow_date is not null and return_date is null and cno = '");
	strcat(query, num);
	strcat(query, " ' ");
	mysql_query(&mysql, "set names gbk");
	mysql_query(&mysql, query);
	if (!(res = mysql_store_result(&mysql)))    //获得sql语句结束后返回的结果集  
	{
		printf("该用户没有未还的书\n");
	}
	else {
		char* str_field[32];  //定义一个字符串数组存储字段信息
		for (int i = 0; i < 5; i++)   //在已知字段数量的情况下获取字段名 
		{
			str_field[i] = mysql_fetch_field(res)->name;	//返回一个所有字段结构的数组。
		}
		for (int i = 0; i < 5; i++)   //打印字段  
			printf("%15s", str_field[i]);
		printf("\n");
		//打印获取的数据  
		while (column = mysql_fetch_row(res))   //在已知字段数量情况下,获取并打印下一行  
		{
			printf("%15s%15s%15s%15s%15s\n", column[0], column[1], column[2], column[3], column[4]);  //column是列数组  
		}
	}
	printf("请输入要借的书的个数:");
	int book_num;
	scanf("%d", &book_num);
	int j;
	for (j = 0; j < book_num; j++) {
		printf("请输入需要借的书的书号:");
		char bno[12];
		scanf("%s", &bno);
		strcpy(query, "insert into borrow(cno,bno,borrow_date,sa) values (");
		strcat(query, num);
		strcat(query, ",");
		strcat(query, bno);
		strcat(query, ",now(),");
		strcat(query, user);
		mysql_query(&mysql, "SET CHARACTER SET GBK");
		if (mysql_query(&mysql, query)) {
			printf("借书成功\n");
		}
		else {
			printf("借书失败,库存不足\n");
		}
	}
	return;
}
MySQL语句格式
SELECT * FROM book where cno = in.cno
INSERT INTO borrow (cno,bno,borrow_date,sa) values(in.cno,in.bno,now(),sa)
#cno和bno需要手动输入 now()函数实现date类型的自动插入
#borrow后面的括号不写return_date使其默认为null
#sa是全局变量,为在login函数登陆时输入的id
余量为0不能再借 编写触发器
CREATE TRIGGER update_stock BEFORE INSERT ON borrow FOR EACH ROW
BEGIN
		UPDATE book 
		SET stock = stock - 1 
	WHERE
		bno = new.bno;

END

当余量为0时,本触发器要更新的余量会变成-1,违反了在建表时的约束(stock>=0),触发器执行失败,返回错误,因此借书的插入函数不能执行,实现余量为0不能借书的功能。

4.2.8 还书

returnbook函数
MySQL语句格式
UPDATE borrow SET return_date = now() where bno = in.bno and cno = in.cnp
还书后更新余量 编写触发器
CREATE TRIGGER add_stock AFTER UPDATE ON borrow FOR EACH ROW
BEGIN
		UPDATE book 
		SET stock = stock + 1 
	WHERE
	bno = old.bno and old.return_date is null and new.return_date is not null;
END

4.2.9 借书证管理

managecard函数
void managecard() {
	printf("您要增加还是删除一个借书证?\n");
	printf("1 增加    2 删除\n");
	int choice;
	scanf("%d", &choice);
	if (choice == 1) {
		char cno[12];
		char name[30];
		char department[30];
		char type[2];
		bool flag;
		flag = false;
		do {
			printf("请输入新建的借书证号:");
			scanf("%s", &cno);
			strcpy(query, "select * from card where cno = '");
			strcat(query, cno);
			strcat(query, "'");
			mysql_query(&mysql, "SET CHARACTER SET GBK");
			mysql_query(&mysql, query);
			if (!(res = mysql_store_result(&mysql)))    //获得sql语句结束后返回的结果集  
			{
				printf("借书证号已被占用!请重新输入!\n");
			}
			else flag = true;
		} while (flag == false);
		printf("请输入姓名:");
		scanf("%s", &name);
		printf("请输入学院:");
		scanf("%s", &department);
		printf("请输入卡的种类:");
		scanf("%s", &type);
		strcpy(query, "INSERT into card values ('");
		strcat(query, cno);
		strcat(query,"','");
		strcat(query, name);
		strcat(query,"','");
		strcat(query, department);
		strcat(query, "','");
		strcat(query, type);
		strcat(query, "')");
		mysql_query(&mysql, "SET CHARACTER SET GBK");
		if (mysql_query(&mysql, query)) {
			printf("建卡成功!\n");
		}
		else {
			printf("建卡失败\n");
		}
	}
	else if (choice == 2) {
		printf("请输入要删除的借书证号:");
		char cno[10];
		scanf("%s", &cno);
		strcpy(query, "select * from borrow where return_date is null and cno = '");
		strcat(query, cno);
		strcat(query, "'");
		mysql_query(&mysql, "SET CHARACTER SET GBK");
		if (mysql_query(&mysql, query)) {
			//删除
			printf("删除成功\n");
		}
		else {
			printf("该借书证还有未还的书!!删除失败\n");
		}
	}
}
MySQL语句格式
INSERT INTO card values(....)
DELETE FROM card where cno = in.cno

5.实验结果与分析

5.1 管理员登录

image-20220419155331790

当账号密码不对时无法成功登录。

5.2 图书入库

只能在第二次插入的时候才成功插入(目前没找到原因qaq)

5.2.1 单本入库

(100,'摄影','影视镜头创作','中国友谊出版社',2019,'刘永思',128.00,1,1)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAT3MPAB-1651337582557)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419165654.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AwEZWSP3-1651337582557)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419165652.png)]

5.2.2 批量入库

(1,'摄影','绘画、摄影、电影','华中科技大学出版社',2021,'拉兹洛·莫霍利-纳吉',49.80,1,1)
(2,'摄影','新视觉 : 从材料到建筑','重庆大学出版社',2020,'拉兹洛·莫霍利-纳吉',38.00,2,2)
(3,'摄影','森山大道','北京美术摄影出版社',2017,'森山大道',98.00,2,2)
(4,'摄影','电视摄像','上海交通大学出版社',2018,'滕方',56.00,1,1)
(5,'摄影','拍出电影感','九州出版社',2021,'屠明非',180.00,1,1)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qx48txN4-1651337582557)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419165648.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kSnbtTxF-1651337582558)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419155810.png)]

5.3 图书查询

5.3.1 单一条件查询

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U3Up88HQ-1651337582558)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419160219.png)]

5.3.2 复合查询

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWByYR1n-1651337582558)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419160355.png)]

5.3 借书

image-20220419165300580

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9AbSOLSQ-1651337582559)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419171622.png)]

image-20220419171639265

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CPN6MdCr-1651337582559)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419171658.png)]

5.4 还书

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qYxIapWV-1651337582559)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419171934.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y419iYnC-1651337582560)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419171958.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qE7gvYTd-1651337582560)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419172027.png)]

5.5 借书证管理

5.5.1 创建

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x7YgRJso-1651337582560)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419174053.png)]

image-20220419174107379

5.5.2 删除

image-20220419174138206

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XA5Fcm7W-1651337582561)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419174157.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W1IFzU5X-1651337582561)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419174216.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CR3K8Tf6-1651337582562)(https://raw.githubusercontent.com/hinsew/photo/master/img/20220419174235.png)]

6. 讨论心得

  • 善于利用已存在的库。
  • 已使用函数连接则不需要再视图里进行设置。
  • mysql_query执行成功返回0.
  • 查找queryNULL值也算作有返回。
  • 文件读写乱码修改txt编码模式。

附录

  • 下载并安装MySQL和Navicat Premium参考[(26条消息) 新人向]MySQL和Navicat下载、安装及使用详细教程_向王同学敬礼的博客-CSDN博客_navicat下载安装以及配置
  • 设置和连接VS和MySQL参考(26条消息) VS2017连接MYSQL 8.0(小白必看!)_v寰宇的博客-CSDN博客_vs连接mysql数据库
  • mysql.h库函数参考(26条消息) C++ 连接数据库代码_Mr.禾的博客-CSDN博客_c++链接数据库
  • mysql_query插入语句不成功解决办法参考mysql_query()插入不了数据解决方案 - 云+社区 - 腾讯云 (tencent.com)
    ium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-82824693.142v9pc_search_result_cache,157v4control&utm_term=vs连接mysql数据库&spm=1018.2226.3001.4187)
  • mysql.h库函数参考(26条消息) C++ 连接数据库代码_Mr.禾的博客-CSDN博客_c++链接数据库
  • mysql_query插入语句不成功解决办法参考mysql_query()插入不了数据解决方案 - 云+社区 - 腾讯云 (tencent.com)
举报

相关推荐

0 条评论