1、问题描述 :
图书馆中的资料很多,如果能分类对其资料流通进行管理,将会带来很多方 便,因此需要有一个媒体库管理系统。 图书馆共有三大类物品资料:图书、视频光盘、图画。 这三类物品共同具有的属性有:编号、标题、作者、评级(未评级,一般 成人,儿童) 等。其中图书类增加出版社、ISBN号、页数等信息;视频光盘类增加出品者 的名字、出品年份和视频时长等信息;图画类增加出品国籍、作品的长和宽 (以厘米计,整数)等信息。 读者:基本信息,可借阅本数 管理员:负责借阅
2、功能要求 :
(1)添加物品:主要完成图书馆三类物品信息的添加,要求编号唯一。当添 加了重复的编号时,则提示数据添加重复并取消添加:查询物品可按照三种 方式来查询物品,分别为: 按标题查询:输入标题,输出所查询的信息,若不存在该记录,则提示“该 标题+存在!”; 按编号查询:输入编号,输出所查询的信息,若不存在该记录,则提示“该 编号不存在!”; 按类别查询:输入类别,输出所查询的信息,若不存在记录,则提示“该类 别没有物品!”;
(2)显示物品库:输出当前物品库中所有物品信息,每条记录占据一行。
(3)编辑物品:可根据查询结果对相应的记录进行修改,修改时注意编号的 唯一性。
(4)删除物品:主要完成图书馆物品信息的删除。如果当前物品库为空,则 提示“物品库为空!”,并返回操作:否则,输入要删除的编号,根据编号删 除该物品的记录,如果该编号不在物品库中,则提示“该编号不存在”。
(5)借阅,管理员负责将物品借阅给读者,数据保存到文件中 。
(6)统计信息 输出当前物品库中总物品数,以及按物品类别,统计出山前物品中各类别的 物品数并显。
(7)物品存盘:将当前程序中的物品信息存入文件中。
(8)读出物品 从文件中将物品信息读入程序。 开发完代码后需要进行测试,如果报错请修改,知道各项功能都可以正常运行。
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <unordered_map>
#include <windows.h>
using namespace std;
enum Rating { UNRATED, ADULT, CHILD };
string ratingToString(Rating rating) {
switch (rating) {
case UNRATED: return "未评级";
case ADULT: return "成人";
case CHILD: return "儿童";
default: return "";
}
}
class Media {
public:
int id;
string title;
string author;
Rating rating;
Media(int id, string title, string author, Rating rating)
: id(id), title(title), author(author), rating(rating) {}
virtual void display() const {
cout << "ID: " << id << ", 标题: " << title << ", 作者: " << author << ", 评级: " << ratingToString(rating) << endl;
}
virtual ~Media() {}
};
class Book : public Media {
public:
string publisher;
string isbn;
int pages;
Book(int id, string title, string author, Rating rating, string publisher, string isbn, int pages)
: Media(id, title, author, rating), publisher(publisher), isbn(isbn), pages(pages) {}
void display() const override {
Media::display();
cout << "出版社: " << publisher << ", ISBN: " << isbn << ", 页数: " << pages << endl;
}
};
class Video : public Media {
public:
string producer;
int year;
int duration;
Video(int id, string title, string author, Rating rating, string producer, int year, int duration)
: Media(id, title, author, rating), producer(producer), year(year), duration(duration) {}
void display() const override {
Media::display();
cout << "出品者: " << producer << ", 年份: " << year << ", 时长: " << duration << " mins" << endl;
}
};
class Picture : public Media {
public:
string nationality;
int length;
int width;
Picture(int id, string title, string author, Rating rating, string nationality, int length, int width)
: Media(id, title, author, rating), nationality(nationality), length(length), width(width) {}
void display() const override {
Media::display();
cout << "国籍: " << nationality << ", 尺寸: " << length << "x" << width << " cm" << endl;
}
};
class Library {
unordered_map<int, Media*> mediaCollection;
public:
~Library() {
for (auto& pair : mediaCollection) {
delete pair.second;
}
}
void addMedia(Media* media) {
if (mediaCollection.find(media->id) != mediaCollection.end()) {
cout << "检测到重复的 ID, 未添加资料." << endl;
delete media;
return;
}
mediaCollection[media->id] = media;
cout << "资料添加成功." << endl;
}
void queryByTitle(const string& title) {
bool found = false;
for (const auto& pair : mediaCollection) {
if (pair.second->title == title) {
pair.second->display();
found = true;
}
}
if (!found) cout << " 标题 \"" << title << "\" 不存在!" << endl;
}
void queryById(int id) {
if (mediaCollection.find(id) != mediaCollection.end()) {
mediaCollection[id]->display();
} else {
cout << " ID \"" << id << "\" 不存在!" << endl;
}
}
void queryByType(const string& type) {
bool found = false;
for (const auto& pair : mediaCollection) {
if ((type == "Book" && dynamic_cast<Book*>(pair.second)) ||
(type == "Video" && dynamic_cast<Video*>(pair.second)) ||
(type == "Picture" && dynamic_cast<Picture*>(pair.second))) {
pair.second->display();
found = true;
}
}
if (!found) cout << "分类没有 \"" << type << "\" 找到!" << endl;
}
void displayAll() {
if (mediaCollection.empty()) {
cout << "数据库中没有相关资料." << endl;
return;
}
for (const auto& pair : mediaCollection) {
pair.second->display();
}
}
void editMedia(int id, Media* newMedia) {
if (mediaCollection.find(id) == mediaCollection.end()) {
cout << " ID \"" << id << "\" 不存在!" << endl;
delete newMedia;
return;
}
delete mediaCollection[id];
mediaCollection[id] = newMedia;
cout << "资料编辑成功." << endl;
}
void deleteMedia(int id) {
if (mediaCollection.find(id) == mediaCollection.end()) {
cout << " ID \"" << id << "\" 不存在!" << endl;
return;
}
delete mediaCollection[id];
mediaCollection.erase(id);
cout << "资料删除成功." << endl;
}
void saveToFile(const string& filename) {
ofstream file(filename, ios::binary);
if (!file) {
cout << "无法打开文件进行写入." << endl;
return;
}
for (const auto& pair : mediaCollection) {
Media* media = pair.second;
file.write((char*)&media->id, sizeof(media->id));
size_t length = media->title.size();
file.write((char*)&length, sizeof(length));
file.write(media->title.c_str(), length);
length = media->author.size();
file.write((char*)&length, sizeof(length));
file.write(media->author.c_str(), length);
file.write((char*)&media->rating, sizeof(media->rating));
if (Book* book = dynamic_cast<Book*>(media)) {
char type = 'B';
file.write(&type, sizeof(type));
length = book->publisher.size();
file.write((char*)&length, sizeof(length));
file.write(book->publisher.c_str(), length);
length = book->isbn.size();
file.write((char*)&length, sizeof(length));
file.write(book->isbn.c_str(), length);
file.write((char*)&book->pages, sizeof(book->pages));
} else if (Video* video = dynamic_cast<Video*>(media)) {
char type = 'V';
file.write(&type, sizeof(type));
length = video->producer.size();
file.write((char*)&length, sizeof(length));
file.write(video->producer.c_str(), length);
file.write((char*)&video->year, sizeof(video->year));
file.write((char*)&video->duration, sizeof(video->duration));
} else if (Picture* picture = dynamic_cast<Picture*>(media)) {
char type = 'P';
file.write(&type, sizeof(type));
length = picture->nationality.size();
file.write((char*)&length, sizeof(length));
file.write(picture->nationality.c_str(), length);
file.write((char*)&picture->length, sizeof(picture->length));
file.write((char*)&picture->width, sizeof(picture->width));
}
}
cout << "数据保存到文件." << endl;
}
void loadFromFile(const string& filename) {
ifstream file(filename, ios::binary);
if (!file) {
cout << "无法打开文件进行读取." << endl;
return;
}
while (file.peek() != EOF) {
int id;
file.read((char*)&id, sizeof(id));
size_t length;
file.read((char*)&length, sizeof(length));
string title(length, ' ');
file.read(&title[0], length);
file.read((char*)&length, sizeof(length));
string author(length, ' ');
file.read(&author[0], length);
Rating rating;
file.read((char*)&rating, sizeof(rating));
char type;
file.read(&type, sizeof(type));
if (type == 'B') {
file.read((char*)&length, sizeof(length));
string publisher(length, ' ');
file.read(&publisher[0], length);
file.read((char*)&length, sizeof(length));
string isbn(length, ' ');
file.read(&isbn[0], length);
int pages;
file.read((char*)&pages, sizeof(pages));
mediaCollection[id] = new Book(id, title, author, rating, publisher, isbn, pages);
} else if (type == 'V') {
file.read((char*)&length, sizeof(length));
string producer(length, ' ');
file.read(&producer[0], length);
int year, duration;
file.read((char*)&year, sizeof(year));
file.read((char*)&duration, sizeof(duration));
mediaCollection[id] = new Video(id, title, author, rating, producer, year, duration);
} else if (type == 'P') {
file.read((char*)&length, sizeof(length));
string nationality(length, ' ');
file.read(&nationality[0], length);
int length, width;
file.read((char*)&length, sizeof(length));
file.read((char*)&width, sizeof(width));
mediaCollection[id] = new Picture(id, title, author, rating, nationality, length, width);
}
}
cout << "从文件加载的数据." << endl;
}
void countItems() {
cout << "Total items: " << mediaCollection.size() << endl;
int books = 0, videos = 0, pictures = 0;
for (const auto& pair : mediaCollection) {
if (dynamic_cast<Book*>(pair.second)) books++;
else if (dynamic_cast<Video*>(pair.second)) videos++;
else if (dynamic_cast<Picture*>(pair.second)) pictures++;
}
cout << "Books: " << books << ", Videos: " << videos << ", Pictures: " << pictures << endl;
}
};
int main() {
SetConsoleOutputCP(65001);
Library library;
while (true) {
cout << "欢迎使用图书馆资料管理系统: \n1. 添加资料\n2. 按标题查询资料\n3. 按ID查询资料\n4. 按类别查询资料\n5. 显示所有资料\n6. 编辑资料\n7. 删除资料\n8. 资料存盘\n9. 读取资料\n10. 统计资料\n11. 退出\n";
int choice;
cin >> choice;
if (choice == 1) {
cout << "选择类别: 1. 图书 2. 视频 3. 图画\n";
int type;
cin >> type;
int id;
string title, author;
int rating;
cout << "输入ID: ";
cin >> id;
cout << "输入标题: ";
cin.ignore();
getline(cin, title);
cout << "输入作者: ";
getline(cin, author);
cout << "输入评级 (0 未评级, 1 成人, 2 儿童): ";
cin >> rating;
if (type == 1) {
string publisher, isbn;
int pages;
cout << "输入出版社: ";
cin.ignore();
getline(cin, publisher);
cout << "输入ISBN: ";
getline(cin, isbn);
cout << "输入页数: ";
cin >> pages;
library.addMedia(new Book(id, title, author, static_cast<Rating>(rating), publisher, isbn, pages));
} else if (type == 2) {
string producer;
int year, duration;
cout << "输入出品者: ";
cin.ignore();
getline(cin, producer);
cout << "输入出品年份: ";
cin >> year;
cout << "输入时长(分钟): ";
cin >> duration;
library.addMedia(new Video(id, title, author, static_cast<Rating>(rating), producer, year, duration));
} else if (type == 3) {
string nationality;
int length, width;
cout << "输入出品国籍: ";
cin.ignore();
getline(cin, nationality);
cout << "输入长度(厘米): ";
cin >> length;
cout << "输入宽度(厘米): ";
cin >> width;
library.addMedia(new Picture(id, title, author, static_cast<Rating>(rating), nationality, length, width));
}
} else if (choice == 2) {
string title;
cout << "输入标题: ";
cin.ignore();
getline(cin, title);
library.queryByTitle(title);
} else if (choice == 3) {
int id;
cout << "输入ID: ";
cin >> id;
library.queryById(id);
} else if (choice == 4) {
string type;
cout << "输入类别 (图书, 视频, 图画): ";
cin.ignore();
getline(cin, type);
library.queryByType(type);
} else if (choice == 5) {
library.displayAll();
} else if (choice == 6) {
int id;
cout << "输入要编辑资料的ID: ";
cin >> id;
cout << "选择新分类: 1. 图书 2. 视频 3. 图画\n";
int type;
cin >> type;
string title, author;
int rating;
cout << "输入新标题: ";
cin.ignore();
getline(cin, title);
cout << "输入新作者: ";
getline(cin, author);
cout << "输入新评级 (0 未评级, 1 成人, 2 儿童): ";
cin >> rating;
if (type == 1) {
string publisher, isbn;
int pages;
cout << "输入新的出版社: ";
cin.ignore();
getline(cin, publisher);
cout << "输入新的ISBN: ";
getline(cin, isbn);
cout << "输入新的页数: ";
cin >> pages;
library.editMedia(id, new Book(id, title, author, static_cast<Rating>(rating), publisher, isbn, pages));
} else if (type == 2) {
string producer;
int year, duration;
cout << "输入新的作者: ";
cin.ignore();
getline(cin, producer);
cout << "输入新的年份: ";
cin >> year;
cout << "输入新的持续时间(分钟): ";
cin >> duration;
library.editMedia(id, new Video(id, title, author, static_cast<Rating>(rating), producer, year, duration));
} else if (type == 3) {
string nationality;
int length, width;
cout << "输入新国籍: ";
cin.ignore();
getline(cin, nationality);
cout << "输入新长度(厘米): ";
cin >> length;
cout << "输入新宽度(厘米): ";
cin >> width;
library.editMedia(id, new Picture(id, title, author, static_cast<Rating>(rating), nationality, length, width));
}
} else if (choice == 7) {
int id;
cout << "输入要删除的资料ID: ";
cin >> id;
library.deleteMedia(id);
} else if (choice == 8) {
string filename;
cout << "输入文件名: ";
cin.ignore();
getline(cin, filename);
library.saveToFile(filename);
} else if (choice == 9) {
string filename;
cout << "输入文件名: ";
cin.ignore();
getline(cin, filename);
library.loadFromFile(filename);
} else if (choice == 10) {
library.countItems();
} else if (choice == 11) {
break;
} else {
cout << "无效的选择,请再试一次." << endl;
}
}
return 0;
}
3、运行效果:
录入:
统计:
查询: