问题分析:
出版社有一些图书数据,为简单起见,在此假设每种图书只包括三部分信息:ISBN 书名和价格,文件中的部分数据如图所示。现要求实现一个图书信息管理系统,包括以下6个具体功能。
查找:根据指定的ISBN或书名查找相应图书的有关信息,并返回该图书在表中的位置序号。
插入:插入一种新的图书信息。
删除:删除一种图书信息。
修改:根据指定的ISBN,修改该图书的价格。
排序:将图书按照价格由低到高进行排序。
计数:统计图书表中的图书数量。
算法步骤:
创建链表,构建添加图书,查找图书,删除图书,修改图书,按价格排序,按序号排序,统计数目以及清空图书的函数。用死循环进行交互,在合适的地方退出,最后结束程序时,调用析构函数释放内存空间。
算法描述:
创建链表实例。
添加图书:获取用户输入,创建新图书节点,插入链表头部。
查找图书:输入ISBN,遍历链表查找并输出信息。
删除图书:输入ISBN,遍历链表找到并删除对应节点。
修改图书:输入ISBN,找到节点并允许用户修改信息。
按价格排序:调用排序方法,更新链表顺序。
显示图书列表:遍历链表,输出所有图书信息。
退出程序:提供退出选项,结束程序。
循环操作:循环执行以上步骤,直到用户选择退出。
清理内存:程序结束时释放链表内存,防止内存泄漏。
工具环境:
Dev-c++ TDM-GCC 4.9.2 64-bit debug ISO C++11
代码:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
class Book {
public:
int num; //图书的序号
string ISBN; //图书的ISBN编号
string name; //图书的名称
int price; //图书的价格
Book(int num, const string& ISBN, const string& name, int price)
: num(num), ISBN(ISBN), name(name), price(price) { }
};
class LinkList {
public:
struct Node {
class Book* book; //指向图书信息的指针
struct Node* next; //指向下一个节点的指针
Node(Book* book) : book(book), next(NULL) { }
};
LinkList( ) : head(NULL), count(0) { }
~LinkList( ) { clear( ); }
void refresh ( ) {
system ("pause"); //暂停程序,等待用户输入
system ("cls"); //清屏
}
void showmenu ( ) {
cout << "请选择操作:" << 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 << "********0. 退出************" << endl;
}
void clear( ) { //清除所有图书
Node* current = head; //从头节点开始
while (current != NULL) {
Node* temp = current; //临时保存当前节点
current = current->next; //移动到下一个节点
delete temp->book; //删除图书信息
delete temp; //删除节点(从头开始删)
}
head = NULL; //将头节点设置为NULL
count = 0; //节点数量设置为0
}
void insert(const Book& book) { //前插操作,添加书
Node* newNode = new Node(new Book(book)); //创建一个新的节点,匿名对象,拷贝构造
newNode->next = head; //将新节点指向原来的头节点
head = newNode; //将头节点更新为新节点
count++; //节点数量加1
}
void remove(const string& ISBN) { //删除书
Node* prev = NULL; //前一个节点
Node* current = head; //当前节点
while (current != NULL && current->book->ISBN != ISBN) {
prev = current; //更新前一个节点
current = current->next; //移动到下一个节点
}
if (current != NULL) { //如果找到了对应的节点
deleteNode(prev); //那就删掉这个结点嘿嘿!
cout << "删除成功" << endl;
} else {
cout << "没有找到哎" << endl;
}
}
void alter(const string& ISBN) { //修改书
Node* node = findBookByISBN(ISBN); //找ISBN对应的节点
if (node != NULL) { //如果找到了对应的节点
cout << "请输入修改后的图书信息:" << endl;
cout << "ISBN(不变): " << ISBN << endl;
cout << "书名:"; cin >> node->book->name; //输入新的书名
cout << "价格:"; cin >> node->book->price; //输入新的价格
} else {
cout << "找不到该ISBN的图书。" << endl;
}
cin.ignore( ); //忽略输入流中的换行符*****
}
void order( ) { //按价格排序
if (head == NULL || head->next == NULL) return; //如果链表为空或只有一个节点,不需要排序
bool swapped; //标记是否发生了交换
Node* current = head; //当前节点
do {
swapped = false; //初始化为未发生交换
current = head; //从头节点开始
while (current->next != NULL) { //遍历链表
if (current->book->price >
current->next->book->price) { //如果当前节点的价格大于下一个节点的价格
swap(current, current->next); //交换两个节点的内容
swapped = true; //标记发生了交换(只动值,不动指针哦)*-*
}
current = current->next; //移动到下一个节点
}
} while (swapped); //如果发生了交换,继续下一轮排序
}
void display( ) const { //嘿嘿,展示一下
if (count == 0) {
cout << "看什么看,一本书都没有" << endl;
return;
}
cout << setw(6) << "序号"
<< setw(18) << "ISBN"
<< setw(25) << "书名"
<< setw(8) << "价格" << endl;
Node* current = head; //从头节点开始
while (current != NULL) { //遍历链表
cout << setw(6) << current->book->num
<< setw(18) << current->book->ISBN
<< setw(25) << current->book->name
<< setw(8) << current->book->price << endl;
current = current->next; //移动到下一个节点
}
}
void defaultOrder( ) { //按序号排序
if (head == NULL || head->next == NULL) return; //如果链表为空或只有一个节点,不需要排序
bool swapped; //标记是否发生了交换
Node* current = head; //当前节点
do {
swapped = false; //初始化为未发生交换
current = head; //从头节点开始
while (current->next != NULL) { //遍历链表
if (current->book->num >
current->next->book->num) { //如果当前节点的序号大于下一个节点的序号
swap(current, current->next); //交换两个节点的内容
swapped = true; //标记发生了交换
}
current = current->next; //移动到下一个节点
}
} while (swapped); //如果发生了交换,继续下一轮排序
}
int getCount( ) const { //获取当前节点数量
return count;
}
Node* findBookByISBN(const string& ISBN) const { //按ISBN值查找
Node* current = head; //从头节点开始
while (current != NULL) { //遍历链表
if (current->book->ISBN == ISBN) { //如果找到了对应的ISBN
return current; //返回节点指针
}
current = current->next; //移动到下一个节点
}
return NULL; //如果没有找到,返回NULL
}
private:
Node* head; //链表的头节点
int count; //链表中的节点数量
void deleteNode(Node* prev) { //删除节点
Node* toDelete = prev ? prev->next : head; //要删除的节点,很有东西的好不好 @…^…@
if (toDelete == head) { //如果是头节点
head = head->next; //更新头节点
} else {
prev->next = toDelete->next; //更新前一个节点的指向
}
delete toDelete->book; //删除图书信息
delete toDelete; //删除节点
count--; //节点数量减1
}
void swap(Node* a, Node* b) { //换值不换结点哦!
Book temp = *a->book; //临时保存节点a的内容
*a->book = *b->book;
*b->book = temp; //交换节点a和b的内容
}
};
int main( ) {
LinkList bookList; //创建一个链表对象
Book books[ ] = { //定义一个图书数组,包含一些初始图书信息
{1,"9787302257646","程序设计基础",25},
{2,"9787302219972","单片机技术及应用",32},
{3,"9787302203513","编译原理",46},
{4,"9787811234923","汇编语言程序设计教程",21},
{5,"9787512100831","计算机操作系统",17},
{6,"9787302265436","计算机导论实验指导",18},
{7,"9787302180630","实用数据结构",29},
{9,"9787302171676","C#面向对象程序设计",39},
{10,"9787302250692","C语言程序设计",42},
{11,"9787302150664","数据库原理",35},
{12,"9787302260806","Java编程与实践",56},
{13,"9787302252887","Java程序设计与应用教程",39},
{14,"9787302198505","嵌入式操作系统及编程",25},
{15,"9787302169666","软件测试",24},
{16,"9787811231557","Eclipse基础与应用",35},
};
for (int i = 0; i < sizeof(books) / sizeof(books[0]); i++) {
bookList.insert(books[i]); //将初始图书信息添加到链表中
}
string choice; //用户选择的操作
while (true) { //无限循环,直到用户选择退出
bookList.display( );
bookList.showmenu ( );
cin >> choice; //输入操作选项
switch (choice[0]) { //根据用户选择的操作执行相应的功能
case '1':
{
string ISBN;
cout << "请输入要查找的图书ISBN:"; cin >> ISBN;
LinkList::Node* node = bookList.findBookByISBN(ISBN); //查找图书
if (node != NULL) { //如果找到了图书
cout << "找到图书:" << endl;
cout << "ISBN: " << node->book->ISBN << endl;
cout << "书名: " << node->book->name << endl;
cout << "价格: " << node->book->price << endl;
} else {
cout << "找不到该ISBN的图书。" << endl;
}
bookList.refresh (); //清屏并暂停
break;
}
case '2':
{
int num,price;
string ISBN, name;
cout << "请输入要添加的图书信息:" << endl;
cout << "序号:"; cin >> num;
cout << "ISBN:"; cin >> ISBN;
cout << "书名:"; cin >> name;
cout << "价格:"; cin >> price;
bookList.insert(Book(num, ISBN, name, price)); //添加图书,匿名对象,有参构造
bookList.refresh ( ); //清屏并暂停
break;
}
case '3':
{
string ISBN;
cout << "请输入要删除的图书ISBN:"; cin >> ISBN;
bookList.remove(ISBN); //删除图书
bookList.refresh ( ); //清屏并暂停
break;
}
case '4':
{
string ISBN;
cout << "请输入要修改的图书ISBN:"; cin >> ISBN;
bookList.alter(ISBN); //修改图书
bookList.refresh ( ); //清屏并暂停
break;
}
case '5':
bookList.order( ); //按价格排序
bookList.display( ); //显示图书列表
bookList.refresh ( ); //清屏并暂停
break;
case '6':
bookList.defaultOrder( ); //按序号排序
bookList.display( ); //显示图书列表
bookList.refresh ( ); //清屏并暂停
break;
case '7':
{
while (true) {
cout << "你确定吗" << endl
<< "1. 确定" << endl
<< "2. 取消" << endl;
string choice;
cin >> choice;
if (choice == "1") {
cout << "毁灭吧" << endl;
bookList.clear( );
bookList.refresh ( );
break;
} else if (choice == "2") {
cout << "清空操作已取消" << endl;
bookList.refresh ( );
break;
} else {
cout << "孩子,你在搞笑吗?请重新输入" << endl;
}
}
break;
}
case '8':
{
int num = bookList.getCount( );
cout << "现在有" << num << "本书" << endl;
bookList.refresh ( );
break;
}
case '0':
cout << "欢迎下次光临" << endl;
return 0; //退出程序
default:
cout << "无效的选项,请重新选择。" << endl;
bookList.refresh ( ); //清屏并暂停
break;
}
}
}