C++实现图书管理系统:类设计与文件操作详解
介绍如何使用C++控制台应用程序构建图书管理系统,重点讲解数据结构封装、二进制文件持久化存储(写入/读取/删除)及命令行交互逻辑,提供可直接编译的完整源码。
系统需求与功能目标
本实例旨在解决基础数据存储与检索问题,主要具备以下核心功能:
- 添加新书:录入书名、ISBN编号、价格及作者,并持久化保存到本地数据文件。
- 浏览记录:分页显示所有已入库的图书记录,便于用户查阅。
- 删除图书:根据记录的逻辑索引移除指定图书,实现文件数据的更新。
系统界面预览
程序运行于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++文件操作与面向对象实践的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









