CLion开发图书管理系统项目 (c++ + MySQL实现)

news2024/12/18 18:52:43

项目仓库  :传送门

需求分析

       当下市场日益激烈的竞争迫使图书企业采用一种新的管理方式来加快图书管理操作,而计算机技术的发展为图书管理注入了新的生机。通过调查市场,一款合格的图书管理系统必须具备以下三个特点:

  1. 能够对图书信息进行集中管理
  2. 能够大大提高用户工作效率
  3. 能够对图书的部分信息进行查询

基于上述需求,笔者在此开发出一款简单的图书管理系统以方便用户管理图书信息。

系统设计

系统目标

  1. 添加图书信息
  2. 所有数据信息存储于数据库中
  3. 根据图书的编号(唯一)删除对应的图书信息
  4. 根据图书的编号查找对应的图书信息
  5. 根据图书的编号修改对应的图书信息

系统功能结构

开发及运行环境

  1. 系统开发平台:CLion 2022.3.2
  2. 数据库管理平台:MYSQL Server 8.0
  3. 运行平台: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,因为该系统在操作查询中文结果时仍会出现乱码情况

创建项目

  1. 选择C++可执行文件

      2.配置工具链

 MSVC或Mingw编译环境都可以,选择MSVC时需要官网下载Visual Studio 并在CLion中选择MSVC的路径,Mingw一般Clion中自带。同时要注意选择合适的架构 x86(32位) 或 x86_amd64(64位)。

配置项目结构

由于该项目在编译链接时需要用到 mysql.h 头文件、libmysql.lib 静态库,在执行时需要引用 libmysql.dll 动态库,因此要向项目中引入外部头文件和外部库。

  1. 在项目中创建lib和include目录。
  2. 复制外部库到项目中

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语言连接数据库的基本操作。但该项目仍有很多不足之处,比如应该采用面向对象思想、在操作数据库查询时的结果存在编码问题,不能显示中文等等。笔者将继续努力学习软件开发相关知识,争取努力开发出更好的管理系统,为社会做出自己的贡献。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/371998.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

注解原理剖析与实战

一、注解及其原理 1.注解的基本概念 注解&#xff0c;可以看作是对 一个类/方法的一个扩展的模版&#xff0c;每个类/方法按照注解类中的规则&#xff0c;来为类/方法注解不同的参数&#xff0c;在用到的地方可以得到不同的类/方法中注解的各种参数与值。 从JDK5开始&#xff…

【必学】最流行的云原生监控解决方案:Prometheus+Grafana

文章目录一、Prometheus和Grafana简介1.1、Prometheus是最受欢迎的云原生监控方案之一1.2、Grafana是最流行的开源可视化平台二、Prometheus的优势三、Prometheus架构原理四、Prometheus和Grafana安装部署一、Prometheus和Grafana简介 1.1、Prometheus是最受欢迎的云原生监控方…

如何进行单元测试

前言单元测试是指对软件中最小可测单元进行检查和验证&#xff1b;c语言中单元指一个函数&#xff0c;java中指一个类。图形化软件中可以指一个窗口或者一个菜单。总的来说&#xff0c;单元就是认为规定最小的被测试模块。1.1单元测试对我们开发程序有什么好处首先是一个前端单…

react: input 输入框 中文onChange事件异常问题 对input输入进行防抖处理

当我们使用Input时&#xff0c;我们可能会遇到一个问题&#xff0c;比如需要对用户输入的内容进行搜索时&#xff0c;当用户处于中文输入时&#xff0c;明明没有对内容进行确认&#xff0c;为什么会触发了onChange事件呢&#xff1f;比如以下场景&#xff0c;中文一边输入另外一…

机器学习知识总结 —— 20.使用朴素贝叶斯进行数据分类

文章目录准备基础数据计算先验概率计算条件概率预测分布验证结果作为一种监督学习分类方法&#xff0c;在上一章中我们已经介绍过它的数理原理。现在我们开始来实现一个简单的朴素贝叶斯分类的算法&#xff0c;这样我们能更好的理解它是怎么运作的。 准备基础数据 首先还是有…

加密流量专栏总览

文章目录加密流量专栏1. 原理篇2. 模型篇3. 文章分类总结3.1 研究方向3.2 特征提取3.3 机器学习模型改进3.4 深度学习模型改进3.5 其他模型改进3.7 实时检测3.8 概念漂移检索论文的方法加密流量专栏 1. 原理篇 原理&#xff1a; 会话、流、数据包之间的关系。 流&#xff1a;…

【离线数仓-4-数据仓库设计-分层规划构建流程】

离线数仓-4-数据仓库设计-分层规划&构建流程离线数仓-4-数据仓库设计-分层规划&构建流程1.数据仓库分层规划2.数据仓库构建流程1.数据调研1.业务调研2.需求分析3.总结2.明确数据域3.构建业务总线矩阵&维度模型设计4.明确统计指标1.指标体系相关概念1.原子指标2.派生…

【渝偲医药】DSPE-PEG-RGD;磷脂聚乙二醇多肽试剂级简介

