C++入门编程实战(一)图书信息管理系统

开发语言: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);
}



猜你喜欢

转载自blog.csdn.net/qq_36616692/article/details/80613050