基于MYSQL的图书管理系统(C/C++实现)

news/2024/12/23 3:03:02 标签: c语言, c++, 开发语言

一、设计目的

通过该设计,应能理解并掌握C++面向对象,连接数据库的方法,对C++语言有更深刻的理解。
使用clion,以及mysql8.0

二、数据库表

--图书管理系统的数据库建表语句
DROP TABLE IF EXISTS Books;
CREATE TABLE Books (
no INT(7) NOT NULL PRIMARY KEY,           -- 图书编号,7位整数
bookName VARCHAR(255) NOT NULL,            -- 书名,
author VARCHAR(255) NOT NULL,               -- 作者,
publisher VARCHAR(255) NOT NULL,           -- 出版社,
price DECIMAL(10,2) NOT NULL,             -- 价格,最大1000
category ENUM('文学','科学','自然','名著') NOT NULL  -- 分类,限定可选值
)


三、核心代码

#include <iostream>
#include <mysql.h>
#include <string>
using namespace std;

MYSQL *conn;
// 数据库的结果对象
MYSQL_RES *res;
MYSQL_ROW row;

// 验证图书编号是否重复
bool isNoExists(int no)
{
    string query = "SELECT COUNT(*) FROM Books WHERE no = " + to_string(no);
    mysql_query(conn, query.c_str());
    res = mysql_store_result(conn);
    row = mysql_fetch_row(res);
    int count = atoi(row[0]);
    mysql_free_result(res);
    return count > 0;
}

// 输入验证函数
int inputNo()
{
    cout << "请输入图书编号(编号必须是7位数,并且不可以重复)" << endl;
    int no;
    cin >> no;
    while (no < 1000000 || no > 9999999 || isNoExists(no))
    {
        if (isNoExists(no))
        {
            cout << "编号已存在,请重新输入" << endl;
        }
        else
        {
            cout << "编号必须是7位数" << endl;
        }
        cin >> no;
    }
    return no;
}

// 验证书名输入
string inputbookName()
{
    cout << "请输入图书的名称(名称必须1-20字)" << endl;
    string bookName;
    cin >> bookName;
    while (bookName.size() < 1 || bookName.size() > 20)
    {
        cout << "名字的长度必须是1-20位,请重新输入。" << endl;
        cin >> bookName;
    }
    return bookName;
}

// 验证作者输入
string inputAuthor()
{
    cout << "请输入作者的名字(名称必须2-8位)" << endl;
    string author;
    cin >> author;
    while (author.size() < 2 || author.size() > 8)
    {
        cout << "作者名字的长度必须是2-8位,请重新输入。" << endl;
        cin >> author;
    }
    return author;
}

// 验证出版社输入
string inputPublisher()
{
    cout << "请输入出版社名称(名称必须2-20位)" << endl;
    string publisher;
    cin >> publisher;
    while (publisher.size() < 2 || publisher.size() > 20)
    {
        cout << "出版社的长度必须是2-20位,请重新输入。" << endl;
        cin >> publisher;
    }
    return publisher;
}

// 验证价格输入
double inputPrice()
{
    cout << "请输入图书价格(价格1 - 1000)" << endl;
    double price;
    cin >> price;
    while (price < 1 || price > 1000)
    {
        cout << "价格必须在1-1000之间,请重新输入。" << endl;
        cin >> price;
    }
    return price;
}

// 验证分类输入
string inputCategory()
{
    cout << "请输入图书的类别(文学 科学 自然 名著)" << endl;
    string category;
    cin >> category;
    while (category != "文学" && category != "科学" &&
           category != "自然" && category != "名著")
    {
        cout << "图书的类别必须是(文学 科学 自然 名著)之一,请重新输入。" << endl;
        cin >> category;
    }
    return category;
}

