项目仓库 :传送门
需求分析
当下市场日益激烈的竞争迫使图书企业采用一种新的管理方式来加快图书管理操作,而计算机技术的发展为图书管理注入了新的生机。通过调查市场,一款合格的图书管理系统必须具备以下三个特点:
- 能够对图书信息进行集中管理
- 能够大大提高用户工作效率
- 能够对图书的部分信息进行查询
基于上述需求,笔者在此开发出一款简单的图书管理系统以方便用户管理图书信息。
系统设计
系统目标
- 添加图书信息
- 所有数据信息存储于数据库中
- 根据图书的编号(唯一)删除对应的图书信息
- 根据图书的编号查找对应的图书信息
- 根据图书的编号修改对应的图书信息
系统功能结构
开发及运行环境
- 系统开发平台:CLion 2022.3.2
- 数据库管理平台:MYSQL Server 8.0
- 运行平台:Windows 11
详细设计
数据库设计
数据表结构
字段名 | 数据类型 | 长度 | 是否为空 | 是否主键 | 描述 |
ID | char | 10 | 否 | 是 | 图书编号 |
bookname | char | 50 | 否 | 否 | 图书名 |
author | char | 50 | 否 | 否 | 作者 |
bookconcern | char | 100 | 否 | 否 | 出版社 |
操作执行SQL语句
#创建数据库
create database db_books DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci
#创建数据表
create table tb_book(
ID char(10) NOT NULL,
bookname char(50) not null ,
author char(50) not null ,
bookconcern char(100) not null ,
primary key (ID)
)ENGINE = MYISAM DEFAULT CHARACTER SET gbk #也可以不设置编码GBK,因为该系统在操作查询中文结果时仍会出现乱码情况
创建项目
- 选择C++可执行文件
2.配置工具链
MSVC或Mingw编译环境都可以,选择MSVC时需要官网下载Visual Studio 并在CLion中选择MSVC的路径,Mingw一般Clion中自带。同时要注意选择合适的架构 x86(32位) 或 x86_amd64(64位)。
配置项目结构
由于该项目在编译链接时需要用到 mysql.h 头文件、libmysql.lib 静态库,在执行时需要引用 libmysql.dll 动态库,因此要向项目中引入外部头文件和外部库。
- 在项目中创建lib和include目录。
- 复制外部库到项目中
将mysql安装目录中的lib目录中的 libmysql.lib 和 libmysql.dll 复制到项目中的lib目录中,将mysql安装目录中的include目录中的所有头文件复制到项目中的include目录中。
项目结构如下所示:
配置CMake
cmake_minimum_required(VERSION 3.0)
project(Library_1) #项目名,可能不一样但不影响
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Bin)
#设置在项目编译连接完成后生成所有的可执行文件以及外部库都默认存放在Bin目录下
include_directories(./include) #引入外部头文件,在当前项目的include目录下
link_directories("./lib") #引入外部库,在当前项目的lib目录下
link_libraries(libmysql) #添加libmysql.lib静态库,编译和链接时需要用到它
target_link_libraries(Library_1 libmysql.lib)
file(GLOB dll_src "${CMAKE_SOURCE_DIR}/lib/libmysql.dll") #设置dll_src为libmysql.dll的路径变量名,后面再使用libmysql.dll路径就可以使用缩写了
file(COPY ${dll_src} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
#在生成可执行文件后将动态库libmysql.dll放入Bin目录下,在执行程序时会直接调用。
add_executable(Library_1 main.cpp menu.h crud.h)
main.cpp
#include <iostream>
#include <mysql.h>
#include <cstring>
#include "menu.h"
#include "crud.h"
#pragma comment(lib, "libmysql") #添加libmysql.lib静态库
//#define debug
using namespace std;
int main() {
#ifdef debug
cout << "准备连接数据库" << endl;
system("pause");
#endif
//初始连接数据库
system("cls");
MYSQL mysql;
mysql_init(&mysql);
if(!mysql_real_connect(&mysql,"127.0.0.1","root","123456","db_books",3306,NULL,0)){
cout << "数据库连接失败" << endl;
system("pause");
return 0;
}else{
cout << "数据库连接成功" << endl;
}
system("pause");
char n = '1';
//主菜单
while(n){
n = ShowMenu();
switch(n){
case '1':
ShowALL(mysql); //显示所有图书信息
break;
case '2':
AddBook(mysql); //添加图书信息
break;
case '3':
ModifyBook(mysql); //修改图书信息
break;
case '4':
DeleteBook(mysql); //删除图书信息
break;
case '5':
QueryBook(mysql); //查询图书信息
break;
case '6':
cout << "感谢您的使用!" << endl; //退出程序
system("pause");
break;
}
if(n == '6') break;
}
// 关闭数据库
mysql_close(&mysql);
cout << "数据库已经关闭连接" << endl;
system("pause");
return 0;
}
menu.h
#include <iostream>
#include <string>
#ifndef LIBRARY_1_MENU_H
#define LIBRARY_1_MENU_H
using namespace std;
char ShowMenu(){
while(true) {
system("cls");
cout << "****************************" << endl;
cout << "* 图书管理系统 *" << endl;
cout << "* 1、显示所有图书信息 *" << endl;
cout << "* 2、添加图书信息息 *" << endl;
cout << "* 3、修改图书信息 *" << endl;
cout << "* 4、删除图书信息 *" << endl;
cout << "* 5、查询图书信息 *" << endl;
cout << "* 6、退出系统 *" << endl;
cout << "****************************" << endl;
cout << "****************************" << endl;
cout << "请选择: ";
string str;
getline(cin,str); // 为了防止非法输入,这里使用了getline函数,先读入一行,再对字符串进行处理
if(str.size() != 1){
cout << "无效选择" << endl;
continue;
}
char s = str.at(0);
if(s >= '1' && s <= '6') {
return s;
}
}
};
#endif //LIBRARY_1_MENU_H
crud.h
该头文件主要实现基本的增删改查功能,四个功能基本上大同小异,存在一些冗余,可以再尝试精简一下。
#include <string>
#include <cstring>
#ifndef LIBRARY_1_CRUD_H
#define LIBRARY_1_CRUD_H
using namespace std;
bool InputCheck(string str,int size);
void ShowALL(MYSQL mysql){
MYSQL_RES *result;
MYSQL_ROW row;
if(mysql_query(&mysql,"select * from tb_book")){
cout << "查询失败" << endl;
cout << mysql_errno(&mysql) << endl;
system("pause");
return;
}else{
result = mysql_store_result(&mysql);
if(mysql_num_rows(result) != NULL){
while((row = mysql_fetch_row(result))){
cout << row[0] << " " << row[1] << " " << row[2] << " " << row[3] << endl;
}
}else{
cout << "没有记录" << endl;
}
system("pause");
}
}
void AddBook(MYSQL mysql){
system("cls");
int rowCount;
MYSQL_RES *result;
string id;
string bookName;
string author;
string bookConcern;
string sql;
string dest;
char str[240];
cout << "********************************" << endl;
cout << " 添加图书信息 " << endl;
cout << "********************************" << endl;
cout << "ID: " ;
getline(cin,id);
string sqltest = "select ID from tb_book where ID = '";
sqltest = sqltest + id + "'";
strcpy_s(str,sqltest.c_str());
if(mysql_query(&mysql,str)){
cout << "数据表查询失败,暂时无法添加。" << endl;
}else{
result = mysql_store_result(&mysql);
rowCount = mysql_num_rows(result);
if(rowCount > 0){
cout << "该编号已经存在无法插入" << endl;
system("pause");
}else{
cout << "图书名:";
getline(cin,bookName);
if(!InputCheck(bookName,50)) return;
cout << "作者:" ;
getline(cin,author);
if(!InputCheck(author,50)) return;
cout << "出版社:";
getline(cin,bookConcern);
if(!InputCheck(bookConcern,100)) return;
sql = "insert into tb_book (ID,bookname,author,bookconcern) values('"+ id + "','" + bookName + "','" + author + "','" + bookConcern + "')";
strcpy_s(str,sql.c_str());
if(mysql_query(&mysql,str)){
cout << "插入数据失败" << endl;
cout << mysql_errno(&mysql) << endl;
cout << mysql_error(&mysql) << endl;
}else{
cout << "插入数据成功" << endl;
}
mysql_free_result(result);
system("pause");
}
}
}
void ModifyBook(MYSQL mysql){
string s;
MYSQL_RES *result;
MYSQL_ROW row;
string bookName;
string author;
string bookConcern;
string sql;
string dest;
int rowCount = 0;
char str[200];
system("cls");
cout << "********************************" << endl;
cout << " 修改图书信息 " << endl;
cout << "********************************" << endl;
cout << "请输入编号:";
getline(cin, s);
sql = "select * from tb_book where ID = '" + s + "'";
strcpy_s(str, sql.c_str());
if (mysql_query(&mysql, str)) {
cout << "查询失败" << endl;
system("pause");
} else {
result = mysql_store_result(&mysql);
rowCount = mysql_num_rows(result);
if (rowCount == 0) {
cout << "不存在此数据" << endl;
system("pause");
return;
}
row = mysql_fetch_row(result);
cout << row[0] << " " << row[1] << " " << row[2] << " " << row[3] << endl;
system("pause");
cout << "新的图书名:";
getline(cin,bookName);
if(!InputCheck(bookName,50)) return;
cout << "作者:" ;
getline(cin,author);
if(!InputCheck(author,50)) return;
cout << "出版社:";
getline(cin,bookConcern);
if(!InputCheck(bookConcern,100)) return;
sql = "update tb_book set bookname = '"+ bookName + "', author = '" + author + "', bookconcern = '" + bookConcern + "' where ID = '" + s + "'";
strcpy_s(str,sql.c_str());
if(mysql_query(&mysql,str)){
cout << "修改数据失败" << endl;
cout << mysql_errno(&mysql) << endl;
cout << mysql_error(&mysql) << endl;
}else{
cout << "修改数据成功" << endl;
}
mysql_free_result(result);
system("pause");
}
}
void DeleteBook(MYSQL mysql){
string s;
MYSQL_RES *result;
MYSQL_ROW row;
int rowCount = 0;
char str[50];
system("cls");
cout << "********************************" << endl;
cout << " 删除图书信息 " << endl;
cout << "********************************" << endl;
cout << "请输入编号:";
getline(cin,s);
string sql = "select * from tb_book where ID = '" + s + "'";
strcpy_s(str, sql.c_str());
if(mysql_query(&mysql,str)){
cout << "查询失败" << endl;
system("pause");
}else {
result = mysql_store_result(&mysql);
rowCount = mysql_num_rows(result);
if(rowCount == 0 ){
cout << "不存在此数据,无法删除" << endl;
system("pause");
return;
}
row = mysql_fetch_row(result);
cout << row[0] << " " << row[1] << " " << row[2] << " " << row[3] << endl;
cout << "确认删除吗? 确认 1 ,任意键取消" << endl;
string ans;
getline(std::cin,ans);
if(ans.size() != 1){
std::cout << "无效选择" << std::endl;
}else {
char t = ans.at(0);
if (t == '1') {
sql = "delete from tb_book where ID = '" + s + "'";
strcpy_s(str, sql.c_str());
if (mysql_query(&mysql, str)) {
cout << "删除图书信息失败" << endl;
} else {
cout << "删除图书信息成功" << endl;
}
}
}
mysql_free_result(result);
}
system("pause");
return;
}
void QueryBook(MYSQL mysql) {
string s;
MYSQL_RES *result;
MYSQL_ROW row;
int rowCount = 0;
char str[50];
system("cls");
cout << "********************************" << endl;
cout << " 查询图书信息 " << endl;
cout << "********************************" << endl;
cout << "请输入编号:";
getline(cin, s);
string sql = "select * from tb_book where ID = '" + s + "'";
strcpy_s(str, sql.c_str());
if (mysql_query(&mysql, str)) {
cout << "查询失败" << endl;
system("pause");
} else {
result = mysql_store_result(&mysql);
rowCount = mysql_num_rows(result);
if (rowCount == 0) {
cout << "不存在此数据" << endl;
system("pause");
return;
}
row = mysql_fetch_row(result);
cout << row[0] << " " << row[1] << " " << row[2] << " " << row[3] << endl;
system("pause");
}
}
bool InputCheck(string str,int size){
if(str.size() >= size) {
cout << "数据太长,无法插入" << endl;
system("pause");
return false;
}
return true;
}
#endif //LIBRARY_1_CRUD_H
效果测试
主菜单界面
显示所有图书信息
添加图书信息
修改图书信息
删除图书信息
查询图书信息
退出系统
开发总结
通过这次项目设计,提升了自己简单管理系统的项目开发的经验,能够独立实现基本的增删改查功能以及C语言连接数据库的基本操作。但该项目仍有很多不足之处,比如应该采用面向对象思想、在操作数据库查询时的结果存在编码问题,不能显示中文等等。笔者将继续努力学习软件开发相关知识,争取努力开发出更好的管理系统,为社会做出自己的贡献。