DSPE-PEG-RGD、 二硬脂酰基磷脂酰乙醇胺-聚乙二醇-多肽、磷脂PEG多肽 英文名称: 1,2-Distearoyl-sn-Glycero-3-Phosphoethanolamine-PEG- RGD 溶剂:可溶解在水中和大多数有机溶剂中 外观:白色粉末 用途:用于链接带有链霉亲和素或其他的基团的分子 分子量(PEG ):2000、3400、…

那些开发过程中需要遵守的开发规范

入职公司三天&#xff0c;没干啥其他活&#xff0c;基本在配置本地环境和阅读相关文档。技术方面公司基本用的是主流的技术体系&#xff0c;入职后需要先阅读阿里的开发规范和其他的一些产研文档。今天整理一些平时需要关注的阿里规约和数据库开发规范&#xff0c;方便今后在开…

TatukGIS Developer Kernel for .NET

TatukGIS Developer Kernel for .NET 用于.NET的TatukGIS开发人员内核的强大功能&#xff1a; 打开、创建、编辑、保存和导出矢量、图片和网格的过程&#xff0c;包括类似于数据库的格式。 扩展属性、北箭头、比例和其他视觉控制也从TatukGIS编辑器/查看器商品中显示给用户开发…

Java基础系列(五): final关键字用法

一. 概述 final关键字代表最终,不可改变的. 常见有5种用法,我们来归纳总结一下: 1. 用来修饰一个类 2. 用来修饰一个方法 3. 用来修饰成员变量 4. 用来修饰局部变量 5. 用来修饰方法参数 二. final饰修类 如果声明一个类为final类, 那么这个类就是最终类,不能被继承 …

7 Python文件、文件夹、word及excel操作

0 建议学时和要求 4学时 掌握os和os.path模块对文件和文件夹操作的函数 掌握shutil模块对文件和文件夹操作的函数 掌握扩展库openpyxl对Excel文件的操作 1 文件的高级操作 1.1 文件的概念及分类 文本文件 文本文件可以使用记事本、gedit、ultraedit等字处理软件直接进行显…

ESP32设备驱动-DS1264数字温度传感器驱动

DS1264数字温度传感器驱动 1、DS1264介绍 DS1624 由两个独立的功能单元组成:一个 256 字节非易失性 E2 存储器和一个直接数字温度传感器。 非易失性存储器由 256 字节的 E2 存储器组成。 该存储器可用于存储用户希望的任何类型的信息。 这些内存位置通过 2 线串行总线访问。…

007永磁电机控制方式:别张嘴就FOC,其他常规控制方式也是伺服人的基本功

在读本篇文&#xff0c;我想做个小调查。到目前为止&#xff0c;你掌握的或者是你了解到的控制永磁同步电机的方式都有哪些&#xff1f;我想&#xff0c;你大概张口就说FOC控制吧。没错&#xff0c;FOC控制是我们日常生活中所见到的最普遍的永磁同步电机的控制方式。当然在本专…

微信电脑版字体模糊(或文字太小)怎么调整

文章目录第一步&#xff1a;设置屏幕缩放125%第二步&#xff1a;文本大小设置为125%第三步&#xff1a;微信设置--通用--勾选“适配系统缩放比例”第四步&#xff1a;微信高DPI缩放行为设置&#xff08;关键&#xff09;ClearType勾选&#xff08;可选&#xff09;笔者遇到这个…

【模板】线段树 2

题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面三种操作&#xff1a; 将某区间每一个数乘上 xxx 将某区间每一个数加上 xxx 求出某区间每一个数的和 输入格式 第一行包含三个整数 n,m,pn,m,pn,m,p&#xff0c;分别表示该数列数字的个数、操作的总个数…

计算机网络笔记(复试准备)第一章

计算机网络笔记&#xff08;复试准备&#xff09; 第一章 网络&#xff0c;互联网与因特网 网络由若干个结点和连接这些结点的链路组成 多个网络通过路由器连接起来这也就形成了一个更大的网络即是我们熟知的互联网也就是“网络的网络” 因特网是世界上最大的网络 问&#xf…

Open-Vocabulary Object Detection Using Captions论文讲解

文章目录一、论文前言二、提出原因三、论文的核心四、论文讲解4.1 论文流程4.2 OVD与之前相关的setting4.3 结果对比一、论文前言 目标检测是人工智能最突出的应用之一&#xff0c;也是深度学习最成功的任务之一。 然而&#xff0c;尽管深度对象检测取得了巨大进步&#xff0…

MongoDB在银行海量历史订单交易数据查询中的应用(Spring boot + Bee)

MongoDB在银行海量历史订单交易数据查询中的应用(Spring boot Bee) 近年来,随着各种便捷支付方式的普及,银行账户交易数据呈现爆炸式增长,同时数据模型也在不断变化,传统关系型数据库已难以满足这种海量的、模式灵活、高可用、高性能的数据存储和查询需求。通过对银行历史交易…

【编程入门】应用市场(php版)

背景 前面已输出多个系列&#xff1a; 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 《N种编程语言做个记事本》 目标 为编程初学者打造入门学习项目&#xff0c;使…