// 添加图书
void add()
{
    int no = inputNo();
    string bookName = inputbookName();
    string author = inputAuthor();
    string publisher = inputPublisher();
    double price = inputPrice();
    string category = inputCategory();

    // 为字符串进行转义
    char escaped_bookName[100];
    char escaped_author[100];
    char escaped_publisher[100];
    char escaped_category[100];

    mysql_real_escape_string(conn, escaped_bookName, bookName.c_str(), bookName.length());
    mysql_real_escape_string(conn, escaped_author, author.c_str(), author.length());
    mysql_real_escape_string(conn, escaped_publisher, publisher.c_str(), publisher.length());
    mysql_real_escape_string(conn, escaped_category, category.c_str(), category.length());

    // 使用预处理语句
    string query = "INSERT INTO Books(no, bookName, author, publisher, price, category) "
                   "VALUES (?, ?, ?, ?, ?, ?)";

    MYSQL_STMT *stmt = mysql_stmt_init(conn);
    if (!stmt)
    {
        cout << "初始化预处理语句失败" << endl;
        return;
    }

    if (mysql_stmt_prepare(stmt, query.c_str(), query.length()))
    {
        cout << "预处理语句准备失败: " << mysql_stmt_error(stmt) << endl;
        mysql_stmt_close(stmt);
        return;
    }

    MYSQL_BIND bind[6];
    memset(bind, 0, sizeof(bind));

    bind[0].buffer_type = MYSQL_TYPE_LONG;
    bind[0].buffer = &no;

    bind[1].buffer_type = MYSQL_TYPE_STRING;
    bind[1].buffer = escaped_bookName;
    bind[1].buffer_length = strlen(escaped_bookName);

    bind[2].buffer_type = MYSQL_TYPE_STRING;
    bind[2].buffer = escaped_author;
    bind[2].buffer_length = strlen(escaped_author);

    bind[3].buffer_type = MYSQL_TYPE_STRING;
    bind[3].buffer = escaped_publisher;
    bind[3].buffer_length = strlen(escaped_publisher);

    bind[4].buffer_type = MYSQL_TYPE_DOUBLE;
    bind[4].buffer = &price;

    bind[5].buffer_type = MYSQL_TYPE_STRING;
    bind[5].buffer = escaped_category;
    bind[5].buffer_length = strlen(escaped_category);

    if (mysql_stmt_bind_param(stmt, bind))
    {
        cout << "参数绑定失败: " << mysql_stmt_error(stmt) << endl;
        mysql_stmt_close(stmt);
        return;
    }

    if (mysql_stmt_execute(stmt))
    {
        cout << "添加失败: " << mysql_stmt_error(stmt) << endl;
    }
    else
    {
        cout << "添加成功" << endl;
    }

    mysql_stmt_close(stmt);
}

// 显示图书列表
void list()
{
    if (mysql_query(conn, "SELECT * FROM Books"))
    {
        cout << "查询失败: " << mysql_error(conn) << endl;
        return;
    }

    res = mysql_store_result(conn);
    cout << "编号\t书名\t作者\t出版社\t价格\t分类" << endl;

    while ((row = mysql_fetch_row(res)))
    {
        cout << row[0] << "\t" << row[1] << "\t" << row[2] << "\t"
             << row[3] << "\t" << row[4] << "\t" << row[5] << endl;
    }

    mysql_free_result(res);
}

// 根据编号删除
void delByNo()
{
    cout << "输入需要删除图书的编号" << endl;
    int no;
    cin >> no;

    string query = "DELETE FROM Books WHERE no = " + to_string(no);

    if (mysql_query(conn, query.c_str()) == 0)
    {
        if (mysql_affected_rows(conn) > 0)
        {
            cout << "删除成功" << endl;
        }
        else
        {
            cout << "未找到该编号的图书" << endl;
        }
    }
    else
    {
        cout << "删除失败: " << mysql_error(conn) << endl;
    }
}

// 根据书名删除
void delByName()
{
    cout << "请输入需要删除的图书名称:" << endl;
    string bookName;
    cin >> bookName;

    string query = "DELETE FROM Books WHERE bookName = '" + bookName + "'";

    if (mysql_query(conn, query.c_str()) == 0)
    {
        int count = mysql_affected_rows(conn);
        if (count > 0)
        {
            cout << "删除成功,本次删除了" << count << "本" << endl;
        }
        else
        {
            cout << "未找到该书名的图书" << endl;
        }
    }
    else
    {
        cout << "删除失败: " << mysql_error(conn) << endl;
    }
}

// 删除功能选择
void del()
{
    cout << "选择删除方式 1.根据图书编号删除 2.根据图书书名删除" << endl;
    int type;
    cin >> type;
    if (type == 1)
    {
        delByNo();
    }
    else if (type == 2)
    {
        delByName();
    }
    else
    {
        cout << "输入错误" << endl;
        del();
    }
}

// 根据编号查询
void searchByNo()
{
    cout << "请输入要查询的图书编号" << endl;
    int no;
    cin >> no;

    string query = "SELECT * FROM Books WHERE no = " + to_string(no);

    if (mysql_query(conn, query.c_str()) == 0)
    {
        res = mysql_store_result(conn);
        if ((row = mysql_fetch_row(res)))
        {
            cout << "\n编号\t书名\t作者\t出版社\t价格\t分类" << endl;
            cout << row[0] << "\t" << row[1] << "\t" << row[2] << "\t"
                 << row[3] << "\t" << row[4] << "\t" << row[5] << endl;
        }
        else
        {
            cout << "该编号不存在" << endl;
        }
        mysql_free_result(res);
    }
    else
    {
        cout << "查询失败: " << mysql_error(conn) << endl;
    }
}

// 根据书名查询
void searchByName()
{
    cout << "请输入要查询的图书名字" << endl;
    string bookName;
    cin >> bookName;

    string query = "SELECT * FROM Books WHERE bookName = '" + bookName + "'";

    if (mysql_query(conn, query.c_str()) == 0)
    {
        res = mysql_store_result(conn);
        bool found = false;

        while ((row = mysql_fetch_row(res)))
        {
            if (!found)
            {
                cout << "\n编号\t书名\t作者\t出版社\t价格\t分类" << endl;
                found = true;
            }
            cout << row[0] << "\t" << row[1] << "\t" << row[2] << "\t"
                 << row[3] << "\t" << row[4] << "\t" << row[5] << endl;
        }

        if (!found)
        {
            cout << "该图书不存在" << endl;
        }
        mysql_free_result(res);
    }
    else
    {
        cout << "查询失败: " << mysql_error(conn) << endl;
    }
}

// 查询功能选择
void searchBook()
{
    cout << "请选择查询方式:" << endl;
    cout << "1. 按编号查询" << endl;
    cout << "2. 按书名查询" << endl;

    int type;
    cin >> type;

    if (type == 1)
    {
        searchByNo();
    }
    else if (type == 2)
    {
        searchByName();
    }
    else
    {
        cout << "输入错误,请重新输入" << endl;
        searchBook();
    }
}

// 修改图书信息
void modifyBook()
{
    cout << "请输入要修改的图书编号:" << endl;
    int oldNo;
    cin >> oldNo;

    string query = "SELECT * FROM Books WHERE no = " + to_string(oldNo);

    if (mysql_query(conn, query.c_str()) == 0)
    {
        res = mysql_store_result(conn);
        if ((row = mysql_fetch_row(res)))
        {
            cout << "当前图书信息:" << endl;
            cout << "编号\t书名\t作者\t出版社\t价格\t分类" << endl;
            cout << row[0] << "\t" << row[1] << "\t" << row[2] << "\t"
                 << row[3] << "\t" << row[4] << "\t" << row[5] << endl;

            mysql_free_result(res);

            // 输入新信息
            int newNo = inputNo();
            string bookName = inputbookName();
            string author = inputAuthor();
            string publisher = inputPublisher();
            double price = inputPrice();
            string category = inputCategory();

            query = "UPDATE Books SET no = " + to_string(newNo) +
                    ", bookName = '" + bookName +
                    "', author = '" + author +
                    "', publisher = '" + publisher +
                    "', price = " + to_string(price) +
                    ", category = '" + category +
                    "' WHERE no = " + to_string(oldNo);

            if (mysql_query(conn, query.c_str()) == 0)
            {
                cout << "修改成功" << endl;
            }
            else
            {
                cout << "修改失败: " << mysql_error(conn) << endl;
            }
        }
        else
        {
            cout << "该编号不存在" << endl;
            mysql_free_result(res);
        }
    }
    else
    {
        cout << "查询失败: " << mysql_error(conn) << endl;
    }
}

