题目要求
1、问题描述 :
定义图书类,属性有:书名、出版社、ISBN 号、作者、库存量、价格等信息和相关的 对属性做操作的行为。 主要完成对图书的销售、统计和图书的简单管理。
2、功能要求
(1)销售功能:
购买书籍时,输入相应的 ISBN 号,并在书库中查找该书的相关信息。 如果有库存量,输入购买的册数,进行相应计算。如果库存量不够,给出提示信息,结束购 买。
(2)图书简单管理功能:
添加功能:主要完成图书信息的添加,要求 ISBN 号唯一。当添加了重复的编号时,则提示数据添加重复并取消添加。
查询功能:可按书名、ISBN 号、作者、出版社进行查询。若存在相应信息,输出所查 询的信息,若不存在该记录,则提示“该标题不存在!”。
修改功能:可根据查询结果对相应的记录进行修改,修改时注意 ISBN 号的唯一性。
删除功能:主要完成图书信息的删除。输入要删除的 ISBN 号,根据编号删除该物品的 记录,如果该编号不在物品库中,则提示“该编号不存在”。
(3)统计功能。 输出当前书库中所有图书的总数及详细信息;可按书的价格、库存量、作者、出版社进 行统计,输出统计信息时,要按从大到小进行排序。
(4)图书存盘:将当前程序中的图书信息存入文件中。
(5)读出信息:从文件中将图书信息读入程序。
思路分析
图书管理系统肯定要定义“书”类啦~大概有这些属性叭。
再分析功能要求,大概这个系统是这样
大致将各个模块分了出来,接下来就开始实现了!
各个模块的实现
“书”类的创建
这个简单,就这几个属性,直接上代码
class Book
{
public:
Book();
~Book();
string name;
int ISBN;
int price;//价格
string writer;//作者
string publishingHouse;//出版社
int inStock; //库存
};
就把他放在Book.h 头文件吧
管理模块的创建及实现
管理权限
定义bool类函数来判断用户输入的密码是否正确,随便写一字符串就好
bool quanxian()
{
cout << "请输入密码来证明您的权限" << endl;
string c;
cin >> c;
return c == "73748156";
}
添加图书
接下来是添加一本书,先声明一个临时的Book类型变量,然后依次读入他的各个属性,一定要注意判断ISBN号是否唯一
先写一个判断ISBN号是否唯一的函数
int isExist(int isbn, vector<Book>& b)
{
for (auto& i : b) {
//遍历这个Book类vector,判断ISBN是否唯一
if (i.ISBN == isbn)return -1;
}
return 0;
}
然后写添加书籍名称的函数
void addBookName(vector<Book>& b, Book& c) {
string name;
cout << "请输入书名" << endl;
cin >> name;
c.name = name;
}
添加ISBN的函数,在其中插入判断ISBN是否唯一的函数
void addBookIsbn(vector<Book>& b, Book& c) {
int isbn;
cout << "请输入ISBN号" << endl;
while (true)
{
cin >> isbn;
if (isExist(isbn, b) == -1)cout << "ISBN号重复,请重新输入" << endl;
else break;
}
c.ISBN = isbn;
}
添加作者的函数
void addBookWriter(vector<Book>& b, Book& c) {
string writer;
cout << "请输入作者" << endl;
cin >> writer;
c.writer = writer;
}
添加出版社的函数
void addBookPublishingHouse(vector<Book>& b, Book& c) {
string chubanshe;
cout << "请输入出版社" << endl;
cin >> chubanshe;
c.publishingHouse = chubanshe;
}
添加库存的函数
void addBookInStock(vector<Book>& b, Book& c) {
int kucun;
cout << "请输入库存" << endl;
cin >> kucun;
c.inStock = kucun;
}
添加价格的函数
void addBookPrice(vector<Book>& b, Book& c) {
int jiage;
cout << "请输入价格" << endl;
cin >> jiage;
c.price = jiage;
}
最后一起调用,做添加图书的总函数
void addBook(vector<Book>& b) {
Book newbook;//声明一个Book类变量
addBookName(b, newbook);
addBookIsbn(b, newbook);
addBookWriter(b, newbook);
addBookPublishingHouse(b, newbook);
addBookInStock(b, newbook);
addBookPrice(b, newbook);
//将信息读取到newbook变量中
b.push_back(newbook);
//再将newbook添加到Book类vector中
cout << "添加成功" << endl;
}
这样就可以添加图书了
查找图书
查找图书肯定要按多种条件查找
先做一个菜单
void showMenu4()
{
cout << "*************************************" << endl;
cout << "*** 请选择您检索书籍的方式 *******" << endl;
cout << "*** 通过书名查找请按1 ******" << endl;
cout << "*** 通过IBSN号查找请按2 ******" << endl;
cout << "*** 通过作者查找请按3 ******" << endl;
cout << "*** 通过出版社查找请按4 ******" << endl;
cout << "*** 退出查找请按0 *******" << endl;
cout << "***********************************" << endl;
}
理科生整的菜单没有美感。。。。。。。
接下来需要考虑的问题是书籍信息重复问题
书名会重,一个作者会写好多本书,出版社也肯定不会只出一本书
考虑到上述情况,查找结果可能不止一本书
故在查找函数内部再声明一个Book类的vector,
将查到的书存在里边,然后再做第二次确认
还是先做查找书名的函数,参数传两个Book类的vector
void findBookName(vector<Book>& b, vector<Book>& c) {
string name;
cout << "请输入您要查找的书籍名称" << endl;
cin >> name;
for (auto& i : b) {
if (i.name == name)
{
c.push_back(i);
}
}
}
然后是查找作者的函数
void findBookWriter(vector<Book>& b, vector<Book>& c) {
string writer;
cout << "请输入您要查找的书籍作者" << endl;
cin >> writer;
for (auto& i : b) {
if (i.writer == writer)
{
c.push_back(i);
}
}
}
还有查找出版社的函数
void findBookPublishingHouse(vector<Book>& b, vector<Book>& c) {
string chubanshe;
cout << "请输入您要查找的书籍出版社" << endl;
cin >> chubanshe;
for (auto& i : b) {
if (i.publishingHouse == chubanshe)
{
c.push_back(i);
}
}
}
最后是查找ISBN的函数,ISBN肯定是唯一的
所以这种检索方式是最准确的
但是为方便后续操作
依旧传两个vector
void findBookIsbn(vector<Book>& b, vector<Book>& c) {
cout << "请输入您要查找的书籍ISBN" << endl;
int ISBN;
cin >> ISBN;
for (auto& i : b) {
if (i.ISBN == ISBN)
{
c.push_back(i);
Book::show(i);
}
}
}
查找之后肯定要把图书信息显示出来供使用者确认
做一个展示图书信息的函数
我写到了Book类里
void Book::show(Book b) {
cout << "书名:" << b.name
<< "\tISBN:" << b.ISBN
<< "\t作者:"<< b.writer
<< "\t出版社:" << b.publishingHouse
<< "\t价格:" << b.price
<< "\t库存:" << b.inStock << endl;
}
最后把这几个查找函数用一个函数封装到一起
Book findBook(vector<Book>& b)
{
Book tmp;
vector<Book>c;//为防止书籍其他信息重复,将信息重复的查找结果存在c中
tmp.ISBN = 0;
showMenu4();
char choose2;
cin >> choose2;
switch (choose2)
{
case '1'://按书名查找
{
findBookName(b, c);
break;
}
case '2'://ISBN
{
findBookIsbn(b, c);
break;
}
case '3'://作者
{
findBookWriter(b, c);
break;
}
case '4'://出版社
{
findBookPublishingHouse(b, c);
break;
}
case '0'://退出
{
cout << "欢迎下次使用" << endl;
tmp.ISBN = -1;
break;
}
default: {
cout << "指令错误,请重新输入" << endl;
break;
}
}
//开始二次检索
if (tmp.ISBN != -1)
{
if (c.empty())
//判断找没找到,没找到vector就是空的
{
cout << "查无此书" << endl;
tmp.ISBN = -1;
}
else if (c.size() == 1)return c[0];
//如果vector内只有一个函数,就不再遍历浪费时间啦
else
{
cout << "请确认您要查找的书籍" << endl;
int i;
for (i = 0; i < c.size(); ++i) {
//c里不止一本书,遍历c确认查找的书
cout << i + 1 << "、\t";
Book::show(c[i]);
}
cout << "请选择您要查找的书籍序号" << endl;
cin >> i;
return c[i - 1];
}
}
return tmp;
}
完事,下一个
修改图书
修改图书也简单,跟添加图书差不多吧
无非就是修改单个信息
肯定是要先找到图书,再去修改,
所以函数中传一个vector和一本书就好
先做一个菜单
void showMenu5()
{
cout << "*************************************" << endl;
cout << "***** 您想要修改该书哪种信息 ******" << endl;
cout << "******* 修改书名请按1 *******" << endl;
cout << "******* 修改ISBN请按2 *******" << endl;
cout << "******* 修改作者请按3 *******" << endl;
cout << "******* 修改出版社请按4 *******" << endl;
cout << "******* 修改价格请按5 *******" << endl;
cout << "******* 修改库存请按6 *******" << endl;
cout << "******* 退出修改请按0 *******" << endl;
cout << "***********************************" << endl;
}
理科生审美标配菜单~
然后还是先做修改单个信息的函数
修改书名的
void modifyBookName(vector<Book>& b, Book& c)
{
string name;
cout << "请输入修改后书名" << endl;
cin >> name;
int i = 0;
for (; i < b.size(); ++i) {
if (b[i].ISBN == c.ISBN)break;
}
b[i].name = name;
cout << "修改成功" << endl;
}
修改ISBN的
这里注意修改后的ISBN不能重复,
调用一次之前写好的函数来判断ISBN是否唯一
void modifyBookIsbn(vector<Book>& b, Book& c)
{
int isbn;
cout << "请输入修改后ISBN号" << endl;
cin >> isbn;
if (isExist(isbn, b) == -1)//判断ISBN是否重复
{
cout << "ISBN重复,修改失败" << endl;
}
else {
int i = 0;
for (; i < b.size(); ++i) {
if (b[i].ISBN == c.ISBN)break;
}
b[i].ISBN = isbn;
cout << "修改成功" << endl;
}
}
修改作者的
void modifyBookWriter(vector<Book>& b, Book& c)
{
string zuozhe;
cout << "请输入修改后作者" << endl;
cin >> zuozhe;
int i = 0;
for (; i < b.size(); ++i) {
if (b[i].ISBN == c.ISBN)break;
}
b[i].writer = zuozhe;
cout << "修改成功" << endl;
}
修改出版社的
void modifyBookChubanshe(vector<Book>& b, Book& c)
{
string chubanshe;
cout << "请输入修改后出版社" << endl;
cin >> chubanshe;
int i = 0;
for (; i < b.size(); ++i) {
if (b[i].ISBN == c.ISBN)break;
}
b[i].publishingHouse = chubanshe;
cout << "修改成功" << endl;
}
修改库存的
void modifyBookKucun(vector<Book>& b, Book& c)
{
int kucun;
cout << "请输入修改后库存" << endl;
cin >> kucun;
int i = 0;
for (; i < b.size(); ++i) {
if (b[i].ISBN == c.ISBN)break;
}
b[i].inStock = kucun;
cout << "修改成功" << endl;
}
修改价格的
void modifyBookJiage(vector<Book>& b, Book& c)
{
int jiage;
cout << "请输入修改后价格" << endl;
cin >> jiage;
int i = 0;
for (; i < b.size(); ++i) {
if (b[i].ISBN == c.ISBN)break;
}
b[i].price = jiage;
cout << "修改成功" << endl;
}
最后封装到一起
void modifyBookInformation(vector<Book>& b, Book& c)
{
while (true)
{
showMenu5();
char choose5;
cin >> choose5;
switch (choose5) {
case '1':
{
modifyBookName(b, c);
break;
}
case '2': {
modifyBookIsbn(b, c);
break;
}
case '3': {
modifyBookWriter(b, c);
break;
}
case '4': {
modifyBookChubanshe(b, c);
break;
}
case '5': {
modifyBookJiage(b, c);
break;
}
case '6':
{
modifyBookKucun(b, c);
break;
}
case '0':
{
cout << "退出修改系统" << endl;
return;
}
default:
{
cout << "指令错误,请重新输入" << endl;
break;
}
}
}
}
删除图书
这个更简单了,因为是用的vector来存储书籍
所以删除图书用vector中的erase方法就行
同样也是先查找书籍再删除
参数传一个vector和一本书
我把这个函数写到了Book类中
void Book::deleteBook(vector<Book>& b, Book c)
{
int i;
for (i = 0; i < b.size(); i++) {
//通过ISBN查找这本书
if (b[i].ISBN == c.ISBN) {
b.erase(b.begin() + i);//删除这本书
}
}
cout << "删除成功" << endl;
}
已经完成一半多啦!
整理模块的封装
做一个修改书目的菜单函数,没什么要求(好看就行)
void showMenu3()
{
cout << "*************************************" << endl;
cout << "******** 修改该书籍请按1 *****" << endl;
cout << "******** 删除该书籍请按2 *****" << endl;
cout << "******** 退出请按0 *****" << endl;
cout << "*************************************" << endl;
}
先将修改信息和删除书目两个功能封装到一块,还是用switch结构
void modifyBook(vector<Book>& b, Book& c) {
showMenu3();
char choose4;
cin >> choose4;
switch (choose4)
{
case '0'://退出
{
cout << "退出修改系统" << endl;
break;
}
case '1'://修改
{
modifyBookInformation(b, c);
break;
}
case '2'://删除
{
Book::deleteBook(b, c);
break;
}
default:
{
cout << "指令错误,修改失败" << endl;
break;
}
}
}
在做一个整理功能的菜单,将功能选项都写好
void showMenu2()
{
cout << "*************************************" << endl;
cout << "******** 添加书籍信息请按1 *****" << endl;
cout << "******** 修改书籍信息请按2 *****" << endl;
cout << "******** 退出整理系统请按0 *****" << endl;
cout << "*************************************" << endl;
}
还是熟悉的风格 ~
然后将整理模块所有功能封装到一个函数中,一样是用switch,大同小异
void arrangeBook(vector<Book>& b) {
while (true)
{
showMenu2();
char choose3;
cin >> choose3;
switch (choose3)
{
case'0'://退出
{
cout << "退出整理系统" << endl;
return;
}
case '1'://添加
{
addBook(b);
break;
}
case '2'://修改
{
Book gai = findBook(b);
if (gai.ISBN != -1)
{
modifyBook(b, gai);
}
break;
}
}
system("pause");//按任意键继续
system("cls");//清屏
}
}
整理模块的所有功能就都包含在arrangeBook(vector<Book>& b)
这个函数中了
销售模块的创建与实现
销售图书无非就是先检索出来
判断库存,然后输出
直接上代码
void buyBook(vector<Book>& b) {
Book mai = findBook(b);
if (mai.ISBN != -1)
{
int number;
cout << "请输入要购买的数量" << endl;
cin >> number;
if (number > mai.inStock)//判断库存够不够
{
cout << "库存不足,购买失败" << endl;
}
else
{
int huaxiao = number * mai.price;
for (int i = 0; i < b.size(); ++i) {
//遍历找到这本书,并调整他的库存
if (b[i].ISBN == mai.ISBN)
{
b[i].inStock -= number;
break;
}
}
cout << "购买成功" << endl;
cout << "共花费 " << huaxiao << " 元" << endl;
}
}
}
统计模块的创建与实现
统计也就是按ISBN,库存或价格排序输出下,
还是先做个菜单
void showMenu6() {
cout << "*********************************************" << endl;
cout << "****** 选择你要统计图书信息的排序方式 ******" << endl;
cout << "******* 按ISBN统计请按1 *******" << endl;
cout << "******* 按库存统计请按2 *******" << endl;
cout << "******* 按价格统计请按3 *******" << endl;
cout << "******* 退出请按0 *******" << endl;
cout << "*********************************************" << endl;
}
简洁且美观!
因为是用vector存储的书籍
所以排序也是很容易操作
直接用sort方法就可以
故只需要自己定义比较函数
先定义比较ISBN的比较函数
bool isbnCmp(const Book& a, const Book& b)
{
return a.ISBN > b.ISBN;
}
接着是库存比较函数
bool inStockCmp(const Book& a, const Book& b)
{
if (a.inStock == b.inStock)return a.ISBN > b.ISBN;
//库存相等的时候按ISBN排序
return a.inStock > b.inStock;
}
然后是价格比较函数
bool priceCmp(const Book& a, const Book& b)
{
if (a.price == b.price)return a.ISBN > b.ISBN;
//价格相等的时候按ISBN排序
return a.price > b.price;
}
最后封装好统计函数
void tongji(vector<Book>& b)
{
showMenu6();
char choose6;
cin >> choose6;
switch (choose6)
{
case '0'://退出
{
cout << "退出统计系统" << endl;
return;
}
case '1'://isbn
{
sort(b.begin(), b.end(), isbnCmp);//排序
for (const auto& i : b)
{
Book::show(i);//显示排完序后的书库
}
break;
}
case '2'://库存
{
sort(b.begin(), b.end(), inStockCmp);
for (const auto& i : b)
{
Book::show(i);
}
break;
}
case '3'://价格
{
sort(b.begin(), b.end(), priceCmp);
for (const auto& i : b)
{
Book::show(i);
}
break;
}
}
}
文件的读取与存储
用文件流写入或读取文件
记得要加 ftream 的头文件
并且加上宏定义#define FILENAME "library.txt"
open函数要写打开模式
写入模式 ios::out
读取模式 ios::in
具体操作方法如下
保存Book类vector信息代码
void save(vector<Book>& b)
{
ofstream ofs;
ofs.open(FILENAME, ios::out);
for (auto& i : b) {
//录入每本书信息
ofs << i.name << " " << i.ISBN << " " << i.writer << " "
<< i.publishingHouse << " "
<< i.inStock << " " << i.price << endl;
//将所有信息存储,信息之间以空格分隔,书之间以换行符分隔
}
cout << "保存成功" << endl;
ofs.close();//关闭文件
}
还有将文件内容读取到Book类vector中
方法是先声明一个Book变量,读取信息后将其插入vector中
代码如下
void fetchBook(vector<Book>& b)
{
ifstream ifs;
ifs.open(FILENAME, ios::in);//读文件
if (!ifs.is_open())//判断是否存在
{
cout << "图书文件不存在" << endl;
ifs.close();
return;
}
Book temp;
while (ifs >> temp.name && ifs >> temp.ISBN && ifs
>> temp.writer && ifs >> temp.publishingHouse &&
ifs >> temp.inStock && ifs >> temp.price)//信息读取到temp中
{
b.push_back(temp);//将temp存在b中
}
ifs.close();
if (b.empty())
{
cout << "图书文件为空" << endl;
}
else
cout << "当前图书种类数目为" << b.size() << "本" << endl;
}
完成!
到这里,题目要求的几个模块就都完成啦~
顺手拓展下再加个用户登录界面完善下吧
创建简易登录界面
有登录肯定得有注册
还是老样子
先做一个巨好看的菜单
void showMenu0() {
cout << "*************************************" << endl;
cout << "******** 书是人类进步的阶梯 *********" << endl;
cout << "******** 登录帐号请按1 *********" << endl;
cout << "******** 注册账号请按2 *********" << endl;
cout << "******** 退出图书系统请按0 *********" << endl;
cout << "*************************************" << endl;
}
好看!
接着先写一个类,就叫User叭
class User {
public:
User() {
}
~User() {
}
string userName;
string password;
};
然后开始写注册函数
当然也要判断用户名是否唯一
判断用户名是否唯一的函数代码
int isUserExist(string name, vector<User>u) {
for (int i = 0; i < u.size(); ++i) {
if (u[i].userName == name) return i;
}
return -1;
}
接着是注册函数的实现,跟添加图书差不多,
还是先声明一个User类变量,输入各信息后再将其插入到vector中
既然是存储用户信息的vector,当然也要保存在文件中
同样加一个宏定义#define FILENAME2 "users.txt"
然后上代码
void zhuce(vector<User>& u)
{
string password;
User tmp;
string name;
cout << "请输入用户名" << endl;
cin >> name;
int a = isUserExist(name, u);
if (a == -1)
{
tmp.userName = name;
cout << "请输入密码" << endl;
cin >> password;
tmp.password = password;
u.push_back(tmp);
ofstream ofs;
ofs.open(FILENAME2, ios::out);
for (auto& i : u) {
//录入用户信息
ofs << i.userName << " "<< i.password << endl;
}
cout << "保存成功" << endl;
ofs.close();//关闭文件
}
else cout << "该用户名已被使用,注册失败" << endl;
}
当然不能忘了还有登录的代码没写
bool denglu(vector<User> u)
{
string name, password;
cout << "请输入用户名" << endl;
cin >> name;
int a = isUserExist(name, u);
if (a == -1) {
cout << "用户名不存在,登录失败" << endl;
return false;
}
else
{
cout << "请输入密码" << endl;
cin >> password;
if (u[a].password == password) {
cout << "登录成功" << endl;
return true;
}
else
{
cout << "密码错误,登录失败" << endl;
return false;
}
}
}
再补一下主函数的封装
主函数的封装
主函数中声明两个 vector ,再调用两个函数读取本地文件到 vector 中
之后调用 选择函数,来封装所有的模块
int main() {
vector<Book>lib;
vector<User>users;
fetchUser(users);
fetchBook(lib);
selectOption(lib, users);
return 0;
}
主菜单选项的封装
还是先做一个百看不腻的美丽菜单
void showMenu1()
{
cout << "*************************************" << endl;
cout << "******** 书是人类进步的阶梯 *********" << endl;
cout << "******** 购买书籍请按1 *********" << endl;
cout << "******** 整理书籍请按2 *********" << endl;
cout << "******** 显示书籍信息请按3 *********" << endl;
cout << "******** 保存图书信息请按4 *********" << endl;
cout << "******** 退出图书系统请按0 *********" << endl;
cout << "*************************************" << endl;
}
觉得好看可以多看一会,我不会不好意思的
接着是 选择函数,就把所有模块扔到一个 switch 结构里就好啦 ~
void selectOption(vector<Book>& b, vector<User>& u)
{
int h = 0;
char choose0;
do {
showMenu0();
cin >> choose0;
switch (choose0)
{
case'1'://登录
if (denglu(u))
{
h = 1;
break;
}
else
continue;
case'2'://注册
zhuce(u);
break;
case'0':
cout << "欢迎下次使用" << endl;
return;
}
system("pause");
system("cls");
} while ((choose0 != '0' && h != 1));
while (true)
{
//展示主菜单
showMenu1();
char choose;
cin >> choose;
switch (choose)
{
case'1'://购买
{
buyBook(b);
break;
}
case'2'://整理
{
if (quanxian())
arrangeBook(b);
else cout << "密码错误,您没有权限" << endl;
break;
}
case '3'://统计
{
if (b.empty())
{
cout << "当前无图书" << endl;
break;
}
tongji(b);
break;
}
case '4'://保存
{
save(b);
break;
}
case'0'://退出
{
cout << "欢迎下次使用" << endl;
return;
}
default:
{
cout << "指令错误,请重新输入" << endl;
}
}
system("pause");
system("cls");
}
}
没有积分的朋友们可以私信管我要代码哦
转载:https://blog.csdn.net/qq_46039856/article/details/106269628