图书信息管理系统的设计与实现
(一)实验内容:
设计并实现一个图书信息管理系统。根据实验要求设计该系统的菜单和交互逻辑,并编码实现增删改查的各项功能。 该系统至少包含以下功能:
- 根据指定图书个数,逐个输入图书信息;
- 逐个显示图书表中所有图书的相关信息;
- 能根据指定的待入库的新图书的位置和信息,将新图书插入到图书表中指定的位置;
- 根据指定的待出库的旧图书的位置,将该图书从图书表中删除;
- 能统计表中图书个数;
- 实现图书信息表的图书去重;
- 实现最爱书籍查询,根据书名进行折半查找,要求使用非递归算法实现,成功返回此书籍的书号和价格;
- 图书信息表按指定条件进行批量修改;
- 利用快速排序按照图书价格降序排序;
- 实现最贵图书的查找;
各个数据结构的定义
创建图书信息类
struct BookMessage
{
string bookId="";//书的ID
string bookName="";//书的名字
double price=0;//书的价格
};
创建链表的结点
struct LibraryNode
{
BookMessage data;//数据域
LibraryNode* next=NULL;//指针域
};
创建图书管理系统(链表)
#pragma once
#include"LibraryNode.h"
#include<iostream>
#include<iomanip>
class LinkListSystem
{
public:
LinkListSystem();//默认构造函数
LinkListSystem(BookMessage* node,int length);//带参构造函数
~LinkListSystem();//析构函数
int GetLength();//得到节点的个数
BookMessage GetData(int pos);//根据指定的位置得到数据
void Insert(BookMessage data, int pos);//在指定位置插入数据
int Search(BookMessage data);//在表中查找指定数据得到其下标
void Delete(int pos);//根据下标删除数据
void Cout();//输出表中所有信息
void Cout(int pos);
LibraryNode* MoveTo(int pos);//移动节点到pos位置
void Sort(int start,int end);//按照图书价格快速排序
void Sort();//按照图书名字选择排序
void Insert(BookMessage book);//把结点插入链表末尾
private:
LibraryNode* first;//头节点
};
各项功能具体实现代码
默认构造函数
LinkListSystem::LinkListSystem()
{
//默认构造函数
this->first = new LibraryNode[1];
this->first->next = NULL;
}
带参构造函数得到链表的长度
int LinkListSystem::GetLength()
{
//得到节点的个数
LibraryNode* p = this->first->next;
int Length = 0;
while (p != NULL)
{
Length++;
p = p->next;
}
return Length;
}
根据指定的位置得到数据
BookMessage LinkListSystem::GetData(int pos)
{
//根据指定的位置得到数据
LibraryNode* p = this->first;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
return p->data;
}
移动节点到pos位置
LibraryNode* LinkListSystem::MoveTo(int pos)
{
//移动节点到pos位置
LibraryNode* p = this->first;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
return p;
}
按照图书价格快速排序
void LinkListSystem::Sort(int start, int end)
{
//按照图书价格快速排序
if (start >= end)
{
return;
}
BookMessage book = this->GetData(start);
int i = start+1;
int j = end;
while (i!=j)
{
//找到一个比哨站大的值
while (this->GetData(j).price < book.price && j > i)
{
j--;
}
//找到一个比哨站小的值
while (this->GetData(i).price > book.price && j > i)
{
i++;
}
if (j > i)
{
BookMessage temp = this->GetData(i);
this->MoveTo(i)->data.bookId = this->GetData(j).bookId;
this->MoveTo(i)->data.bookName = this->GetData(j).bookName;
this->MoveTo(i)->data.price = this->GetData(j).price;
this->MoveTo(j)->data.bookId = temp.bookId;
this->MoveTo(j)->data.bookName = temp.bookName;
this->MoveTo(j)->data.price = temp.price;
}
}
//不能交换最后一个值作为新哨站
if (i == end)
{
i = end - 1;
}
this->MoveTo(1)->data.price = this->GetData(i).price;
this->MoveTo(1)->data.bookId = this->GetData(i).bookId;
this->MoveTo(1)->data.bookName = this->GetData(i).bookName;
this->MoveTo(i)->data.bookId = book.bookId;
this->MoveTo(i)->data.bookName = book.bookName;
this->MoveTo(i)->data.price = book.price;
this->Sort(start, i - 1);
this->Sort(i + 1, end);
}
在列表末尾插入节点
void LinkListSystem::Insert(BookMessage book)
{
//在列表末尾插入节点
LibraryNode* p = new LibraryNode;
p->data.bookId= book.bookId;
p->data.bookName = book.bookName;
p->data.price = book.price;
p->next = NULL;
LibraryNode* q = MoveTo(this->GetLength());
q->next = p;
}
在指定位置插入数据
void LinkListSystem::Insert(BookMessage data, int pos)
{
//在指定位置插入数据
LibraryNode* p = new LibraryNode[1];
p->data = data;
LibraryNode* q = this->MoveTo(pos - 1);
p->next = q->next;
q->next = p;
}
在表中查找指定数据得到其下标
int LinkListSystem::Search(BookMessage data)
{
//在表中查找指定数据得到其下标
int pos = 0;
for (LibraryNode* p = this->first->next; p != NULL; p = p->next)
{
pos++;
if (p->data.bookId==data.bookId&&p->data.bookName==data.bookName&&p->data.price==data.price)
{
return pos;
}
}
return -1;
}
根据下标删除数据
void LinkListSystem::Delete(int pos)
{
//根据下标删除数据
LibraryNode* p = this->MoveTo(pos - 1);
LibraryNode* q = p->next;
p->next = q->next;
delete q;
}
输出表中信息
void LinkListSystem::Cout()
{
//输出表中信息
for (LibraryNode* p = this->first->next; p != NULL; p = p->next)
{
cout << "书的ID为:" << p->data.bookId << endl;
cout << "书的名字为:" << p->data.bookName << endl;
cout << "书的价格为:" <<setiosflags(ios::fixed)<<setprecision(2)<<p->data.price << endl;
}
cout << "0 0 0" << endl;
cout << endl;
}
输出列表中pos位置的数据信息
void LinkListSystem::Cout(int pos)
{
//输出列表中pos位置的数据信息
cout << "书的ID为:" << this->MoveTo(pos)->data.bookId << endl;
cout << "书的名字为:" << this->MoveTo(pos)->data.bookName << endl;
cout << "书的价格为:" << setiosflags(ios::fixed) <<setprecision(2) << this->MoveTo(pos)->data.price << endl;
}
主函数代码
使用文件流读入信息并创建列表
void ReadBooks(LinkListSystem& system)
{
//使用文件流读入列表信息
ifstream file;
file.open("books.txt");
while (true)
{
BookMessage book;
file >> book.bookId;
file >> book.bookName;
file >> book.price;
if (book.bookId == "0" && book.bookName == "0" && book.price == 0)
{
break;
}
system.Insert(book);
}
}
通过键盘输入创建表的信息
void InputBook(LinkListSystem& system)
{
cout << "请输入图书的数量:";
int number;
cin >> number;
for (int i = 0; i < number; i++)
{
BookMessage book;
cout << "请输入新入库的书的ID:";
cin >> book.bookId;
cout << "请输入新入库的书的名字:";
cin >> book.bookName;
cout << "请输入新入库的书的价格:";
cin >> book.price;
system.Insert(book);
}
}
读入图书信息表,然后计算所有图书的平均价格,将所有低于平均价格的图书价格提高20%,所有高于或等于平均价格的图书价格提高10%,最后逐行输出价格修改后的图书信息。
void ChangePrice(LinkListSystem& system)
{
//修改
double averagePrice = 0;
for (int i = 0; i < system.GetLength()+1; i++)
{
averagePrice += system.GetData(i).price;
}
//计算平均价格
averagePrice = averagePrice / system.GetLength();
for (int i = 0; i < system.GetLength()+1; i++)
{
LibraryNode* temp = system.MoveTo(i);
if (temp->data.price>= averagePrice)
{
temp->data.price = temp->data.price * 1.1;
}
else
{
temp->data.price = temp->data.price * 1.2;
}
}
system.Cout();
}
读入相应的图书信息表,然后查找价格最高的图书,输出相应图书的信息。
void SearchExpensiveBook(LinkListSystem& system)
{
//查找
int maxIndex = 0;
int sameIndexNumber = 1;
for (int i = 1; i < system.GetLength()+1; i++)
{
if (system.GetData(i).price > system.GetData(maxIndex).price)
{
maxIndex = i;
sameIndexNumber = 1;
}
else if(system.GetData(i).price ==system.GetData(maxIndex).price)
{
sameIndexNumber++;
}
}
cout << "最贵的图书的数量为:"<<sameIndexNumber << endl;
for (int i = 0; i < system.GetLength()+1; i++)
{
if (system.GetData(i).price == system.GetData(maxIndex).price)
{
system.Cout(i);
}
}
cout << endl;
}
读入相应的图书信息表,然后根据指定的最爱图书的名字,利用二分查找输出相应图书的信息。
void SearchPreferBook(LinkListSystem& system)
{
//二分查找
cout << "请输入最喜欢图书的名字:";
string bookName;
cin >> bookName;
int left = 0;
int right = system.GetLength();
int indexNumber=-1;
//按名字从小到大排序
system.Sort();
while (left<=right)
{
int mid = (left + right) / 2;
if (system.GetData(mid).bookName == bookName)
{
indexNumber = mid;
break;
}
if (system.GetData(mid).bookName < bookName)
{
left = mid + 1;
}
else
{
right = mid - 1;
}
}
if (indexNumber == -1)
{
cout << "没有此书" << endl;
}
else
{
int count = 0;//最喜欢图书的数量
for (int i = 1; i < system.GetLength(); i++)
{
if (system.GetData(i).bookName.find(bookName) != -1)
{
system.Cout(i);
count++;
}
}
cout << "喜欢的图书的数量为:" << count << endl;
}
}
读入指定的待入库的新图书的位置和信息,将新图书插入到图书表中指定的位置上,最后输出新图书入库后所有图书的信息。
void BookInsert(LinkListSystem& system)
{
//插入
BookMessage book;
cout << "请输入插入的位置:";
int index;
cin >> index;
cout << "请输入新入库的书的ID:";
cin >> book.bookId;
cout << "请输入新入库的书的名字:";
cin >> book.bookName;
cout << "请输入新入库的书的价格:";
cin >> book.price;
system.Insert(book, index);
system.Cout();
}
读入指定的待出库的旧图书的书号,将该图书从图书表中删除,最后输出旧图书出库后所有图书的信息。
void BookDelete(LinkListSystem& system)
{
//删除
cout << "请输入待出库的旧图书的书号:";
string bookId;
cin >> bookId;
for (int i = 0; i < system.GetLength()+1; i++)
{
if (system.GetData(i).bookId == bookId)
{
system.Delete(i);
}
}
system.Cout();
}
出版社出版的任何一本图书的书号(ISBN)都是唯一的,即图书表中不允许包含书号重复的图书。读入相应的图书信息表(事先加入书号重复的记录),然后进行图书的去重,即删除书号重复的图书(只留第一本),最后输出去重后所有图书的信息。
void BookDeleteDuplication(LinkListSystem& system)
{
//去重
int length = system.GetLength()+1;
for (int i = 0; i < length; i++)
{
for (int j = i+1; j< length; j++)
{
if (system.GetData(i).bookId == system.GetData(j).bookId)
{
system.Delete(j);
length--;
j--;
}
}
}
cout << "书的数量为:";
cout << system.GetLength();
cout << endl;
system.Cout();
}
实验结果
主菜单
使用文件流新建列表
通过键盘输入创建表的信息
修改图书表信息
查找图书信息表最贵的图书
查找图书信息表最爱的图书
新书入库
旧书出库
图书去重
去重前
去重后
图书的数量
把图书按照价格从大到小排序