C++实现图书管理系统:类设计与文件操作详解

陆景行
陆景行
发布时间:2026-10-16 | 6人浏览过
原创

介绍如何使用C++控制台应用程序构建图书管理系统,重点讲解数据结构封装、二进制文件持久化存储(写入/读取/删除)及命令行交互逻辑,提供可直接编译的完整源码。

系统需求与功能目标

本实例旨在解决基础数据存储与检索问题,主要具备以下核心功能:

  1. 添加新书:录入书名、ISBN编号、价格及作者,并持久化保存到本地数据文件。
  2. 浏览记录:分页显示所有已入库的图书记录,便于用户查阅。
  3. 删除图书:根据记录的逻辑索引移除指定图书,实现文件数据的更新。

系统界面预览

程序运行于Windows控制台环境下,初始化窗口尺寸以提高阅读体验。

类结构设计 (Book.h)

使用 CBook 类封装图书实体,定义最大长度常量以确保内存安全。核心字段包括名称、ISBN、价格和作者,均为字符数组类型。

#define NUM1 128
#define NUM2 50
class CBook{
public:
    CBook(){}
    CBook(char* cName,char*cIsbn,char* cPrice,char* cAuthor);
    ~CBook(){}
public:
    char* GetName();
    void SetName(char* cName);
    char* GetIsbn();
    void SetIsbn(char* clsbn);
    char* GetPrice();
    void SetPrice(char* cPrice);
    char* GetAuthor();
    void SetAuthor(char* cAuthor);
    void WriteData();
    void DeleteData(int iCount);
    void GetBookFromFile(int iCount);
protected:
    char m_cName[NUM1];
    char m_cIsbn[NUM1];
    char m_cPrice[NUM2];
    char m_cAuthor[NUM2];
};

核心业务逻辑实现

第1步:初始化对象与安全赋值

构造函数接收各属性参数,使用 strncpy_s 函数将输入复制至成员变量,防止缓冲区溢出。

CBook::CBook(char* cName, char*cIsbn, char* cPrice, char* cAuthor){
    strncpy_s(m_cName,cName,NUM1);
    strncpy_s(m_cIsbn, cIsbn, NUM1);
    strncpy_s(m_cPrice, cPrice, NUM2);
    strncpy_s(m_cAuthor, cAuthor, NUM2);
}

第2步:数据写入 (WriteData)

以追加模式打开二进制文件 book.dat,使用 ofile.write 逐块写入固定长度的字符数据。此方法简单高效,但适用于结构固定的场景。

void CBook::WriteData()
{
    ofstream ofile;
    ofile.open("book.dat", ios::binary | ios::app);
    try {
        ofile.write(m_cName, NUM1);
        ofile.write(m_cIsbn, NUM1);
        ofile.write(m_cPrice, NUM2);
        ofile.write(m_cAuthor, NUM2);
    }
    catch (...) {
        throw "file error occurred";
        ofile.close();
    }
    ofile.close();
}

第3步:按索引读取数据 (GetBookFromFile)

通过计算字节偏移量 (iCount * record_size) 定位到特定记录,依次读取各字段并同步至当前对象内部状态。

void CBook::GetBookFromFile(int iCount)
{
    // ... 省略部分临时变量声明 ...
    ifstream ifile;
    ifile.open("book.dat", ios::binary);
    try {
        // 移动文件指针到指定记录位置
        ifile.seekg(iCount*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);
        ifile.read(cName, NUM1);
        // ... 依次读取其他字段 ... 
    } catch (...) {
        throw "file error occurred";
        ifile.close();
    }
    ifile.close();
}

第4步:非破坏性删除策略 (DeleteData)

由于二进制文件直接修改中间段落会导致后续数据错位,系统采用“中转站”机制。先创建临时文件 temp.dat,跳过待删除行后继续拷贝剩余数据,最后覆盖原文件并清理临时文件。

void CBook::DeleteData(int iCount)
{
    fstream file, tmpfile, ofile;
    char cTempBuf[NUM1 + NUM1 + NUM2 + NUM2];
    // 打开源文件和临时文件
    file.open("book.dat", ios::binary | ios::in | ios::out);
    tmpfile.open("temp.dat", ios::binary | ios::in | ios::out | ios::trunc);
    
    // 计算总条数
    file.seekg(0, ios::end);
    long respos = file.tellg();
    int iDataCount = respos / (NUM1 + NUM1 + NUM2 + NUM2);
    
    // 验证索引范围
    if (iCount <=0 || iCount >= iDataCount) { /* 错误处理 */ }
    else {
        // 跳过要删除的记录
        file.seekg((iCount)*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);
        for (int j = 0; j<(iDataCount - iCount); j++) {
            file.read(cTempBuf, sizeof(cTempBuf));
            tmpfile.write(cTempBuf, sizeof(cTempBuf));
        }
        // 将临时文件内容写回原文件
        tmpfile.seekg(0, ios::beg);
        ofile.open("book.dat");
        // ... 拷贝逻辑 ... 
    }
    remove("temp.dat");
}

控制台交互与主入口

主程序通过 ShowRootMenu 展示选项,使用 switch 语句分发逻辑。其中 ViewData 支持翻页浏览,每页固定显示20条记录。

void main()
{
    SetScreenGrid();
    SetSysCaption("图书管理系统");
    mainloop();
}

排错与注意事项

  • 编译器差异:代码使用了 gets_s 和 strncpy_s,建议在Visual Studio环境下编译;Linux/Mac下可能需替换为标准库函数或开启POSIX兼容。
  • 文件路径:数据文件 book.dat 默认保存在程序工作目录下,确保运行目录有写入权限。
  • 逻辑边界:DeleteData 中的索引为从0开始的整数,超出范围时应抛出异常或提示用户。

以上就是C++实现图书管理系统的详细内容,更多关于C++文件操作与面向对象实践的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表