【MySQL】数据库-图书管理系统(CC++实现)
一.预期功能
该图书管理系统设计提供基本的设计模版,涉及数据库的增删查改等操作,包含登录功能,图书管理功能,图书借阅功能,用户管理功能等基础功能,详细功能查看以下菜单表,共包含三个菜单,登录菜单,管理员菜单和用户菜单。
void Menu()
{printf("***************************************
");printf("* 欢迎进入线上图书管理系统! *
");printf("* *
");printf("* 1.管理员登录 *
");printf("* 2.读者登录 *
");printf("* 3.读者注册 *
");printf("* 0.退出本系统 *
");printf("***************************************
");
}
void manager_Menu()
{printf("***************************************
");printf("* 欢迎你,管理员
");printf("*
");printf("* 1.添加书籍
");printf("* 2.显示书籍
");printf("* 3.查找书籍
");printf("* 4.修改书籍
");printf("* 5.显示用户数据
");printf("* 6.返回主菜单
");printf("* 7.添加新管理员
");printf("* 0.退出本系统
");printf("***************************************
");
}
void reader_Menu(user* head)
{printf("***************************************
");printf("* 欢迎你,读者
");printf("*
");printf("* 1.借阅书籍
");printf("* 2.归还书籍
");printf("* 3.修改密码
");printf("* 4.返回主菜单
");printf("* 0.退出本系统
");printf("*
");printf("***************************************
");
}
二.建表
1.管理员表(manager)
列名
数据类型
约束
说明
M_ID
INT
PRIMARY KEY
管理员ID编号
M_Account
VARCHAR(30)
NOT NULL
管理员账号
M-Password
VARCHAR(30)
NOT NULL
密码
2.图书信息表(book)
列名
数据类型
约束
说明
B_ID
INT
PRIMARY KEY
图书ID编号
B_Name
VARCHAR(30)
NOT NULL
图书名称
Author
VARCHAR(30)
NOT NULL
作者
Publish
VARCHAR(30)
NOT NULL
出版社名称
Price
DECIMAL(10,2)
NOT NULL
价格
Quantity
INT
DEFAULT 0
库存量
3.用户表(user)
列名
数据类型
约束
说明
U_ID
INT
PRIMARY KEY
用户ID编号
U_Account
VARCHAR(30)
NOT NULL
用户账号
U_Password
VARCHAR(30)
NOT NULL
密码
4.借书表(borrow_book)
列名
数据类型
约束
说明
U_ID
INT
FOREIGN KEY
用户ID编号
B_ID
INT
FOREIGN KEY
图书ID编号
Borrow_time
VARCHAR(30)
NOT NULL
借阅时间
Return_time
VARCHAR(30)
NOT NULL
归还时间
State
VARCHAR(30)
NOT NULL
状态
备注1:登录功能使用管理员账号/用户账号+密码进行登录,在这里省略了管理员/用户昵称。
备注2:价格DECIMAL对应VS中的float(浮点型)进行转化。
备注3:时间可以使用Date类型,但为了方便在VS中添加到数据库使用varchar类型,在VS上将当前时间转化为字符串进行添加。
备注4:借书表中U_ID和B_ID共同构成主码。
附上MySQL建表,数据插入代码:
CREATE TABLE manager(
M_ID INT PRIMARY KEY,
M_Account VARCHAR(30) NOT NULL,
M_Password VARCHAR(30) NOT NULL
);CREATE TABLE book(
B_ID INT PRIMARY KEY,
B_NAME VARCHAR(30) NOT NULL,
Author VARCHAR(30) NOT NULL,
Publish VARCHAR(30) NOT NULL,
Price DECIMAL(10,2) NOT NULL,
Quantity INT DEFAULT 0
);CREATE TABLE user(
U_ID INT PRIMARY KEY,
U_Account VARCHAR(30) NOT NULL,
U_Password VARCHAR(30) NOT NULL
);CREATE TABLE borrow_book(
U_ID INT NOT NULL,
B_ID INT NOT NULL,
Borrow_time VARCHAR(30) NOT NULL,
Return_time VARCHAR(30),
State VARCHAR(30),
PRIMARY KEY (U_ID,B_ID),
FOREIGN KEY(U_ID) REFERENCES user(U_ID) ON DELETE CASCADE,
FOREIGN KEY(B_ID) REFERENCES book(B_ID) ON DELETE CASCADE
);-- 管理员表数据
INSERT INTO manager (M_ID, M_Account, M_Password) VALUES
(3, 'alice_admin', 'alice123'),
(4, 'bob_admin', 'bob123'),
(5, 'charlie_admin', 'charlie123');-- 书籍表数据
INSERT INTO book (B_ID, B_NAME, Author, Publish, Price, Quantity) VALUES
(101, '百年孤独', '加布里埃尔·加西亚·马尔克斯', '南海出版公司', 59.90, 20),
(102, '追风筝的人', '卡勒德·胡赛尼', '上海人民出版社', 39.50, 15),
(103, '解忧杂货店', '东野圭吾', '南海出版公司', 39.00, 30),
(104, '活着', '余华', '北京十月文艺出版社', 35.00, 25),
(105, '哈利·波特与魔法石', 'J.K.罗琳', '人民文学出版社', 69.00, 50);-- 用户表数据
INSERT INTO user (U_ID, U_Account, U_Password) VALUES
(201, 'diana_user', 'diana123'),
(202, 'eric_user', 'eric123'),
(203, 'fiona_user', 'fiona123'),
(204, 'george_user', 'george123'),
(205, 'hannah_user', 'hannah123');-- 借阅记录表数据
INSERT INTO borrow_book (U_ID, B_ID, Borrow_time, Return_time, State) VALUES
(201, 101, '2024-06-01', '2024-06-15', 'RETURNED'),
(202, 102, '2024-06-02', NULL, 'BORROWED'),
(203, 103, '2024-06-03', '2024-06-10', 'RETURNED'),
(204, 104, '2024-06-04', NULL, 'BORROWED'),
(205, 105, '2024-06-05', '2024-06-20', 'RETURNED'),
(201, 105, '2024-06-21', NULL, 'BORROWED');
三.环境配置
声明:本文使用Visual studio2022 编写,其他编译器可自行考量,下面进行环境配置。
首先,找到项目的属性页面,找到C/C++,在常规的附加包含目录中选中安装的MySQL文件中的Include文件
然后在连接器的常规中,找到附加库目录,选中mysql文件中的lib文件
在链接器的输入中,选择附加依赖项,手动输入libmysql.lib
最后一步,将MySQL文件lib文件中的libmysql.dll复制到项目的x64目录下。
这样环境就配置好了。
四.数据库连接
这是链接数据库和编译器的起点,系统整体的功能都在这个实现内部,注意设置字符编码,否则可能会出现乱码。
//初始化
MYSQL* con = mysql_init(NULL);//设置字符编码,以防出现乱码
mysql_options(con, MYSQL_SET_CHARSET_NAME, "GBK");//开始连接
if (!mysql_real_connect(con, host, use, password, database_name, port, NULL, 0))
{fprintf(stderr, "connect fail", mysql_error(con));return -1;
}//关闭连接
mysql_close(con);
五.添加、删除信息
在编译器中定义表格数据对应的结构体,在编译器中输入的数据存入结构体链表中,在通过sprintf将对应的MySQL插入/删除语句输出执行。本系统在VS上使用结构体链表储存对应表格的所有数据,因此设置三个链表的头指针:book_head,user_head,manager_head,初始化为NULL
//结构体定义
typedef struct manager_table
{int M_ID;char M_Account[30];char M_Password[30];struct manager_table* next;
}manager;typedef struct book_table
{int B_ID;char B_NAME[30];char Author[30];char Publish[30];float Price;int Quantity;struct book_table* next;
}book;typedef struct user_table
{int U_ID;char U_Account[30];char U_Password[30];struct user_table* next;
}user;//链表头节点指针book* book_head = NULL;user* user_head = NULL;manager* manager_head = NULL;
添加新书籍首先找到链表的尾部,创建新节点,将书籍信息输入,随后将mysql语句存入字符数组sql中,使用mysql_query即可。当然在编号输入中可以添加重复检查等功能,实现就是链表的遍历,在此不进行实现该功能。书籍添加实现,其余管理员添加,用户添加也是同理。
book* Add_new_book(book* head, MYSQL* mysql)
{book* newbook = (book*)malloc(sizeof(book));if (newbook == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = newbook;}else{//找到尾节点book* pcur = head;while (pcur->next){pcur = pcur->next;}pcur->next = newbook;}printf("请输入书籍编号:");scanf("%d", &(newbook->B_ID));//检测编号重复(未实现)printf("请输入名称:");scanf("%s", newbook->B_NAME);printf("请输入作者:");scanf("%s", newbook->Author);printf("请输入出版社:");scanf("%s", newbook->Publish);printf("请输入价格:");scanf("%f", &(newbook->Price));printf("请输入库存量:");scanf("%d", &(newbook->Quantity));//将新增书籍信息存入数据库char sql[256];sprintf(sql, "insert into book values('%d','%s','%s','%s','%f','%d')",newbook->B_ID, newbook->B_NAME, newbook->Author, newbook->Publish, newbook->Price, newbook->Quantity);mysql_query(mysql, sql);newbook->next = NULL;printf("添加成功!
");return head;
}
删除书籍需要进行以下两步:找到对应编号的节点,然后释放该节点。防止删除错误,加入了删除时显示书籍信息并且进行二次确认功能。
//删除书籍信息
book* Delete_Book(book* head, MYSQL* mysql)
{book* p = head;book* pcur = NULL;int id, option;char sql[256];printf("请输入删除书籍的编号:");scanf("%d", &id);while (p){if (id == p->B_ID){break;}pcur = p;p = p->next;}if (p == NULL){printf("未找到此ID编号的书籍
");return 0;}else{printf("===================================================================================
");printf("|书名 |作者 |出版社 |价格 |库存 |编号 |
");printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);printf("===================================================================================
");printf("================
");printf("|是否确定删除?|
");printf("|0.取消 1.确定|
");printf("================
");scanf("%d", &option);switch (option){case 1:sprintf(sql, "delete from book where B_ID = %d;", id);mysql_query(mysql, sql);if (p == head){head = head->next;free(p);}else{pcur->next = p->next;free(p);}printf("已成功删除
");option = 0;break;case 0:printf("取消删除
");break;default:printf("输入错误
");break;}}return head;
}
六.加载数据库信息
在加载数据库的信息前需要定义res 和 row来查询结果集和记录结构体,随后将获得的结果插入进链表,将数据库的内容拷贝到编译器的链表中。
MYSQL_RES* res = NULL;//查询结果集
MYSQL_ROW row = NULL;//记录结构体//从数据库中加载书籍信息
book* load_Book(book* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql)
{book* p = NULL;book* pcur = head;//查询数据mysql_query(mysql, "select * from book;");//获取结果集res = mysql_store_result(mysql);//将值赋为链表while (row = mysql_fetch_row(res)){p = NULL, pcur = head;p = (book*)malloc(sizeof(book));if (p == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = p;}else{while (pcur->next != NULL){pcur = pcur->next;}pcur->next = p;}p->B_ID = atoi(row[0]);strcpy(p->B_NAME, row[1]);strcpy(p->Author, row[2]);strcpy(p->Publish, row[3]);p->Price = atoi(row[4]);p->Quantity = atoi(row[5]);p->next = NULL;}//释放结果集mysql_free_result(res);return head;
}
七.查找与登录
使用者输入账号存入account数组,遍历链表使用strcmp进行比较,匹配成功后再输入密码进行对比,密码有可能输入错误,设置循环再次尝试。
manager* manager_Login(manager* head)
{manager* p = head;char account[30], password[30];printf("请输入账号:");scanf("%s", account);while (p != NULL){if (!strcmp(account, p->M_Account)){break;}p = p->next;}if (p == NULL){printf("没有查找到该账号!
");return NULL;}else{while (1){printf("请输入密码:");scanf("%s", password);if (strcmp(password, p->M_Password) == 0){printf("成功登录!
");break;}else {printf("密码错误!请重新输入!
");}}}return p;
}
八.借阅与归还
借阅归还中与前面不同的就在于时间,在VS中得到当前日期的字符数组,可以这样实现:
#include<time.h>time_t rawtime;
struct tm* timeinfo;
char date_str[11]; // 足够存储 "YYYY-MM-DD" 格式的日期字符串// 获取当前时间的时间戳
time(&rawtime);// 将时间戳转换为本地时间
timeinfo = localtime(&rawtime);// 使用sprintf将年、月、日格式化为字符串
// 注意:tm_year是从1900年开始的,所以需要+1900
// tm_mon是从0开始的,所以需要+1
sprintf(date_str, "%d-%02d-%02d",timeinfo->tm_year + 1900,timeinfo->tm_mon + 1,timeinfo->tm_mday);
因此在借阅时,填入借阅时间,并将状态改为“BORROWED”,在归还时填入归还时间,并将状态改为“RETURNED”即可。
//借阅图书
int borrow_book(int id, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql, book* head)
{Show_remaining_book(res, row, mysql);char sql[256];int b_id;book* p = head;printf("请输入要借阅的书籍编号:");scanf("%d", &b_id);while (head != NULL){if (b_id == p->B_ID){sprintf_s(sql, sizeof(sql), "select * from book where B_ID = %d;", b_id);mysql_query(mysql, sql);res = mysql_store_result(mysql);row = mysql_fetch_row(res);if (atoi(row[5]) <= 0){printf("库存量不足!
");return 0;}else{time_t rawtime;struct tm* timeinfo;char date_str[11]; // 足够存储 "YYYY-MM-DD" 格式的日期字符串// 获取当前时间的时间戳time(&rawtime);// 将时间戳转换为本地时间timeinfo = localtime(&rawtime);// 使用sprintf将年、月、日格式化为字符串// 注意:tm_year是从1900年开始的,所以需要+1900// tm_mon是从0开始的,所以需要+1sprintf(date_str, "%d-%02d-%02d",timeinfo->tm_year + 1900,timeinfo->tm_mon + 1,timeinfo->tm_mday);sprintf(sql, "insert into borrow_book values (%d,%d,'%s','%s','%s');", id, b_id, date_str, "NULL", "BORROWED");mysql_query(mysql, sql);sprintf(sql, "update book set Quantity = Quantity - 1 where B_ID = %d;", b_id);mysql_query(mysql, sql);printf("借阅成功!
");return 0;}}p = p->next;}if (p == NULL) {printf("图书编号不存在
");}return 0;
}
//归还图书
int return_book(int id, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql, book* head)
{int b_id;book* p = head;char sql[256];printf("请输入要归还的书籍编号:");scanf("%d", &b_id);while (p != NULL){if (b_id == p->B_ID){time_t rawtime;struct tm* timeinfo;char date_str[11];time(&rawtime);timeinfo = localtime(&rawtime);sprintf(date_str, "%d-%02d-%02d",timeinfo->tm_year + 1900,timeinfo->tm_mon + 1,timeinfo->tm_mday);sprintf(sql, "update book set Quantity = Quantity + 1 where B_ID = %d;", p->B_ID);mysql_query(mysql, sql);sprintf(sql, "update borrow_book set Return_time = '%s', State = '%s' where U_ID = %d AND B_ID = %d;", date_str, "RETURNED", id, p->B_ID);mysql_query(mysql, sql);printf("归还成功!
");break;}p = p->next;}if (p == NULL) {printf("不存在该借出的图书!
");}return 0;
}
九.完整代码
备注:如果是C++要进行封装,可以建立对象book、manager、user等类,放入对应的结构体和函数方法即可实现,以下代码是按照C语言编写。
头文件:Library.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<mysql.h>
#include<time.h>//结构体定义
typedef struct manager_table
{int M_ID;char M_Account[30];char M_Password[30];struct manager_table* next;
}manager;typedef struct book_table
{int B_ID;char B_NAME[30];char Author[30];char Publish[30];float Price;int Quantity;struct book_table* next;
}book;typedef struct user_table
{int U_ID;char U_Account[30];char U_Password[30];struct user_table* next;
}user;//函数定义//展示菜单
void Menu();
void manager_Menu();
void reader_Menu(user* head);
void show_Menu_user(user* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql);//从数据库中加载书籍信息
book* load_Book(book* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql);//添加新管理员
manager* Add_new_manager(manager* head, MYSQL* mysql);
//添加新借书记录
//borrow_book* Add_new_borrow(borrow_book* head, MYSQL* mysql);//从数据库中加载书籍信息
book* load_Book(book* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql);
//从数据库中加载借阅信息//添加新书籍
book* Add_new_book(book* head, MYSQL* mysql);
//展示书籍信息
void Show_All_book(book* head);
//查找书籍信息
void Search_book(book* head);
//删除书籍信息
book* Delete_Book(book* head, MYSQL* mysql);
//修改书籍信息
book* Change_book(book* head, MYSQL* mysql);//添加新用户
user* Add_new_user(user* head, MYSQL* mysql);
//展示所有的用户信息
void Show_All_user(user* head);
//从数据库中加载用户信息
user* load_User(user* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql);
//从数据库中加载管理员信息
user* load_Manager(user* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql);
//修改用户密码
int Change_User_password(user* head, MYSQL* mysql);
//用户登陆
user* user_Login(user* head);
//管理员登录
manager* manager_Login(manager* head);//显示有库存的书籍
void Show_remaining_book(MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql);
//借阅图书
int borrow_book(int id, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql, book* head);
//归还图书
int return_book(int id, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql, book* head);
源文件:Library.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Library.h"//初始菜单
void Menu()
{printf("***************************************
");printf("* 欢迎进入线上图书管理系统! *
");printf("* *
");printf("* 1.管理员登录 *
");printf("* 2.读者登录 *
");printf("* 3.读者注册 *
");printf("* 0.退出本系统 *
");printf("***************************************
");
}
void manager_Menu()
{printf("***************************************
");printf("* 欢迎你,管理员
");printf("*
");printf("* 1.添加书籍
");printf("* 2.显示书籍
");printf("* 3.查找书籍
");printf("* 4.修改书籍
");printf("* 5.删除书籍
");printf("* 6.显示用户数据
");printf("* 7.返回主菜单
");printf("* 8.添加新管理员
");printf("* 0.退出本系统
");printf("***************************************
");
}
void reader_Menu(user* head)
{printf("***************************************
");printf("* 欢迎你,读者
");printf("*
");printf("* 1.借阅书籍
");printf("* 2.归还书籍
");printf("* 3.修改密码
");printf("* 4.返回主菜单
");printf("* 0.退出本系统
");printf("*
");printf("***************************************
");
}//从数据库中加载书籍信息
book* load_Book(book* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql)
{book* p = NULL;book* pcur = head;//查询数据mysql_query(mysql, "select * from book;");//获取结果集res = mysql_store_result(mysql);//将值赋为链表while (row = mysql_fetch_row(res)){p = NULL, pcur = head;p = (book*)malloc(sizeof(book));if (p == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = p;}else{while (pcur->next != NULL){pcur = pcur->next;}pcur->next = p;}p->B_ID = atoi(row[0]);strcpy(p->B_NAME, row[1]);strcpy(p->Author, row[2]);strcpy(p->Publish, row[3]);p->Price = atoi(row[4]);p->Quantity = atoi(row[5]);p->next = NULL;}//释放结果集mysql_free_result(res);return head;
}//添加新书籍
book* Add_new_book(book* head, MYSQL* mysql)
{book* newbook = (book*)malloc(sizeof(book));if (newbook == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = newbook;}else{//找到尾节点book* pcur = head;while (pcur->next){pcur = pcur->next;}pcur->next = newbook;}printf("请输入书籍编号:");scanf("%d", &(newbook->B_ID));//检测编号重复printf("请输入名称:");scanf("%s", newbook->B_NAME);printf("请输入作者:");scanf("%s", newbook->Author);printf("请输入出版社:");scanf("%s", newbook->Publish);printf("请输入价格:");scanf("%f", &(newbook->Price));printf("请输入库存量:");scanf("%d", &(newbook->Quantity));//将新增书籍信息存入数据库char sql[256];sprintf(sql, "insert into book values('%d','%s','%s','%s','%f','%d')",newbook->B_ID, newbook->B_NAME, newbook->Author, newbook->Publish, newbook->Price, newbook->Quantity);mysql_query(mysql, sql);newbook->next = NULL;printf("添加成功!
");return head;
}
//添加新用户
user* Add_new_user(user* head, MYSQL* mysql)
{user* newuser = (user*)malloc(sizeof(user));user* pcur = head;if (newuser == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = newuser;}else{//找到尾节点book* pcur = head;while (pcur->next){pcur = pcur->next;}pcur->next = newuser;}printf("请输入用户编号:");scanf("%d", &(newuser->U_ID));printf("请输入用户账号:");scanf("%s", newuser->U_Account);printf("请输入用户密码:");scanf("%s", newuser->U_Password);char sql[256];sprintf(sql, "insert into user values('%d','%s','%s')",newuser->U_ID, newuser->U_Account, newuser->U_Password);mysql_query(mysql, sql);newuser->next = NULL;printf("添加成功!
");return head;
}
//添加新管理员
manager* Add_new_manager(manager* head, MYSQL* mysql)
{manager* newmanager = (manager*)malloc(sizeof(manager));user* pcur = head;if (newmanager == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = newmanager;}else{//找到尾节点book* pcur = head;while (pcur->next){pcur = pcur->next;}pcur->next = newmanager;}printf("请输入管理员编号:");scanf("%d", &(newmanager->M_ID));printf("请输入管理员账号:");scanf("%s", newmanager->M_Account);printf("请输入管理员密码:");scanf("%s", newmanager->M_Password);char sql[256];sprintf(sql, "insert into manager values('%d','%s','%s')",newmanager->M_ID, newmanager->M_Account, newmanager->M_Password);mysql_query(mysql, sql);newmanager->next = NULL;printf("添加成功!
");return head;
}//展示书籍信息
void Show_All_book(book* head)
{book* p = head;printf("===================================================================================
");printf("|书名 |作者 |出版社 |价格 |库存 |编号 |
");while (p != NULL) {printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);p = p->next;}printf("===================================================================================
");}
//查找书籍信息
void Search_book(book* head)
{book* p = head;char search[100];int option;printf("=======================
");printf("| 请输入查询的项目 |
");printf("| 1.图书名 |
");printf("| 2.书作者 |
");printf("| 3.出版社 |
");printf("=======================
");scanf("%d", &option);while (1){printf("=======================
");printf("| 请输入查询的内容 |
");printf("=======================
");scanf("%s", search);printf("===================================================================================
");printf("|书名 |作者 |出版社 |价格 |库存 |编号 |
");int flag = 1;while (p != NULL){switch (option){case 1:if (strstr(p->B_NAME, search)){flag = 0;printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);}break;case 2:if (strstr(p->Author, search)){flag = 0;printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);}break;case 3:if (strstr(p->Publish, search)){flag = 0;printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);}break;}p = p->next;}if (flag){printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6s|%-6s|%-8s|
", "无", "无", "无", "无", "无", "无");}printf("===================================================================================
");break;}
}
//删除书籍信息
book* Delete_Book(book* head, MYSQL* mysql)
{book* p = head;book* pcur = NULL;int id, option;char sql[256];printf("请输入删除书籍的编号:");scanf("%d", &id);while (p){if (id == p->B_ID){break;}pcur = p;p = p->next;}if (p == NULL){printf("未找到此ID编号的书籍
");return 0;}else{printf("===================================================================================
");printf("|书名 |作者 |出版社 |价格 |库存 |编号 |
");printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);printf("===================================================================================
");printf("================
");printf("|是否确定删除?|
");printf("|0.取消 1.确定|
");printf("================
");scanf("%d", &option);switch (option){case 1:sprintf(sql, "delete from book where B_ID = %d;", id);mysql_query(mysql, sql);if (p == head){head = head->next;free(p);}else{pcur->next = p->next;free(p);}printf("已成功删除
");option = 0;break;case 0:printf("取消删除
");break;default:printf("输入错误
");break;}}return head;
}
//修改书籍信息
book* Change_book(book* head, MYSQL* mysql)
{int id;int option = 0;book* p = head;char sql[256];printf("请输入你要修改的书籍编号:");scanf("%d", &id);while (p){if (id == p->B_ID){break;}p = p->next;}if (p == NULL){printf("未找到此ID编号的书籍
");return 0;}else{do{printf("===================================================================================
");printf("|书名 |作者 |出版社 |价格 |库存 |编号 |
");printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-6.2f|%-6d|%-8d|
", p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);printf("===================================================================================
");printf("================
");printf("|请选择修改的内容|
");printf("| 1.书名 |
");printf("| 2.作者 |
");printf("| 3.出版社 |
");printf("| 4.价格 |
");printf("| 5.库存量 |
");printf("| 0.退出修改 |
");printf("================
");scanf("%d", &option);switch (option){case 1:printf("请输入修改后的书名:");scanf("%s", p->B_NAME);break;case 2:printf("请输入修改后的作者:");scanf("%s", p->Author);break;case 3:printf("请输入修改后的出版社:");scanf("%s", p->Publish);break;case 4:printf("请输入修改后的价格:");scanf("%f", &(p->Price));break;case 5:printf("请输入修改后的库存量:");scanf("%d", &(p->Quantity));break;case 0:break;}} while (option);}sprintf(sql, "update book set B_NAME = '%s', Author = '%s', Publish = '%s', Price = %f, Quantity = %d where B_ID = %d;",p->B_NAME, p->Author, p->Publish, p->Price, p->Quantity, p->B_ID);mysql_query(mysql, sql);printf("修改成功!
");return 0;
}//展示所有的用户信息
void Show_All_user(user* head)
{user* p = head;printf("=========================================================
");printf("|用户编号 |账号 |密码 |
");while (p != NULL) {printf("---------------------------------------------------------
");printf("|%-27d|%-14s|%-14s|
", p->U_ID, p->U_Account, p->U_Password);p = p->next;}printf("=========================================================
");
}
//从数据库中加载用户信息
user* load_User(user* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql)
{user* p = NULL, * pr = head;mysql_query(mysql, "select * from user;");res = mysql_store_result(mysql);while (row = mysql_fetch_row(res)){p = NULL, pr = head;p = (user*)malloc(sizeof(user));if (p == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = p;}else{while (pr->next != NULL){pr = pr->next;}pr->next = p;}p->U_ID = atoi(row[0]);strcpy(p->U_Account, row[1]);strcpy(p->U_Password, row[2]);p->next = NULL;}mysql_free_result(res);return head;
}
//从数据库中加载管理员信息
user* load_Manager(user* head, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql)
{manager* p = NULL, * pr = head;mysql_query(mysql, "select * from manager;");res = mysql_store_result(mysql);while (row = mysql_fetch_row(res)){p = NULL, pr = head;p = (manager*)malloc(sizeof(manager));if (p == NULL){perror("malloc fail");exit(1);}if (head == NULL){head = p;}else{while (pr->next != NULL){pr = pr->next;}pr->next = p;}p->M_ID = atoi(row[0]);strcpy(p->M_Account, row[1]);strcpy(p->M_Password, row[2]);p->next = NULL;}mysql_free_result(res);return head;
}
//修改用户密码
int Change_User_password(user* head, MYSQL* mysql)
{char account[30];char password[30];char sql[256];int option;user* p = head;printf("请输入用户账号:");scanf("%s", account);while (p){if (!strcmp(account, p->U_Account)){break;}p = p->next;}if (p == NULL){printf("没有查找到该用户
");return 0;}else{printf("==============================
");printf("|账号 |编号 |
");printf("------------------------------
");printf("|%-20s|%6d|
", p->U_Account, p->U_ID);printf("==============================
");}while (1){printf("请输入该账号密码:");scanf("%s", password);if (strcmp(password, p->U_Password) == 0){printf("请输入新密码:");scanf("%s", password);sprintf(sql, "update user set U_Password = '%s' where U_ID = %d;", password, p->U_ID);mysql_query(mysql, sql);printf("修改成功!");break;}else{printf("密码错误,请重试
");}}
}
//用户登陆
user* user_Login(user* head)
{user* p = head;char account[30], password[30];printf("请输入账号:");scanf("%s", account);while (p != NULL){if (!strcmp(account, p->U_Account)){break;}p = p->next;}if (p == NULL){printf("没有查找到该账号!
");return 0;}else{while (1){printf("请输入密码:");scanf("%s", password);if (strcmp(password, p->U_Password) == 0){printf("成功登录!
");break;}else {printf("密码错误!请重新输入!
");}}}return p;
}
//管理员登录
manager* manager_Login(manager* head)
{manager* p = head;char account[30], password[30];printf("请输入账号:");scanf("%s", account);while (p != NULL){if (!strcmp(account, p->M_Account)){break;}p = p->next;}if (p == NULL){printf("没有查找到该账号!
");return NULL;}else{while (1){printf("请输入密码:");scanf("%s", password);if (strcmp(password, p->M_Password) == 0){printf("成功登录!
");break;}else {printf("密码错误!请重新输入!
");}}}return p;
}//显示有库存的书籍
void Show_remaining_book(MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql)
{mysql_query(mysql, "select * from book;");res = mysql_store_result(mysql);printf("===================================================================================
");printf("|书名 |作者 |出版社 |库存量 |编号
");while (row = mysql_fetch_row(res)) {//若余量大于0则输出if (atoi(row[5]) > 0) {printf("-----------------------------------------------------------------------------------
");printf("|%-24s|%-16s|%-16s|%-15d|%-8d
", row[1], row[2], row[3], atoi(row[5]), atoi(row[0]));}}printf("===================================================================================
");
}
//借阅图书
int borrow_book(int id, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql, book* head)
{Show_remaining_book(res, row, mysql);char sql[256];int b_id;book* p = head;printf("请输入要借阅的书籍编号:");scanf("%d", &b_id);while (head != NULL){if (b_id == p->B_ID){sprintf_s(sql, sizeof(sql), "select * from book where B_ID = %d;", b_id);mysql_query(mysql, sql);res = mysql_store_result(mysql);row = mysql_fetch_row(res);if (atoi(row[5]) <= 0){printf("库存量不足!
");return 0;}else{time_t rawtime;struct tm* timeinfo;char date_str[11]; // 足够存储 "YYYY-MM-DD" 格式的日期字符串// 获取当前时间的时间戳time(&rawtime);// 将时间戳转换为本地时间timeinfo = localtime(&rawtime);// 使用sprintf将年、月、日格式化为字符串// 注意:tm_year是从1900年开始的,所以需要+1900// tm_mon是从0开始的,所以需要+1sprintf(date_str, "%d-%02d-%02d",timeinfo->tm_year + 1900,timeinfo->tm_mon + 1,timeinfo->tm_mday);sprintf(sql, "insert into borrow_book values (%d,%d,'%s','%s','%s');", id, b_id, date_str, "NULL", "BORROWED");mysql_query(mysql, sql);sprintf(sql, "update book set Quantity = Quantity - 1 where B_ID = %d;", b_id);mysql_query(mysql, sql);printf("借阅成功!
");return 0;}}p = p->next;}if (p == NULL) {printf("图书编号不存在
");}return 0;
}
//归还图书
int return_book(int id, MYSQL_RES* res, MYSQL_ROW row, MYSQL* mysql, book* head)
{int b_id;book* p = head;char sql[256];printf("请输入要归还的书籍编号:");scanf("%d", &b_id);while (p != NULL){if (b_id == p->B_ID){time_t rawtime;struct tm* timeinfo;char date_str[11];time(&rawtime);timeinfo = localtime(&rawtime);sprintf(date_str, "%d-%02d-%02d",timeinfo->tm_year + 1900,timeinfo->tm_mon + 1,timeinfo->tm_mday);sprintf(sql, "update book set Quantity = Quantity + 1 where B_ID = %d;", p->B_ID);mysql_query(mysql, sql);sprintf(sql, "update borrow_book set Return_time = '%s', State = '%s' where U_ID = %d AND B_ID = %d;", date_str, "RETURNED", id, p->B_ID);mysql_query(mysql, sql);printf("归还成功!
");break;}p = p->next;}if (p == NULL) {printf("不存在该借出的图书!
");}return 0;
}
源文件:Test.c
在该文件前要定义自己的数据库数据:
Test02()
{MYSQL_RES* res = NULL;//查询结果集MYSQL_ROW row = NULL;//记录结构体//初始化MYSQL* con = mysql_init(NULL);//设置字符编码,以防出现乱码mysql_options(con, MYSQL_SET_CHARSET_NAME, "GBK");//开始连接if (!mysql_real_connect(con, host, use, password, database_name, port, NULL, 0)){fprintf(stderr, "connect fail", mysql_error(con));return -1;}book* book_head = NULL;user* user_head = NULL;manager* manager_head = NULL;book_head = load_Book(book_head, res, row, con);user_head = load_User(user_head, res, row, con);manager_head = load_Manager(manager_head, res, row, con);//主体int input = 0;do{Menu();scanf("%d", &input);switch (input){case 1:if (manager_Login(manager_head)){int input2 = 0;do{manager_Menu();scanf("%d", &input2);switch (input2){case 1:Add_new_book(book_head, con);break;case 2:Show_All_book(book_head);break;case 3:Search_book(book_head);break;case 4:Change_book(book_head,con);break;case 5:Delete_Book(book_head, con);break;case 6:Show_All_user(user_head);break;case 7:input2 = 0;break;case 8:Add_new_manager(manager_head, con);break;case 0:input2 = 0;input = 0;break;}} while (input2);}break;case 2:printf("
");user * cur = user_Login(user_head);if (cur){int input3 = 0;do{reader_Menu(user_head);scanf("%d", &input3);switch (input3){case 1:borrow_book(cur->U_ID, res, row, con, book_head);break;case 2:return_book(cur->U_ID, res, row, con, book_head);break;case 3:Change_User_password(user_head, con);break;case 4:input3 = 0;break;case 0:input3 = 0;input = 0;break;}} while (input3);}break;case 3:Add_new_user(user_head, con);break;}} while (input);printf("再会!
");//关闭连接mysql_close(con);
}int main()
{//Test01();Test02();return 0;
}
相关文章:
【MySQL】数据库-图书管理系统(CC++实现)
一.预期功能 该图书管理系统设计提供基本的设计模版,涉及数据库的增删查改等操作,包含登录功能,图书管理功能,图书借阅功能,用户管理功能等基础功能,详细功能查看以下菜单表,共包含三个菜单&am…...
【leetcode hot 100 560】和为K的子数组
解法一:用左右指针寻找字串,如果和>k,则减少一个数(left);如果和<k,则加上一个数(right)。 class Solution {public int subarraySum(int[] nums, int k) {int nu…...
【漫话机器学习系列】110.线性可分(Linearly Separable)
线性可分与线性不可分的概念详解 1. 引言 在机器学习和模式识别领域,分类问题是一个重要的研究方向。在分类任务中,我们通常需要将不同类别的数据点分开,而如何进行分割是一个关键问题。线性可分(Linearly Separable)…...
单细胞分析(19)—— 单细胞转录组基因集评分方法
下面是每种基因集评分方法的原理介绍代码示例,适用于R语言和Python两种主流生信分析环境。可以直接应用于单细胞转录组(scRNA-seq)数据分析中。 🔬 单细胞转录组基因集评分方法(附代码示例) 在单细胞RNA测…...
【数据挖掘】Pandas
Pandas 是 Python 进行 数据挖掘 和 数据分析 的核心库之一,提供了强大的 数据清洗、预处理、转换、分析 和 可视化 功能。它通常与 NumPy、Matplotlib、Seaborn、Scikit-Learn 等库结合使用,帮助构建高效的数据挖掘流程。 📌 1. 读取数据 P…...
Spring Boot 中 @Transactional 注解全面解析
亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、Java 与 Python 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在未来…...
【网络】数据链路层(以太网帧格式、MTU、ARP)、NAT、内网穿透
文章目录 1. 数据链路层2. 以太网帧格式3. MTU3.1 认识MTU3.2 MTU 对于 TCP 协议的影响 4. 局域网通信原理5. ARP协议5.1 基本概念5.2 原理5.3 ARP 数据报的格式 6. NAT技术7. 内网穿透8. 内网打洞9. 代理服务器9.1 正向代理9.2 反向代理9.3 NAT VS 代理服务器 10.网络总结 1. …...
ASPNET Core笔试题 【面试宝典】
文章目录 一、如何在ASP.NET Core中激活Session功能?二、什么是中间件?三、ApplicationBuilder的Use和Run方法有什么区别?四、如何使TagHelper在元素这一层上失效?五、什么是ASP.NET Core?六、ASP.NET Core中AOP的支持…...
Harmony os next~鸿蒙原子化服务开发实战:天气卡片开发全解析
鸿蒙原子化服务开发实战:天气卡片开发全解析 一、原子化服务与HarmonyOS卡片概述 (1)原子化服务特性 HarmonyOS原子化服务具有独立入口(桌面图标/智慧搜索)、免安装、跨设备流转三大核心特性。服务卡片作为其可视化载…...
【pytest框架源码分析三】pluggy源码分析之hook注册调用流程
pluggy的hook调用,最重要的就是使用了__call__魔法函数,这个函数能够在我们调用实例时,自动调用这个函数,无需自己手动调用。 前面介绍了各个类的方法,这里简述下pluggy的调用流程(主要介绍主流程ÿ…...
Linux消息队列
msgget函数(类似于shmget) 是 Linux 系统中用于 创建或获取消息队列(System V Message Queue) 的系统调用。 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h>int msgget(key_t key, int m…...
ChatGPT 提示词框架
作为一个资深安卓开发工程师,我们在日常开发中经常会用到 ChatGPT 来提升开发效率,比如代码优化、bug 排查、生成单元测试等。 但要想真正发挥 ChatGPT 的潜力,我们需要掌握一些提示词(Prompt)的编写技巧,并…...
对于动态线程池框架 Hippo4j 的思考
从 java 线程池探讨动态线程池框架的可行性以及扩展性 ThreadPoolExecutor 对外给用户暴露了很多 get、set 方法,get 方法可以让我直接获得一些线程池的运行时信息,比如线程池过去已经完成任务的总数量,线程池目前活跃线程数量等等ÿ…...
问deepseek: HYPRE BoomerAMG 有哪些参数可以进行性能调优
Hypre BoomerAMG 是一个高性能的多重网格预条件子,常用于求解大规模稀疏线性系统。为了优化其性能,可以调整以下关键参数: 1. AMG 参数 Coarsening (强连接阈值) strong_threshold: 控制强连接的阈值,通常在 0.25 到 0.6 之间&a…...
seacms v9 实现的MySQL注入
目录 过滤关键词information_schema 怎么办 一、环境搭建 二、环境分析 三、源代码分析 1、过滤程序 2、注入点 四、获取数据库名 五、获取数据库表名 六、获取表的列名 七、获取数据信息 过滤关键词information_schema 怎么办 1.、利用sys数据库(MySQL 5.…...
基于C#的CANoe CLR Adapter开发指南
一、引言 CANoe 是一款广泛应用于汽车电子开发和测试的工具,它支持多种编程接口,方便开发者进行自定义扩展。CANoe CLR Adapter 允许我们使用 C# 语言与 CANoe 进行交互,充分利用 C# 的强大功能和丰富的类库。本文将详细介绍如何基于 C# 进行…...
Vue 系列之:基础知识
什么是 MVVM MVVM(Model-View-ViewModel)一种软件设计模式,旨在将应用程序的数据模型(Model)与视图层(View)分离,并通过 ViewModel 来实现它们之间的通信。降低了代码的耦合度。 M…...
知识库功能测试难点
图表交互功能测试难点 知识库图表类型多,每种图表交互功能不同。像柱状图,可能有点击柱子查看详细数据、鼠标悬停显示数据提示等交互;折线图除了这些,还可能支持缩放查看不同时间段数据。多种交互操作在不同图表间存在差异&#x…...
一文掌握 Scrapy 框架的详细使用,包括实战案例
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. Scrapy 简介2. Scrapy 的核心组件3. 安装 Scrapy4. 创建 Scrapy 项目4.1 创建项目4.2 创建 Spider5. 编写 Spider5.1 定义 Item5.2 编写 Spider 逻辑6. 运行 Scrapy 爬虫6.1 运行爬虫6.2 保存爬取数据7. Scrapy 的高…...
奔图Pantum M7165DN黑白激光打印一体机报数据清除中…维修
故障描述: 一台奔图Pantum M7165DN黑白激光打印一体机开机自检正常,自检过后就不能工作了,按键面板无任何反应一直提示数据清除中…,如果快速操作的话也能按出菜单、功能啥的,不过一会又死机了,故障请看下图: 故障检修: 经分析可能是主板数据出现了问题,看看能不能快速…...
微服务架构与传统的单体架构有什么区别?微服务架构(Spring Cloud + Maven)强在哪?
微服务架构与传统的单体架构(Spring Boot Maven 项目)在设计和实现上有显著差异,主要体现在系统拆分方式、部署模式、技术栈选择、维护成本等方面。以下是具体对比: 1. 架构设计 维度单体架构微服务架构系统拆分所有功能模块集…...
二、QT和驱动模块实现智能家居----2、编译支持QT的系统
因为我们的Linux内核文件不支持QT系统(当然如果你的支持,完全跳过这篇文章),所以我们要从网上下载很多软件包,这里直接用百问网的软件包,非常方便。 一:Ubuntu 配置 1 设置交叉编译工具链 以…...
游戏引擎学习第128天
开始 然而,我们仍然有一些工作要做,渲染部分并没有完全完成。虽然现在已经能够运行游戏,而且帧率已经可以接受,但仍然有一些东西需要进一步完善。正在使用调试构建编译版本,虽然调试版本的性能不如优化版本࿰…...
【量化策略】套利交易策略
【量化策略】套利交易策略 🚀量化软件开通 🚀量化实战教程 技术背景与应用场景 在金融市场中,套利交易策略是一种利用市场价格差异来获取无风险利润的交易方式。这种策略通常涉及同时买入和卖出不同市场上的相同或相似金融产品࿰…...
laravel11设置中文语言包
安装中文语言包 Laravel 11 默认没有内置完整中文语言包,推荐使用第三方维护的完整翻译: # 通过 Composer 安装语言包 composer require laravel-lang/common --dev# 发布中文语言文件到项目 php artisan lang:add zh_CN这会自动将中文语言文件生成到 l…...
Javaweb数据库多表查询 内连接 外连接 子查询
内连接 外连接 左外连接,左边是全部表 表名,即使没有匹配右边的数据,也要查询出来 子查询 案例 1.没有说所有的部门,所有的员工,用内连接(隐式内连接)...
欧氏距离、曼哈顿距离、切比雪夫距离、闵可夫斯基距离、马氏距离理解学习
目录 一、欧氏距离(Euclidean Distance)公式:原理: 二、曼哈顿距离(Manhattan Distance)公式:原理: 三、切比雪夫距离(Chebyshev Distance)公式:原…...
【地图视界-Leaflet4】绘制自定义图形
引言 在前面的文章中,我们学会了如何在 Leaflet 中添加标记、弹窗以及切换不同的底图和叠加图层。但是在很多实际应用中,我们需要在地图上绘制多边形、圆形、矩形、折线等几何图形,用于标记区域、路径规划、范围分析等。 本篇文章将介绍如何…...
华为hcia——Datacom实验指南——STP工作基本原理及STP/RSTP基本功能配置
什么时候需要用到STP 在二层交换网络中,为了避免环路产生。 什么是STP STP生成树协议,是用来在冗余链路上消除二层环路。在众多交换机中,需要设置出一个根桥,其余的交换机称为非根桥,根桥是整个交换网络的核心&…...
游戏引擎学习第127天
仓库:https://gitee.com/mrxiao_com/2d_game_3 为本周设定阶段 我们目前的渲染器已经实现了令人惊讶的优化,经过过去两周的优化工作后,渲染器在1920x1080分辨率下稳定地运行在60帧每秒。这个结果是意料之外的,因为我们没有预计会达到这样的…...
PostgreSQL 创建表格
PostgreSQL 创建表格 在数据库管理中,表格(Table)是数据存储的基础。PostgreSQL作为一款强大的开源对象关系型数据库管理系统(ORDBMS),创建表格是其最基本的功能之一。本文将详细讲解如何在PostgreSQL中创…...
AF3 deduplicate_unpaired_sequences函数解读
AlphaFold3 msa_pairing模块的deduplicate_unpaired_sequences 函数的作用是移除 chain[msa] 中那些已经存在于 chain[msa_all_seq] 中的序列。换句话说,它保留那些不在 chain[msa_all_seq] 中的序列,从而确保未配对的 MSA 序列不会与配对的 MSA 序列重复…...
图像处理之图像边缘检测算法
目录 1 图像边缘检测算法简介 2 Sobel边缘检测 3 经典的Canny边缘检测算法 4 演示Demo 4.1 开发环境 4.2 功能介绍 4.3 下载地址 参考 1 图像边缘检测算法简介 图像边缘检测是计算机视觉和图像处理中的基本问题,主要目的是提取图像中明暗变化明显的边缘细节…...
unity使用input system实现相机屏幕手势丝滑拖拽
input action设置 操作对象设置 camera 具体操作类 PlayerInputView类 using System.Collections; using UnityEngine; using UnityEngine.InputSystem; using TouchPhase UnityEngine.InputSystem.TouchPhase;public class FingerScale : MonoBehaviour {private Vector3…...
Leetcode-853. Car Fleet [C++][Java]
目录 一、题目描述 二、解题思路 Leetcode-853. Car Fleethttps://leetcode.com/problems/car-fleet/description/ 一、题目描述 There are n cars at given miles away from the starting mile 0, traveling to reach the mile target. You are given two integer array …...
建易WordPress
建易WordPress是一家专业的WordPress建站服务提供商,专注于为企业和个人提供一站式的WordPress网站建设、维护、托管、运营推广以及搜索引擎优化(SEO)服务。 服务内容 1. 网站建设 提供模板建站和定制开发两种服务,满足不同客户的需求。模板建站价格为…...
计算机三级网络技术备考(3)
【知识点补充:带宽是是链路的传输速率,宽带是一种服务】 第四章:路由设计技术 考点1:IP路由选择与路由汇聚 核心层:s0两个IP进行汇聚就行 汇聚层:聚合后两个以上的往前进几位(因为主机号不够因…...
工程化与框架系列(13)--虚拟DOM实现
虚拟DOM实现 🌳 虚拟DOM(Virtual DOM)是现代前端框架的核心技术之一,它通过在内存中维护UI的虚拟表示来提高渲染性能。本文将深入探讨虚拟DOM的实现原理和关键技术。 虚拟DOM概述 🌟 💡 小知识࿱…...
Java实现pdf文件压缩(aspose-pdf实现压缩、itextpdf去除aspose-pdf版权水印)
Java实现pdf文件压缩 时间换空间,实现pdf文件无损压缩。 1、依赖准备 市面上操作pdf文件的组件有spire.pdf.free、itextpdf、openpdf、pdfbox等,它们各有千秋。我们主要完成的场景为压缩,减少文件大小去优化存储、传输等。 在这里选取的组件…...
生态安全相关
概念:生态安全指一个国家具有支撑国家生存发展的较为完整、不受威胁的生态系统,以及应对内外重大生态问题的能力。 (1)国外生态安全的研究进展 国际上对生态安全的研究是从“环境”与“安全”之间的关系展开的。开始的阶段&#x…...
通过 ANSYS Discovery 进行 CFD 分析,增强工程设计
概括 工程师使用计算流体动力学 (CFD) 分析来研究和优化各种应用中的流体流动和传热分析。ANSYS Discovery 是一个用户友好的软件平台,使工程师能够轻松设置和解决 CFD 模型,并能够通知设计修改 在这篇博文中,我们将重点介绍在 Ansys Disc…...
2. 在后端代码中加入日志记录模块
1. 说明 日志模块基本上是每一个软件系统开发中必不可少的,主要用于持久记录一些代码运行中的输出信息,辅助编码人员进行代码调试,以及后期软件上线运行报错分析。在Python中加入日志模块比较简单,只需要借助logging和RotatingFi…...
MySQL锁分类
一、按锁的粒度划分 全局锁 定义:锁定整个数据库实例,阻止所有写操作,确保数据备份一致性。加锁方式:通过FLUSH TABLES WITH READ LOCK实现,释放需执行UNLOCK TABLES。应用场景:适用于全库逻辑备份…...
软件测试之白盒测试知识总结
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 概念与定义 白盒测试:侧重于系统或部件内部机制的测试,类型分为分支测试(判定节点测试)、路径测试、语句测试…...
看视频学习方法总结
以下是提高教学视频吸收率的系统性方法,结合认知科学原理和实际学习场景,帮助您最大化学习效果: 一、观看前的黄金准备阶段 60秒快速扫描法 用1分钟快速浏览视频目录、章节标题和简介,建立知识框架。荷兰伊拉斯姆斯大学实验表明&…...
nvm的学习
学习 nvm(Node Version Manager) 是掌握 Node.js 开发的关键技能之一。以下是系统的学习路径和实战指南,涵盖从基础到进阶的内容: 一、基础入门 1. nvm 的核心作用 多版本共存:安装和管理多个 Node.js 版本ÿ…...
OpenCV计算摄影学(5)处理一系列图像(例如视频帧)的非局部均值去噪的函数fastNlMeansDenoisingColoredMulti()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 对用于彩色图像序列的 fastNlMeansDenoisingMulti 函数的修改。 cv::fastNlMeansDenoisingColoredMulti 函数是 OpenCV 中用于处理一系列图像&am…...
mysql安装教程,超详细图文教程(附安装包)MySQL8.0安装教程
文章目录 前言一、MySQL安装包下载二、mysql安装教程 前言 本教程旨在为大家提供详细、清晰的 mysql安装教程,帮助你轻松跨过安装门槛,顺利开启数据库管理与开发的精彩之旅。 一、MySQL安装包下载 MySQL 是一款备受欢迎的开源关系型数据库管理系统&…...
Spark内存迭代计算
一、宽窄依赖 窄依赖:父RDD的一个分区数据全部发往子RDD的一个分区 宽依赖:父RDD的一个分区数据发往子RDD的多个分区,也称为shuffle 二、Spark是如何进行内存计算的?DAG的作用?Stage阶段划分的作用? &a…...
Odoo免费开源CRM技术实战:从商机线索关联转化为售后工单的应用
文 / 开源智造 Odoo金牌服务 Odoo:功能强大且免费开源的CRM Odoo 引入了一种高效的客户支持管理方式,即将 CRM 线索转换为服务台工单。此功能确保销售和支持团队能够无缝协作,从而提升客户满意度并缩短问题解决时间。通过整合 CRM 模块与服…...