图书信息管理系统(顺序表)
图书信息管理系统(顺序表)任务需求代码任务需求 读取给定的图书文件book.txt中的信息,完成一个图书信息管理系统,该系统的各个功能模块利用菜单选项进行选择,要求程序具有正确性、可读性(变量函数命名规范、核心语句添加注释)、健壮性(数据非法时能够进行相应处理)。输出:读取book.txt中的文件信息并依次输出所有图
·
任务需求
读取给定的图书文件book.txt中的信息,完成一个图书信息管理系统,该系统的各个功能模块利用菜单选项进行选择,要求程序具有正确性、可读性(变量函数命名规范、核心语句添加注释)、健壮性(数据非法时能够进行相应处理)。
输出:读取book.txt中的文件信息并依次输出所有图书信息(书号、书名、价格)。
插入:根据指定的位置i(1≤i≤n+1)和给定的一本图书信息,将该图书插入到位置i,并将变化后的图书信息回写到book.txt。
删除:根据指定的位置i(1≤i≤n),删除该位置上的图书信息,并将变化后的图书信息回写到book.txt。
查找
1、按位置进行查找:根据输入的位置i(1≤i≤n),查找位置i上的图书信息并输出;
2、按书名进行查找:根据输入的书名,查找该图书的信息并输出(如果有多本,则全部输出)。
修改:将价格小于25元的图书价格提高20%,价格大于等于25元的图书价格提高10%,将修改后的图书信息写入文件book_newprice.txt中。
排序:按书的价格由低到高排序写入文件book_newsort.txt中。(必须包含冒泡排序,其他排序任选)
注意:book.txt的内容如下图所示
代码
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
const int MAXSIZE = 1e5+7; //最多数据元素个数
const int MAXLEN = 107; //字符串类型数据的最长长度
const int INF = 0x3f3f3f3f; //整型的无穷大
typedef struct{
char no[MAXLEN]; //图书编号
char name[MAXLEN]; //图书名字
double price; //图书价格
}Book;
typedef struct{
Book *elem; //存储空间的基地址
int length; //图书表中当前图书的个数
}SqList;
void Init(SqList &L); //初始化
void ReadFromFile(SqList &L); //读文件
void WriteIntoFile(SqList &L, const char *file); //写文件
void IllegalInput(string menu); //非法输入
void ShowMainMenu(); //显示主菜单
void ShowAll(SqList &L); //显示所有图书信息
void Insert(SqList &L); //插入图书信息
void Erase(SqList &L); //删除图书信息
void Modify(SqList &L); //修改图书信息
void Quit(); //退出
void ShowSearchMenu(); //显示查找菜单
void SearchByPosition(SqList &L); //通过位置查找图书信息
void SearchByName(SqList &L); //通过书名查找图书信息
void ShowSortMenu(); //显示排序菜单
void InsertionSort(SqList &L); //插入排序
void ShellSort(SqList &L); //希尔排序
void SelectionSort(SqList &L); //选择排序
void HeapSort(SqList &L); //堆排序
void BubbleSort(SqList &L); //冒泡排序
void QuickSort(SqList &L); //快速排序
void MergeSort(SqList &L); //归并排序
int main(){
ShowMainMenu();
return 0;
}
//主菜单界面
void ShowMainMenu(){
system("cls");
printf("*************************图书管理系统*************************\n");
printf("显示所有图书信息---------------------------------------------1\n");
printf("插入---------------------------------------------------------2\n");
printf("删除---------------------------------------------------------3\n");
printf("查找---------------------------------------------------------4\n");
printf("修改---------------------------------------------------------5\n");
printf("排序---------------------------------------------------------6\n");
printf("退出---------------------------------------------------------7\n\n");
printf("请输入想进入的二级菜单:");
SqList L;
Init(L);
ReadFromFile(L);
int op;
scanf("%d", &op);
switch(op){
case 1:{ //输入1,显示所有书本
ShowAll(L);
break;
}
case 2:{ //输入2,插入功能
Insert(L);
break;
}
case 3:{ //输入3,删除功能
Erase(L);
break;
}
case 4:{ //输入4,显示搜索界面
ShowSearchMenu();
break;
}
case 5:{ //输入5,修改
Modify(L);
break;
}
case 6:{ //输入6,显示排序界面
ShowSortMenu();
break;
}
case 7:{ //输入7,退出程序
Quit();
break;
}
default:{ //非法输入
IllegalInput("main");
break;
}
}
delete [] L.elem; //释放空间
}
//查找界面
void ShowSearchMenu(){
system("cls");
printf("************************请选择查找方式************************\n");
printf("按位置查找---------------------------------------------------1\n");
printf("按书名查找---------------------------------------------------2\n");
printf("返回一级菜单-------------------------------------------------3\n\n");
printf("请输入您所选的排序方式:");
SqList L;
Init(L);
ReadFromFile(L);
int op;
scanf("%d", &op);
switch(op){
case 1:{ //输入1,根据位置查找
SearchByPosition(L);
break;
}
case 2:{ //输入2,根据名字查找
SearchByName(L);
break;
}
case 3:{ //输入3,返回主菜单
ShowMainMenu();
break;
}
default:{ //非法输入
IllegalInput("search");
break;
}
}
delete [] L.elem; //释放空间
}
//排序界面
void ShowSortMenu(){
system("cls"); //清屏
printf("************************请选择排序方式************************\n");
printf("插入排序-----------------------------------------------------1\n");
printf("希尔排序-----------------------------------------------------2\n");
printf("选择排序-----------------------------------------------------3\n");
printf("堆排序-------------------------------------------------------4\n");
printf("冒泡排序-----------------------------------------------------5\n");
printf("快速排序-----------------------------------------------------6\n");
printf("归并排序-----------------------------------------------------7\n");
printf("返回一级菜单-------------------------------------------------8\n\n");
printf("请输入您所选的排序方式:");
SqList L;
Init(L);
ReadFromFile(L);
int op;
scanf("%d", &op);
switch(op){
case 1:{ //输入1,执行插入排序
InsertionSort(L);
break;
}
case 2:{ //输入2,执行希尔排序
ShellSort(L);
break;
}
case 3:{ //输入3,执行选择排序
SelectionSort(L);
break;
}
case 4:{ //输入4,执行堆排序
HeapSort(L);
break;
}
case 5:{ //输入5,执行冒泡排序
BubbleSort(L);
break;
}
case 6:{ //输入6,执行快速排序
QuickSort(L);
break;
}
case 7:{ //输入7,执行归并排序
MergeSort(L);
break;
}
case 8:{ //输入8,返回主菜单
ShowMainMenu();
break;
}
default:{ //非法输入
IllegalInput("sort");
break;
}
}
delete [] L.elem; //释放空间
}
//初始化
void Init(SqList &L){
L.elem = new Book [MAXSIZE]; //分配新空间
if (! L.elem){
exit(-2); //存储分配失败,则退出
}
L.length = 0;
}
//读文件
void ReadFromFile(SqList &L){
ifstream rd("book.txt"); //新建一个文件输出流指针,打开文件book.txt
if (! rd){
exit(0); //如果打开失败,异常结束
}
char title[MAXLEN];
char noTitle[MAXLEN], nameTitle[MAXLEN], priceTitle[MAXLEN];
rd >> title; //读取标题
rd >> noTitle >> nameTitle >> priceTitle; //读取标题
Book book;
while (rd >> book.no >> book.name >> book.price){
L.elem[L.length] = book; //将新的图书放在第L.length位置上
L.length++; //表长加1
}
rd.close(); //关闭文件流指针
}
//写文件
void WriteIntoFile(SqList &L, const char *file){
ofstream w(file); //新建一个文件输入流指针,打开文件file
if (! w){
exit(0); //如果打开失败,异常结束
}
w << "北京林业大学图书馆计算机类图书采购列表" << endl;
w << "ISBN 书名 定价" << endl;
for (int i = 0; i < L.length; i++){
w << L.elem[i].no << " " << L.elem[i].name << " " << L.elem[i].price << endl; //将图书信息写入文件中
}
w.close(); //关闭文件流指针
}
//非法输入
void IllegalInput(string menu){
printf("输入失败,请重新输入!");
system("pause"); //需要输入一个字符程序才能执行
getchar(); //读取字符
//根据menu分别进入不同的菜单
if (menu == "main"){
ShowMainMenu();
}else if (menu == "search"){
ShowSearchMenu();
}else if (menu == "sort"){
ShowSortMenu();
}
}
//显示所有图书信息
void ShowAll(SqList &L){
system("cls"); //清屏
if (L.length == 0){ //表长为0,没有图书
printf("暂无图书!");
}else{
printf("所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //按顺序输出所有的图书信息
}
printf("=================================================================\n\n");
}
//按任意键返回主菜单
system("pause");
ShowMainMenu();
}
//插入图书信息
void Insert(SqList &L){
system("cls"); //清屏
int pos;
Book book;
printf("请输入要插入的位置(1~%d):", L.length+1);
scanf("%d", &pos);
//若想要插入的位置不在区间[1,L.length+1],则插入的位置不合法,需要重新输入位置
while (pos < 1 || pos > L.length+1){
printf("输入不正确,请重新输入:");
scanf("%d", &pos);
}
//依次输入图书编号、书名、价格
printf("请输入图书编号:");
scanf("%s", book.no);
printf("请输入图书书名:");
scanf("%s", book.name);
printf("请输入图书价格:");
scanf("%lf", &book.price);
for (int i = L.length-1; i >= pos-1; i--){
L.elem[i+1] = L.elem[i]; //区间[pos,L.length-1]中的每个图书信息都要向后移动
}
L.elem[pos-1] = book; //将新的图书信息放入pos-1的位置上
L.length++; //表长加1
WriteIntoFile(L, "book.txt"); //将插入后的所有图书信息重新写入到book.txt中
printf("\n\n插入成功!\n");
//按任意键返回主菜单
system("pause");
ShowMainMenu();
}
//删除图书信息
void Erase(SqList &L){
system("cls"); //清屏
int pos;
Book book;
printf("请输入要删除的位置(1~%d):", L.length);
scanf("%d", &pos);
//若想要删除的位置不在区间[1,L.length],则删除的位置不合法,需要重新输入位置
while (pos < 1 || pos > L.length){
printf("输入不正确,请重新输入:");
scanf("%d", &pos);
}
for (int i = pos; i <= L.length-1; i++){
L.elem[i-1] = L.elem[i]; //区间[pos+1,L.length-1]中的每个图书信息都要向前移动
}
L.length--; //表长减1
WriteIntoFile(L, "book.txt"); //将删除后的所有图书信息重新写入到book.txt中
printf("\n\n删除成功!\n");
//按任意键返回主菜单
system("pause");
ShowMainMenu();
}
//修改图书信息
void Modify(SqList &L){
system("cls"); //清屏
//依次遍历所有图书,按要求提高价格
for (int i = 0; i < L.length; i++){
if (L.elem[i].price < 25){
L.elem[i].price *= 1.2;
}else{
L.elem[i].price *= 1.1;
}
}
//显示所有修改后的图书信息
printf("修改后所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price);
}
printf("=================================================================\n");
printf("因某些不可抗力,图书价格小于25元的书价格提高20%,图书价格大于等于25元的书价格提高10%。敬请谅解!\n\n");
WriteIntoFile(L, "book.txt"); //将修改后的所有图书信息重新写入到book.txt中
WriteIntoFile(L, "book_newprice.txt"); //将修改后的所有图书信息写入到book_newprice.txt中
//按任意键返回主菜单
system("pause");
ShowMainMenu();
}
//退出
void Quit(){
system("cls"); //清屏
printf("确定要退出?y/n:");
char op;
scanf("%c", &op);
if (op == 'n' || op == 'N'){
ShowMainMenu();
}else if (op != 'y' && op != 'Y'){
Quit();
}
}
//下面为2种查找:
//按位置查找图书信息
void SearchByPosition(SqList &L){
system("cls"); //清屏
int pos;
printf("请输入要查找的图书位置(1~%d):", L.length);
scanf("%d", &pos);
//若想要查找的位置不在区间[1,L.length],则查找的位置不合法,需要重新输入位置
while (pos < 1 || pos > L.length){
printf("输入不正确,请重新输入:");
scanf("%d", &pos);
}
printf("\n\n位于%d位的图书信息:\n\n", pos);
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
printf("%-20s%-40s%.2f\n", L.elem[pos-1].no, L.elem[pos-1].name, L.elem[pos-1].price); //因为指针的下标从0开始,所以要输出pos-1位置的图书信息
printf("=================================================================\n\n");
//按任意键返回主菜单
system("pause");
ShowSearchMenu();
}
//按书名查找图书信息
void SearchByName(SqList &L){
system("cls");
char name[MAXLEN];
printf("请输入想要查找的书名:");
scanf("%s", name);
SqList tmp; //建立一个新的线性表,用于存储书名为所找书名的图书信息
Init(tmp);
for (int i = 0; i < L.length; i++){ //依次遍历所有图书
if (strcmp(L.elem[i].name, name) == 0){ //找到书名为name的图书
tmp.elem[tmp.length] = L.elem[i]; //将这本书的信息放入顺序表tmp的tmp.length的位置
tmp.length++; //tmp表长加1
}
}
if (tmp.length == 0){ //找不到书名为name的书,tmp的表长为0
printf("\n\n对不起,查无此书!\n\n");
}else{
printf("\n\n所有书名为%s图书信息:\n\n", name);
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < tmp.length; i++){
printf("%-20s%-40s%.2f\n", tmp.elem[i].no, tmp.elem[i].name, tmp.elem[i].price); //依次输出tmp的图书信息
}
printf("=================================================================\n\n");
}
delete tmp.elem; //释放tmp的空间
//按任意键返回查找菜单页面
system("pause");
ShowSearchMenu();
}
//下面的为各种排序:
//插排
//O(N*N),稳定
void InsertionSort(SqList &L){
system("cls");
//插入排序实现过程:
for (int i = 1; i < L.length; i++){ //i是当前数
for (int j = i-1 ; j >= 0; j--){ //j是从i-1开始向前移动,每次与i图书比较
if (L.elem[i].price < L.elem[j].price){ //若 i图书的价格 < j图书的价格,说明i图书当前是要插入到j图书之前
swap(L.elem[i], L.elem[j]); //交换i图书和j图书的位置
i = j-1; //互换后i也要向前移动一位
}else{
break; //直到i图书的价格比j图书大,因为前面从小到大已经排好序,所以没有必要继续向前判断了
}
}
}
printf("经过插入排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
//希尔排序
//O(N*sqrt(N)),不稳定
void ShellSort(SqList &L){
system("cls");
int h = 1;
while (h < L.length / 3){
h = 3 * h + 1; //分段
}
while (h >= 1){
//将数组变为h有序,两个for循环组成插入排序
for (int i = h; i < L.length; i++){
for (int j = i; j >= h && L.elem[j].price < L.elem[j-h].price; j -= h){ //相隔h的元素进行比较,从后往前迭代
swap(L.elem[j], L.elem[j-h]); //交换 j图书 和 j+h图书
}
}
h = h / 3;
}
printf("经过希尔排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
//选择排序
//O(N*N),不稳定
void SelectionSort(SqList &L){
system("cls");
//选择排序实现过程:
for (int i = 0; i < L.length; i++){
int idx = i; //记录这趟排序价格最小的图书
for (int j = i+1; j < L.length; j++){
if (L.elem[idx].price > L.elem[j].price){ //如果价格比idx图书的价格还小
idx = j; //idx指向这趟排序价格最小的图书
}
}
swap(L.elem[idx], L.elem[i]); //交换idx图书和i图书
}
printf("经过选择排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
//堆排
//O(N*log N),不稳定
void Adjust(SqList &L, int i, int n){
int parent = i; //父节点
int child = 2 * i + 1; //左子节点
while (child < n){
if (child +1 < n && L.elem[child].price < L.elem[child+1].price){
child++; //变成右子节点
}
if (L.elem[parent].price < L.elem[child].price){
swap(L.elem[child], L.elem[parent]); //交换父子节点
parent = child; //子节点就变为父节点
}
child = child * 2 + 1;
}
}
void HSort(SqList &L){ //建立小根堆
for (int i = L.length/2-1; i >= 0; i--){
Adjust(L, i, L.length);
}
for (int i = L.length-1; i > 0; i--){
swap(L.elem[i], L.elem[0]); //将堆顶记录与当前未排序的序列[0, i-1]中的最后一个元素交换
Adjust(L, 0, i); //将[0,i]调整为小根堆
}
}
void HeapSort(SqList &L){
system("cls");
HSort(L); //堆排序
printf("经过堆排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
//冒泡
//O(N*N),稳定
void BubbleSort(SqList &L){
system("cls"); //清屏
//冒泡排序实现过程:
for (int i = 0; i < L.length-1; i++){ //执行L.length-1遍,每遍将无序中的最大的那个沉底
for (int j = 0; j < L.length-i-1; j++){ //因为后面i个都已经有序,只需排前面L.length-i-1个
if (L.elem[j].price > L.elem[j+1].price){ //若j图书的价格 > j+1图书的价格
swap(L.elem[j], L.elem[j+1]); //j和j+1的图书交换位置
}
}
}
printf("经过冒泡排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
//快排
//O(N*log N),不稳定
void QSort(SqList &L, int l, int r){ //对区间[l,r]的快速排序
if (l >= r){
return ; //当左 >= 右时,返回
}
Book x = L.elem[(l+r)>>1]; //哨兵
int i = l-1, j = r+1;
while (i < j){
//把比哨兵小的左移,比哨兵大的右移
do{
i++;
}while (L.elem[i].price < x.price);
do{
j--;
}while (L.elem[j].price > x.price);
if (i < j){
swap(L.elem[i], L.elem[j]);
}
}
QSort(L, l, j); //对左半边再次快速排序
QSort(L, j+1, r); //对右半边再次快速排序
}
void QuickSort(SqList &L){
system("cls");
QSort(L, 0, L.length-1);
printf("经过快速排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
//归并排序
//O(N*log N),不稳定
void Merge(SqList &L, int l, int r){ //合并[l,r]
int mid = (l + r) >> 1;
int n1 = mid - l + 1;
int n2 = r - mid;
Book *left = new Book[n1+1]; //左半部分
Book *right = new Book[n2+1]; //右半部分
left[n1].price = INF; //定义为无穷大
right[n2].price = INF; //定义为无穷大
int tmp = l;
for (int i = 0; i < n1; i++){
left[i] = L.elem[tmp]; //将L.elem左半部分放入left中
tmp++;
}
tmp = mid + 1;
for (int i = 0; i < n2; i++){
right[i] = L.elem[tmp]; //将L.elem右半部分放入right中
tmp++;
}
for (int i = 0, j = 0, k = l; k <= r; k++){
if (left[i].price <= right[j].price){ //根据左右大小依次放入L.elem中
L.elem[k] = left[i];
i++;
}else{
L.elem[k] = right[j];
j++;
}
}
delete [] left; //释放空间
delete [] right; //释放空间
}
void MSort(SqList &L, int l, int r){
if (l >= r){
return ; //当 左 >= 右 时,返回
}
int mid = (l + r) >> 1;
MSort(L, l, mid); //对左半边归并排序
MSort(L, mid+1, r); //对右半边归并排序
Merge(L, l, r); //将左右半边合并
}
void MergeSort(SqList &L){
system("cls");
MSort(L, 0, L.length-1);
printf("经过归并排序后,所有的图书信息:\n\n");
printf(" ISBN 书名 定价\n");
printf("=================================================================\n");
for (int i = 0; i < L.length; i++){
printf("%-20s%-40s%.2f\n", L.elem[i].no, L.elem[i].name, L.elem[i].price); //依次输出排序后的图书信息
}
printf("=================================================================\n\n");
WriteIntoFile(L, "book_newsort.txt"); //将修改后的所有图书信息写入到book_newsort.txt中
//按任意键返回排序菜单页面
system("pause");
ShowSortMenu();
}
更多推荐
所有评论(0)