开发语言:C++
开发环境:VS2017
程序说明:图书管理系统分为三个模块:添加新书、浏览全部、删除图书。
三个文件分别是Book.h(包括Book类的声明)、Book.cpp(包括Book类中各方法的具体实现)、main.cpp(包括主函数及各模块的设计)
图书管理系统主界面如图
添加新书界面
浏览全部
Book.h代码如下
#pragma once #define NUM1 128 //图书名称和Isbn编号最大长度 #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();//获取图书ISBN编号 void SetIsbn(char* cIsbn);//设置图书ISBN编号 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]; };
Book.cpp代码如下
#include "Book.h" #include <string.h> #include <fstream> #include <iostream> #include <iomanip> using namespace std; CBook::CBook(char* cName, char* cIsbn, char* cPrice, char* cAuthor) { strncpy(m_cName, cName, NUM1); strncpy(m_cIsbn, cIsbn, NUM1); strncpy(m_cPrice, cPrice, NUM2); strncpy(m_cAuthor, cAuthor, NUM2); } char* CBook::GetName() { return m_cName; } void CBook::SetName(char* cName) { strncpy(m_cName, cName, NUM1); } char* CBook::GetIsbn() { return m_cIsbn; } void CBook::SetIsbn(char* cIsbn) { strncpy(m_cName, cIsbn, NUM1); } char* CBook::GetPrice() { return m_cPrice; } void CBook::SetPrice(char* cPrice) { strncpy(m_cPrice, cPrice, NUM2); } char* CBook::GetAuthor() { return m_cAuthor; } void CBook::SetAuthor(char* cAuthor) { strncpy(m_cAuthor, cAuthor, NUM2); } //函数WriteDate,GetBookFromFile,DeleteData是类对象对写文件的函数,相当于操作数据库的接口 void CBook::WriteData() { ofstream ofile; ofile.open("book.dat", ios::binary | ios::app);//以二进制格式(binary)打开book.dat, app:每次写操作前均定位到文件末尾 try { ofile.write(m_cName, NUM1);//写入图书的信息 ofile.write(m_cIsbn, NUM1); ofile.write(m_cPrice, NUM2); ofile.write(m_cAuthor, NUM2); } catch (...) {//catch(…)能够捕获多种数据类型的异常对象 throw "file error occurred"; ofile.close(); } ofile.close(); } //成员函数DeleteData负责将图书信息从文件中删除 void CBook::DeleteData(int iCount) {//删掉第iCount条记录 long respos; int iDataCount = 0; /*头文件fstarem定义了3各类型来支持文件IO,ifstream从一个给定文件读取数据, ofatream向一个给定文件写入数据,以及fstream可以读写给定文件*/ fstream file; fstream tmpfile; ofstream ofile; char cTempBuf[NUM1 + NUM1 + NUM2 + NUM2]; file.open("book.dat", ios::binary | ios::in | ios::out);//二进制/读/写 tmpfile.open("temp.dat", ios::binary | ios::out | ios::in | ios::trunc); /*seekg()是对输入文件定位,它有两个参数:第一个参数是偏移量,第二个参数是基地址。*/ file.seekg(0, ios::end); //基地址为文件结束处,偏移地址为0,于是指针定位在文件结束处 respos = file.tellg();//返回当前定位指针的位置,也代表着输入流的大小。 iDataCount = respos / (NUM1 + NUM1 + NUM2 + NUM2);//总记录数=文件大小/基本量 if (iCount<0 || iCount>iDataCount) { throw "Input number error"; } else {//从第iCount+1条记录开始,将以后的记录先存至中间文件变量tmpfile,后将tmpfile的内容覆盖掉iCount条记录之后的内容,相当于删掉了第iCount条记录 file.seekg((iCount)*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);//基地址为文件头,偏移量为基本量*iCount,即读写指针指向了第iCount条记录的起始位置 for (int j = 0; j < (iDataCount - iCount); j++) {//将第iCount条记录后的记录先存入tmpfile memset(cTempBuf, 0, NUM1 + NUM1 + NUM2 + NUM2);//将cTempBuf清零 file.read(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);//将file中的一条记录读入cTempBuf tmpfile.write(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);//将cTempBuf中的一条记录写入tmpfile } file.close(); tmpfile.seekg(0, ios::beg);//将指针定位在文件头 ofile.open("book.dat"); ofile.seekp((iCount - 1)*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg);//将指针定位到第iCount-1条记录的结束位置 for (int i = 0; i < (iDataCount - iCount); i++) { memset(cTempBuf, 0, NUM1 + NUM1 + NUM2 + NUM2); tmpfile.read(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2); ofile.write(cTempBuf, NUM1 + NUM1 + NUM2 + NUM2);//将cTempBuf中的一条记录写入ofile } } tmpfile.close(); ofile.close(); remove("temp.dat"); } //成员函数GetBookFromFile从文件中读取数据来构建对象 void CBook::GetBookFromFile(int iCount) { char cName[NUM1]; char cIsbn[NUM1]; char cPrice[NUM2]; char cAuthor[NUM2]; ifstream ifile; ifile.open("book.dat", ios::binary); try { ifile.seekg(iCount*(NUM1 + NUM1 + NUM2 + NUM2), ios::beg); ifile.read(cName, NUM1); if (ifile.tellg() > 0) strncpy(m_cName, cName, NUM1); ifile.read(cIsbn, NUM1); if (ifile.tellg() > 0) strncpy(m_cIsbn, cIsbn, NUM1); ifile.read(cPrice, NUM2); if (ifile.tellg() > 0) strncpy(m_cPrice, cPrice, NUM2); ifile.read(cAuthor, NUM2); if (ifile.tellg() > 0) strncpy(m_cAuthor, cAuthor, NUM2); } catch (...) { throw "file error occured"; ifile.close(); } ifile.close(); }
main.cpp代码如下
#include <iostream> #include <iomanip> #include <stdlib.h> #include <conio.h> #include <string.h> #include <fstream> #include "Book.h" #define CMD_COLS 80 #define CMD_LINES 25 using namespace std; void SetScreenGrid();//设置屏幕显示的行数和列数 void ClearScreen();//清除屏幕信息 void SetSysCaption(const char *pText);//设置窗体标题栏 void ShowWelcome();//显示欢迎信息 void ShowRootMenu();//显示开始菜单 void WaitView(int iCurPage);//浏览数据时等待用户操作 void WaitUser();//等待用户操作 void GuideInput();//使用向导添加图书信息 int GetSelect();//获得用户菜单选择 long GetFileLength(ifstream &ifs);//获取文件长度 void ViewData(int iSelPage);//浏览所有图书记录 void DeleteBookFromFile();//在文件中产生图书信息 void mainloop();//主循环 void main() { SetScreenGrid(); SetSysCaption("图书管理系统"); mainloop(); } void SetScreenGrid() { char sysSetBuf[80]; sprintf(sysSetBuf, "mode con cols=%d lines=%d", CMD_COLS, CMD_LINES); system(sysSetBuf); } void SetSysCaption() { system("title Sample"); } void SetSysCaption(const char *pText) { char sysSetBuf[80]; sprintf(sysSetBuf, "title %s", pText); system(sysSetBuf); } void ClearScreen() { system("cls"); } void ShowWelcome() { for (int i = 0; i < 7; i++) { cout << endl; } cout << setw(40); cout << "******************" << endl; cout << setw(40); cout << "***图书管理系统***" << endl; cout << setw(40); cout << "******************" << endl; } void ShowRootMenu() { cout << setw(35); cout << "请选择功能" << endl; cout << endl; cout << setw(35); cout << "1 添加新书" << endl; cout << endl; cout << setw(35); cout << "2 浏览全部" << endl; cout << endl; cout << setw(35); cout << "3 删除图书" << endl; cout << endl; } void WaitUser() { int iInputPage = 0; cout << "enter 返回主菜单 q退出" << endl; char buf[256]; gets_s(buf); if (buf[0] == 'q') system("exit"); } void mainloop(){ ShowWelcome(); while (1) { ClearScreen(); ShowWelcome(); ShowRootMenu(); switch (GetSelect()) { case 1: ClearScreen(); GuideInput(); break; case 2: ClearScreen(); ViewData(1); break; case 3: ClearScreen(); DeleteBookFromFile(); break; } } } int GetSelect() { char buf[256]; gets_s(buf); return atoi(buf); } void GuideInput() { char inName[NUM1]; char inIsbn[NUM1]; char inPrice[NUM2]; char inAuthor[NUM2]; cout << "输入书名" << endl; cin >> inName; cout << "输入Isbn" << endl; cin >> inIsbn; cout << "输入价格" << endl; cin >> inPrice; cout << "输入作者" << endl; cin >> inAuthor; CBook book(inName, inIsbn, inPrice, inAuthor); book.WriteData(); cout << "Write Finish" << endl; WaitUser(); } void ViewData(int iSelPage=1)//浏览图书 { int iPage = 0;//总页数 int iCurPage = 0;//当前页数 int iDataCount = 0;//总书数 char inName[NUM1]; char inIsbn[NUM1]; char inPrice[NUM2]; char inAuthor[NUM2]; bool bIndex = false; int iFileLength; iCurPage = iSelPage; ifstream ifile; ifile.open("book.dat", ios::binary); iFileLength = GetFileLength(ifile); iDataCount = iFileLength / (NUM1 + NUM1 + NUM2 + NUM2);//根据文件长度,计算文件中总记录数 if (iDataCount >= 1) bIndex = true; iPage = iDataCount / 20 + 1; ClearScreen();//清除屏幕信息 cout << "共有记录" << iDataCount << " "; cout << "共有页数" << iPage << " "; cout << "当前页数" << iCurPage << " "; cout << "n 显示下一页 m 返回" <<endl; cout << setw(3) << "Index"; cout << setw(20) << "Name"<<setw(24)<<"Isbn"; cout << setw(15) << "Price" << setw(13) << "Author"; cout << endl; try { //根据图书记录编号查找在文件中的位置 ifile.seekg((iCurPage - 1) * 20 * (NUM1 + NUM1 + NUM2 + NUM2), ios::beg);//偏移量=页数*基本量,从文件头开始 if (!ifile.fail()) { for (int i = 1; i < 21; i++) { memset(inName, 0, 128);//清零 memset(inIsbn, 0, 128); memset(inPrice, 0, 50); memset(inAuthor, 0, 50); if (bIndex) {//找到了书 cout << setw(3) << ((iCurPage - 1) * 20 + i);//多输出了一个索引 ifile.read(inName, NUM1); cout << setw(24) << inName; ifile.read(inIsbn, NUM1); cout << setw(24) << inIsbn; ifile.read(inPrice, NUM2); cout << setw(12) << inPrice;//闪退原因是将这里的12误写成了24.。。。。。。 ifile.read(inAuthor, NUM2); cout << setw(12) << inAuthor; cout << endl; } if (ifile.tellg() < 0) bIndex = false; else bIndex = true; } } } catch (...) { cout << "throw file exception" << endl; throw "file error occurred";//抛出异常 ifile.close(); } if (iCurPage < iPage) { iCurPage = iCurPage + 1; WaitView(iCurPage);//等待用户处理 } else { WaitView(iCurPage); } ifile.close(); } long GetFileLength(ifstream &ifs) { long temppos; long respos; temppos = ifs.tellg(); ifs.seekg(0, ios::end); respos = ifs.tellg(); ifs.seekg(temppos, ios::beg); return respos; } void DeleteBookFromFile() {// int iDelCount; cout << "Input delete index" << endl; cin >> iDelCount; CBook tmpbook; tmpbook.DeleteData(iDelCount); cout << "Delete Finish" << endl; WaitUser(); } void WaitView(int iCurPage) { char buf[256]; gets_s(buf); if (buf[0] == 'q') system("exit"); if (buf[0] == 'm') mainloop(); if (buf[0] == 'n') ViewData(iCurPage); }