第一个问题:在编入了新书或是新读者之后,如果关闭了程序再次打开,则查找、删除等功能无法实现。问题出在再次打开程序时,调用的是无参构造函数,导致没有从文件读入数据。但是如果把构造函数中我写的分三种情况初始化的代码也写入无参构造函数,会导致初始化读者函数(Borrower_initialize)和初始化图书函数(Library_initialize)与构造函数反复调用,程序无法正确运行,陷入死循环。这里如何正确修改?
第二个问题:我在实现借书和还书两个功能时候,在尝试把借书人的信息和书籍信息进行关联的时候,是按照我代码中目前Library类中borrow_book函数里注释掉的部分进行的,但是这样并不能正确运行。借书和还书两个功能如何正确实现?
以下附上没有进行“把构造函数中我写的分三种情况初始化的代码也写入无参构造函数”的代码
#include<iostream>
#include<fstream>
#include<string>
#define BOOKFILE "BookFile.txt"//存放图书信息的文档
#define BORROWERFILE "BorrowerFile.txt"//存放读者信息的文档
using namespace std;
//图书信息结构体
struct Book_struct
{
string m_book_name;//图书名称
int m_book_id;//图书编号
float m_book_price;//单价。考虑到单价不一定为整数,这里的数据类型使用浮点型
string m_author;//作者
bool m_loan;//存在状态。true表示状态为已经借出,标记为1;false表示未借出,可被借,标记为0
//Borrower_struct m_borrower;//此书借阅者的信息
};
//读者信息结构体
struct Borrower_struct
{
string m_borrower_name;//借书人姓名
string m_sex;//性别
int m_borrower_id;//学号
};
//读者类
class Borrower
{
public:
int borrower_num;//统计已注册的读者的数量
Borrower** m_Borrower_Array;
bool m_BORROWERFILE_empty;
Borrower_struct m_borrower;
//构造函数
Borrower(){}//用于main函数中
Borrower(string borrower_name, string sex, int borrower_id)//用于录入新读者时
{
//给结构体初始化
m_borrower.m_borrower_name = borrower_name;
m_borrower.m_sex = sex;
m_borrower.m_borrower_id = borrower_id;
//分三种情况
//第一种情况:文件不存在
ifstream ifs;
ifs.open(BORROWERFILE, ios::in | ios::binary); // 读文件
if (!ifs.is_open())
{
//初始化记录人数
this->borrower_num = 0;
//初始化数组指针
this->m_Borrower_Array = NULL;
//初始化文件是否为空
this->m_BORROWERFILE_empty = true;
ifs.close();
return;
}
//第二种情况:文件存在,数据为空
char ch;
ifs >> ch;//先读一个字符
if (ifs.eof())//如果读到的标志时eof,意思是读到头了,也就是数据为空的意思
{
//初始化记录人数
this->borrower_num = 0;
//初始化数组指针
this->m_Borrower_Array = NULL;
//初始化文件是否为空
this->m_BORROWERFILE_empty = true;
ifs.close();
return;
}
//3、文件存在,并且记录数据
int num = this->get_borrower_number();
this->borrower_num = num;
//开辟空间
this->m_Borrower_Array = new Borrower * [this->borrower_num];
//将文件中的数据 ,存到数组中
this->Borrower_initialize();
}
//初始化读者
void Borrower_initialize()
{
ifstream ifs;
ifs.open(BORROWERFILE, ios::in | ios::binary);
Borrower_struct borrower_struct;
int index = 0;
while (ifs >> borrower_struct.m_borrower_name && ifs >> borrower_struct.m_sex && ifs >> borrower_struct.m_borrower_id)
{
Borrower* borrower = NULL;
borrower = new Borrower;
this->m_Borrower_Array[index] = borrower;
index++;
}
//关闭文件
ifs.close();
}
//新读者注册函数。另外注意,不能加const,不用管此处编译器的提示。一旦增加了const,会导致不能修改该类的成员变量borrower_num,然而这个函数需要做到能修改borrower_num
void set_borrower()
{
cout << "请输入要新增读者的数量" << endl;
int add_number = 0;
cin >> add_number;
if (add_number > 0)
{
//计算新空间的大小,其中,等号右边第一项是已经存储的书的数目,第二项是新增加的书的数目
int new_size = this->borrower_num + add_number;
//开辟新空间
Borrower** new_space = new Borrower * [new_size];
//将原空间下内容存放到新空间下
if (this->m_Borrower_Array != NULL)
{
for (int i = 0; i < this->borrower_num; i++)
{
new_space[i] = this->m_Borrower_Array[i];
}
}
//输入新数据
for (int i = 0; i < add_number; i++)
{
Borrower_struct new_borrower;
cout << "请输入第 " << i + 1 << " 位新读者的名字:" << endl;
cin >> new_borrower.m_borrower_name;
cout << "请输入第 " << i + 1 << " 位新读者的性别:" << endl;
cin >> new_borrower.m_sex;
cout << "请输入第 " << i + 1 << " 位新读者的学号:" << endl;
cin >> new_borrower.m_borrower_id;
Borrower* borrower = NULL;
borrower = new Borrower(new_borrower.m_borrower_name, new_borrower.m_sex, new_borrower.m_borrower_id);
new_space[this->borrower_num + i] = borrower;
}
//释放原有空间
delete[] this->m_Borrower_Array;
//更改新空间的指向
this->m_Borrower_Array = new_space;
//更新读者数量
this->borrower_num = new_size;
//更新判断读者数量是否为空的标志为“不为空”
this->m_BORROWERFILE_empty = false;
//提示添加成功
cout << "成功添加" << add_number << "位新读者!" << endl;
//保存数据到文件中
this->save();
}
else
{
cout << "输入有误" << endl;
}
//按任意键后 清屏回到上级目录
system("pause");
system("cls");
}
//将信息写入文件
void save()
{
ofstream ofs;
ofs.open(BORROWERFILE, ios::out | ios::binary);//按照题目要求,以二进制形式存储
//将每个人数据写入到文件中
for (int i = 0; i < this->borrower_num; i++)
{
ofs << this->m_Borrower_Array[i]->m_borrower.m_borrower_name << " "
<< this->m_Borrower_Array[i]->m_borrower.m_sex << " "
<< this->m_Borrower_Array[i]->m_borrower.m_borrower_id << " " << endl;
}
//关闭文件
ofs.close();
}
//统计文件中的读者数量
int get_borrower_number()
{
ifstream ifs;
ifs.open(BORROWERFILE, ios::in | ios::binary);
Borrower_struct borrower;
int num = 0;
while (ifs >> borrower.m_borrower_name && ifs >> borrower.m_sex && ifs >> borrower.m_borrower_id)
{
//统计人数变量
num++;
}
return num;
}
//显示所有读者的信息函数中的show_one_borrower函数,该函数用于输出单个读者的信息,再通过for循环来调用该函数以输出全部读者信息
void show_one_borrower()
{
cout << "读者姓名: " << this->m_borrower.m_borrower_name
<< "\t性别: " << this->m_borrower.m_sex
<< "\t学号: " << this->m_borrower.m_borrower_id << endl;
}
//显示所有读者的信息
void show_all_borrower()
{
//判断文件是否为空
if (this->m_BORROWERFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
for (int i = 0; i < borrower_num; i++)
{
this->m_Borrower_Array[i]->show_one_borrower();
}
}
//按任意键后清屏
system("pause");
system("cls");
}
//删除某一读者
void del_borrower()
{
if (this->m_BORROWERFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
//按照读者编号删除
cout << "请输入想要删除读者编号:" << endl;
int id = 0;
cin >> id;
int index = this->borrower_exist(id);
if (index != -1) //说明读者存在,并且要删除掉index位置上的读者
{
for (int i = index; i < this->borrower_num - 1; i++)
{
//数据前移
this->m_Borrower_Array[i] = this->m_Borrower_Array[i + 1];
}
this->borrower_num--; //更新数组中记录读者个数
//数据同步更新到文件中
this->save();
cout << "删除成功!" << endl;
}
else
{
cout << "删除失败,未找到该读者" << endl;
}
}
//按任意键 清屏
system("pause");
system("cls");
}
//查询某一读者
void find_borrower()
{
if (this->m_BORROWERFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
cout << "请输入查找的方式:" << endl;
cout << "1、按目标读者的学号查找 " << endl;
cout << "2、按目标读者的姓名查找 " << endl;
int select = 0;
cin >> select;
if (select == 1)
{
//按照学号查
int id;
cout << "请输入查找的读者的学号: " << endl;
cin >> id;
int ret = borrower_exist(id);
if (ret != -1)
{
//找到目标读者
cout << "查找成功!该读者信息如下:" << endl;
this->m_Borrower_Array[ret]->show_one_borrower();
}
else
{
cout << "查找失败,查无此人" << endl;
}
}
else if (select == 2)
{
//按照姓名查
string name;
cout << "请输入目标读者的姓名:" << endl;
cin >> name;
//加入判断是否查到的标志
bool flag = false; //默认未找到读者
for (int i = 0; i < borrower_num; i++)
{
if (this->m_Borrower_Array[i]->m_borrower.m_borrower_name == name)
{
cout << "查找成功,目标读者的学号为: "
<< this->m_Borrower_Array[i]->m_borrower.m_borrower_id
<< "号读者信息如下:" << endl;
flag = true;
//调用显示信息接口
this->m_Borrower_Array[i]->show_one_borrower();
}
}
if (flag == false)
{
cout << "查找失败,查无此人!" << endl;
}
}
else
{
cout << "输入选项有误!" << endl;
}
}
//按任意键清屏
system("pause");
system("cls");
}
//判断目标读者是否存在。如果存在返回读者所在数组中的位置,不存在返回-1
int borrower_exist(int id)
{
int index = -1;
for (int i = 0; i < this->borrower_num; i++)
{
if (this->m_Borrower_Array[i]->m_borrower.m_borrower_id == id)
{
//找到目标
index = i;
break;
}
}
return index;
}
};
//图书馆类(公有继承Borrower类)
class Library:public Borrower//继承是为了在借书还书时,能够方便地调用Library类中的变量和函数
{
private:
Book_struct m_book;
int book_num;//统计已录入的图书数量
Library** m_Library_Array;
bool m_BOOKFILE_empty;
public:
//构造函数
Library(){}//用于main函数中
Library(string book_name, int book_id, float book_price, string author, bool loan)//用于录入新书时
{
//给结构体初始化
m_book.m_book_name = book_name;
m_book.m_book_id = book_id;
m_book.m_book_price = book_price;
m_book.m_author = author;
m_book.m_loan = loan;
//分三种情况
//第一种情况:文件不存在
ifstream ifs;
ifs.open(BOOKFILE, ios::in | ios::binary); // 读文件
if (!ifs.is_open())
{
//初始化记录人数
this->book_num = 0;
//初始化数组指针
this->m_Library_Array = NULL;
//初始化文件是否为空
this->m_BOOKFILE_empty = true;
ifs.close();
return;
}
//第二种情况:文件存在,数据为空
char ch;
ifs >> ch;//先读一个字符
if (ifs.eof())//如果读到的标志时eof,意思是读到头了,也就是数据为空的意思
{
//初始化记录人数
this->book_num = 0;
//初始化数组指针
this->m_Library_Array = NULL;
//初始化文件是否为空
this->m_BOOKFILE_empty = true;
ifs.close();
return;
}
//3、文件存在,并且记录数据
int num = this->get_book_number();
this->book_num = num;
//开辟空间
this->m_Library_Array = new Library * [this->book_num];
//将文件中的数据 ,存到数组中
this->Library_initialize();
}
//统计文件中的书籍数量
int get_book_number()
{
ifstream ifs;
ifs.open(BOOKFILE, ios::in | ios::binary);
Book_struct book;
int num = 0;
while (ifs >> book.m_book_name && ifs >> book.m_book_id && ifs >> book.m_book_price && ifs >> book.m_author && ifs >> book.m_loan)
{
//统计人数变量
num++;
}
return num;
}
//初始化图书
void Library_initialize()
{
ifstream ifs;
ifs.open(BOOKFILE, ios::in | ios::binary);
Book_struct book_struct;
int index = 0;
while (ifs >> book_struct.m_book_name && ifs >> book_struct.m_book_id && ifs >> book_struct.m_book_price && ifs>> book_struct.m_author && ifs >> book_struct.m_loan)
{
Library* book = NULL;
book = new Library;
this->m_Library_Array[index] = book;
index++;
}
//关闭文件
ifs.close();
}
//显示菜单的函数
void show_menu()
{
cout << "********************************************" << endl;
cout << "**********欢迎使用图书借阅管理系统**********" << endl;
cout << "************** 0.退出系统 **************" << endl;
cout << "************** 1.录入新书 **************" << endl;
cout << "************** 2.查询图书 **************" << endl;
cout << "********* 3.显示所有图书的信息 *********" << endl;
cout << "************ 4.删除某一本书 ************" << endl;
cout << "********** 5.为借书人办理注册 **********" << endl;
cout << "************** 6.查询读者 **************" << endl;
cout << "********* 7.显示所有读者的信息 *********" << endl;
cout << "************ 8.删除某一读者 ************" << endl;
cout << "**************** 9.借书 ****************" << endl;
cout << "**************** 10.还书 ****************" << endl;
cout << "********************************************" << endl;
cout << endl;
}
//录入新书函数。另外注意,不能加const,不用管此处编译器的提示。一旦增加了const,会导致不能修改该类的成员变量book_num,然而这个函数需要做到能修改book_num
void set_book()
{
cout << "请输入要新增图书的数量" << endl;
int add_number = 0;
cin >> add_number;
if (add_number > 0)
{
//计算新空间的大小,其中,等号右边第一项是已经存储的书的数目,第二项是新增加的书的数目
int new_size = this->book_num + add_number;
//开辟新空间
Library** new_space = new Library * [new_size];
//将原空间下内容存放到新空间下
if (this->m_Library_Array != NULL)
{
for (int i = 0; i < this->book_num; i++)
{
new_space[i] = this->m_Library_Array[i];
}
}
//输入新数据
for (int i = 0; i < add_number; i++)
{
Book_struct new_book;
cout << "请输入第 " << i + 1 << " 本新书的名称:" << endl;
cin >> new_book.m_book_name;
cout << "请输入第 " << i + 1 << " 本新书的编号:" << endl;
cin >> new_book.m_book_id;
cout << "请输入第 " << i + 1 << " 本新书的价格:" << endl;
cin >> new_book.m_book_price;
cout << "请输入第 " << i + 1 << " 本新书的作者:" << endl;
cin >> new_book.m_author;
new_book.m_loan = false;//由于是新录入的图书,所以状态一定是未借出
Library* book = NULL;
book = new Library(new_book.m_book_name, new_book.m_book_id, new_book.m_book_price, new_book.m_author, new_book.m_loan);
new_space[this->book_num + i] = book;
}
//释放原有空间
delete[] this->m_Library_Array;
//更改新空间的指向
this->m_Library_Array = new_space;
//更新图书数量
this->book_num = new_size;
//更新判断图书数量是否为空的标志为“不为空”
this->m_BOOKFILE_empty = false;
//提示添加成功
cout << "成功添加" << add_number << "本新书!" << endl;
//保存数据到文件中
this->save();
}
else
{
cout << "输入有误" << endl;
}
//按任意键后 清屏回到上级目录
system("pause");
system("cls");
}
//将信息写入文件
void save()
{
ofstream ofs;
ofs.open(BOOKFILE, ios::out | ios::binary);//按照题目要求,以二进制形式存储
//将每个人数据写入到文件中
for (int i = 0; i < this->book_num; i++)
{
ofs << this->m_Library_Array[i]->m_book.m_book_name << " "
<< this->m_Library_Array[i]->m_book.m_book_id << " "
<< this->m_Library_Array[i]->m_book.m_book_price << " "
<< this->m_Library_Array[i]->m_book.m_author << " "
<< this->m_Library_Array[i]->m_book.m_loan << endl;
}
//关闭文件
ofs.close();
}
//查询某一本书
void find_book()
{
if (this->m_BOOKFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
cout << "请输入查找的方式:" << endl;
cout << "1、按目标书籍的编号查找 " << endl;
cout << "2、按目标书籍的名称查找 " << endl;
int select = 0;
cin >> select;
if (select == 1)
{
//按照编号查
int id;
cout << "请输入查找的书籍的编号: " << endl;
cin >> id;
int ret = book_exist(id);
if (ret != -1)
{
//找到目标书籍
cout << "查找成功!该书籍信息如下:" << endl;
this->m_Library_Array[ret]->show_one_book();
}
else
{
cout << "查找失败,查无此书" << endl;
}
}
else if (select == 2)
{
//按照姓名查
string name;
cout << "请输入目标书籍的名称:" << endl;
cin >> name;
//加入判断是否查到的标志
bool flag = false; //默认未找到目标书籍
for (int i = 0; i < book_num; i++)
{
if (this->m_Library_Array[i]->m_book.m_book_name == name)
{
cout << "查找成功,目标读者的学号为: "
<< this->m_Library_Array[i]->m_book.m_book_id
<< "号书籍信息如下:" << endl;
flag = true;
//调用显示信息接口
this->m_Library_Array[i]->show_one_book();
}
}
if (flag == false)
{
cout << "查找失败,查无此书!" << endl;
}
}
else
{
cout << "输入选项有误!" << endl;
}
}
//按任意键清屏
system("pause");
system("cls");
}
//显示所有图书的信息函数中的show_one_book函数,该函数用于输出单个图书的信息,再通过for循环来调用该函数以输出全部读者信息
void show_one_book()
{
cout << "图书名称: " << this->m_book.m_book_name
<< "\t编号: " << this->m_book.m_book_id
<< "\t单价: " << this->m_book.m_book_price
<< "\t作者:" << this->m_book.m_author
<< "\t存在状态" << this->m_book.m_loan << endl;
}
//显示所有图书的信息
void show_all_book()
{
//判断文件是否为空
if (this->m_BOOKFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
for (int i = 0; i < book_num; i++)
{
this->m_Library_Array[i]->show_one_book();
}
}
//按任意键后清屏
system("pause");
system("cls");
}
//删除某一本书
void del_book()
{
if (this->m_BOOKFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
//按照书籍编号删除
cout << "请输入想要删除书籍编号:" << endl;
int id = 0;
cin >> id;
int index = this->book_exist(id);
if (index != -1) //说明书籍存在,并且要删除掉index位置上的书籍
{
for (int i = index; i < this->book_num - 1; i++)
{
//数据前移
this->m_Library_Array[i] = this->m_Library_Array[i + 1];
}
this->book_num--; //更新数组中记录书籍个数
//数据同步更新到文件中
this->save();
cout << "删除成功!" << endl;
}
else
{
cout << "删除失败,未找到该书籍" << endl;
}
}
//按任意键 清屏
system("pause");
system("cls");
}
//判断目标书籍是否存在。如果存在返回书籍所在数组中的位置,不存在返回-1
int book_exist(int id)
{
int index = -1;
for (int i = 0; i < this->book_num; i++)
{
if (this->m_Library_Array[i]->m_book.m_book_id == id)
{
//找到目标
index = i;
break;
}
}
return index;
}
//借书
void borrow_book()
{
if (this->m_BOOKFILE_empty||this->m_BORROWERFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
//按照书籍编号借书,同时要求输入读者的学号
cout << "请输入您的学号" << endl;
int stu;//读者的学号
cin >> stu;
int reader = -1;//用于表示读者在读者数组中的位置
reader = Borrower::borrower_exist(stu);
if (reader != -1)//reader如果为-1,说明没有在读者数组中找到目标
{
cout << "请输入想要借阅的书籍编号:" << endl;
int id = 0;
cin >> id;
int index = this->book_exist(id);
if (index != -1 && m_Library_Array[index]->m_book.m_loan == false)//书籍存在,且其状态为未借阅
{
cout << "已成功借阅" << endl;
m_Library_Array[index]->m_book.m_loan = true;
////将读者信息与该书籍的信息进行关联
//m_Library_Array[index]->m_book.m_borrower.m_borrower_name = m_Borrower_Array[reader]->m_borrower.m_borrower_name;
//m_Library_Array[index]->m_book.m_borrower.m_sex = m_Borrower_Array[reader]->m_borrower.m_sex;
//m_Library_Array[index]->m_book.m_borrower.m_borrower_id = m_Borrower_Array[reader]->m_borrower.m_borrower_id;
Library::save();
}
else if (index != -1 && m_Library_Array[index]->m_book.m_loan == true)//书籍存在,但是其状态未已借阅
{
cout << "已查找到该书籍,但是该书籍已经被借阅" << endl;
}
else
{
cout << "未查找到该书" << endl;
}
}
else
{
cout << "未在数据库中查找到您的信息,请确认您输入的学号是否正确。如果您尚未注册,请先进行读者注册" << endl;
}
//按任意键清屏
system("pause");
system("cls");
}
}
//还书
void return_book()
{
if (this->m_BOOKFILE_empty || this->m_BORROWERFILE_empty)
{
cout << "文件不存在或记录为空!" << endl;
}
else
{
cout << "请输入您的学号" << endl;
int stu;//读者的学号
cin >> stu;
int reader = -1;//用于表示读者在读者数组中的位置
reader = Borrower::borrower_exist(stu);
if (reader != -1)//reader如果为-1,说明没有在读者数组中找到目标
{
}
else
{
cout << "未在数据库中查找到您的信息,请确认您输入的学号是否正确。如果您尚未注册,请先进行读者注册" << endl;
}
}
}
//退出系统
void exit_system()
{
cout << "欢迎下次使用" << endl;
system("pause");
exit(0);
}
//析构函数
~Library()
{
//手动释放堆区数据
if (this->m_Library_Array != NULL)
{
delete[] this->m_Library_Array;
}
}
};
int main() {
Library lib;
Borrower bor;
int choice = 0;
while (true)//为了能够结合清屏功能,使得每次屏幕都打印菜单,且可以连续进行选择
{
lib.show_menu();
cout << "请输入您的选择:" << endl;
cin >> choice;
switch (choice)
{
case 0://退出系统
lib.exit_system();
break;
case 1://录入新书
lib.set_book();
break;
case 2://查询图书
lib.find_book();
break;
case 3://显示所有图书的信息
lib.show_all_book();
break;
case 4://删除某一本书
lib.del_book();
break;
case 5://为借书人办理注册
bor.set_borrower();
break;
case 6://查询读者
bor.find_borrower();
break;
case 7://显示所有读者的信息
bor.show_all_borrower();
break;
case 8://删除某一读者
bor.del_borrower();
break;
case 9://借书
lib.borrow_book();
break;
case 10://还书
lib.return_book();
break;
default:
system("cls");
break;
}
}
system("pause");
return 0;
}