圖書管理系統設計
題目要求
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 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 結構裏就好啦 ~
```cpp
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");
}
}
燕大的朋友們可以私信管我要代碼哦