// 主菜单选择功能
void choose(int input)
{
    system("cls");
    switch (input)
    {
    case 1:
        cout << "你选择了添加功能" << endl;
        add();
        break;
    case 2:
        cout << "你选择了删除功能" << endl;
        del();
        break;
    case 3:
        cout << "你选择了修改功能" << endl;
        modifyBook();
        break;
    case 4:
        cout << "你选择了列表功能" << endl;
        list();
        break;
    case 5:
        cout << "你选择了查询功能" << endl;
        searchBook();
        break;
    case 0:
        cout << "退出系统" << endl;
        return;
    default:
        cout << "功能码错误" << endl;
    }

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

int main()
{
    // 初始化数据库连接
    conn = mysql_init(NULL);

    // 设置数据库编码为 utf8
    mysql_options(conn, MYSQL_SET_CHARSET_NAME, "utf8");

    // 设置控制台输出编码为 UTF-8
    system("chcp 65001");

    // 连接数据库
    if (!mysql_real_connect(conn, "localhost", "root", "123456", "cppbook", 3306, NULL, 0))
    {
        cout << "数据库连接失败: " << mysql_error(conn) << endl;
        return 1;
    }

    // 设置连接字符集
    mysql_set_character_set(conn, "utf8");

    cout << "数据库连接成功!" << endl;

    int input = 1;
    while (input != 0)
    {
        cout << "1.添加图书" << endl;
        cout << "2.删除图书" << endl;
        cout << "3.修改图书" << endl;
        cout << "4.图书列表" << endl;
        cout << "5.图书查询" << endl;
        cout << "0.退出系统" << endl;
        cout << "输入选择功能(0-5)" << endl;

        cin >> input;
        choose(input);
    }

    // 关闭数据库连接
    mysql_close(conn);
    return 0;
}

四、运行界面

1.添加界面

在这里插入图片描述

2.列表功能

在这里插入图片描述

3.修改图书

在这里插入图片描述

4.查询图书

在这里插入图片描述

在这里插入图片描述

5.删除图书

在这里插入图片描述
在这里插入图片描述

六、总结

通过本次课设,加深了我对《C++程序设计》课程的理论知识的巩固、理解和掌握以及综合应用能力的锻炼。在课程设计期间与老师探讨写代码遇到的问题,也学会了怎么独立的去解决问题,培养了我们查阅资料、独立思考、刻苦钻研和创新的意识。将书本上抽象的概念与具体的实现技术相结合,体会C++语言的设计与实现过程,培养解决问题的实际能力。
通过该设计,理解并掌握了C++面向对象,连接数据库和使用文件流的方法,对C++语言有更深刻的理解,希望以后会在这次基础上完成更多的项目,不断地积累和学习。


http://www.niftyadmin.cn/n/5796248.html

相关文章

前端面试题整理-前端异步编程

1. 进程、线程、协程的区别 在并发编程领域&#xff0c;进程、线程和协程是三个核心概念&#xff0c;它们在资源管理、调度和执行上有着本质的不同。 首先&#xff0c;进程是操作系统进行资源分配和调度的独立单位&#xff08;资源分配基本单位&#xff09;&#xff0c;每个进…

2024年港澳台华侨生联考师范类院校录取情况来

导读 师范类大学一直是在港澳台华侨生联考中&#xff0c;最受瞩目的学校类型之一&#xff0c;今天我们就跟大家一块来盘点一下2024年的港澳台联考中&#xff0c;师范类大学的录取分数线情况。&#xff08;景于行提示您&#xff1a;我们给您提供的分数线数据真实可靠&#xff0…

STM32 HAL库之配置数据FLASH存储

设计需求 在项目开发中&#xff0c;经常需要保存配置数据至非易失性存储介质中&#xff08;Flash 或EEPROM中&#xff09;&#xff0c;以便上电重启后获取配置信息。常见的STM32开发中&#xff0c;一般将数据存储在FLASH、备份区域寄存器、外挂EEPROM。由于内部Flash不能像EEPR…

“魔法糖果盒的秘密:用朴素贝叶斯算法猜糖果颜色”

想象一下&#xff0c;你有一个神奇的糖果盒&#xff0c;这个糖果盒里有两种糖果&#xff1a;红色的和蓝色的。你闭上眼睛&#xff0c;从盒子里拿出一个糖果&#xff0c;然后尝一尝&#xff0c;你想知道这个糖果是红色的还是蓝色的。朴素贝叶斯算法就像是一个魔法规则&#xff0…

Glide 自定义圆角、铺满FitXY

在 Android 开发中&#xff0c;使用 Glide 来加载图片时&#xff0c;有时需要对图片进行特定的处理&#xff0c;比如设置圆角或者使图片完全填充到一个视图中&#xff08;类似于 ImageView 的 scaleType 中的 FitXY&#xff09;。以下是如何使用 Glide 来实现这些自定义需求的处…

Linux —— 搭建Apache服务器

一、基本概念 定义 Apache 服务器&#xff08;全称 Apache HTTP Server&#xff09;是一款开源的、跨平台的 Web 服务器软件。它通过 HTTP 协议提供网页服务&#xff0c;能够将存储在服务器上的网页文件&#xff08;如 HTML 文件、图片、脚本等&#xff09;发送给客户端&#…

OpenAI发布全新AI模型 o3 与 o3-mini:推理与编码能力迎来重大突破. AGI 来临

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

鸿蒙UI开发——组件滤镜效果

1、概 述 ArkUI为组件提供了滤镜效果设置&#xff0c;背景滤镜、前景滤镜、合成滤镜。我们可以通过以下方式为组件设置对应的滤镜效果。 Text(前景滤镜)// ..其他属性.foregroundFilter(filterTest1) // 通过 foregroundFilter 设置模糊效果Text(背景滤镜)// ...其他属性.bac…