目录
《基于线性表的图书信息管理》基于“顺序存储结构”和“链式存储结构”来实现对图书信息的管理。两种存储结构所定义的功能略有不同:“顺序存储结构”定义了“查找最贵书籍”功能,“链式存储结构”定义了“按价格将图书从高到低排序”的功能;两种存储结构的相同点在于:都设计了“图书入库”、“图书出库”和“查看图书信息表”的功能。
(1)构造初始信息表:输入n+1行,其中第n行是n本图书的信息( 包括书号、书名和价格), 每本图书信息占一行,书号、书名、价格用空格分隔,价格之后没有空格。最后第n+1行是输入结束的标志:0 0 0 (空格分割的三个0)。其中书号和书名为字符串类型 ,价格为浮点数类型 。
(2)输入操作指令:当界面显示“请输入操作系统(例如:A):>>”时,需要输入A或B来选择后续操作的存储结构,当输入为A时为链式操作系统,B为顺序操作系统。
(3)当界面显示“请输入初始信息,完成图书信息表的初始化:”时,根据上述“构造初始信息表”的要求进行输入完成信息表初始化。
(4)当界面显示“操作提示框”和“请输入操作指令(例如1 Y):>>”需要根据所需的功能进行指令输入。例如输入“1 Y”,则表示在“按照价格对图书信息表进行排序”之后会将操作后的图书信息表输出;输入“2 N”,则表示在“图书入库”之后不将图书信息表输出。特殊的,当选择指令为4,无论后方字符为N还是Y都会将信息表输出;当指令选择为5时,无论后方字符为N还是Y都会退出系统,且退出前不会输出信息表。


本程序输出形式共有三种,且图书信息查看采用操作员可选择方式(即:操作员可以选择程序在完成一项操作后是否输出全部图书信息)。
(1)第一种:全图书信息输出。输出共n+1行,第一行提示操作完成,并输出当前信息表中图书数量;后续n行是n本图书的信息(书号、书名和价格),每本图书信息占一行,书号、书名和价格以空格分隔,其中价格输出保留两位小数。
(2)第二种:操作完成情况提示。当操作人员选择程序完成一项操作后不输出全部图书信息时,输出“****操作已完成”的提示内容。当输入指令有问题使得操作中断,则会提示错误信息。
(3)第三种:特殊输出形式(“查找最贵书籍”专有)。在完成最贵图书的查找之后,输出n+1行,第一行为最贵图书的本数,后n行分别为最贵图书的信息(书号、书名和价格),每本图书信息占一行,书号、书名和价格以空格分隔,其中价格输出保留两位小数。



(1)基于顺序存储结构的图书信息表的创建和输出:定义一个包含图书信息的顺序表,读入相应的图书数据来完成图书信息表的创建;
(2)基于顺序存储结构的图书信息表的最贵图书的查找:图书信息表的创建完成后,根据图书信息表查找价格最高的图书,并输出相关信息;
(3)基于顺序存储结构的图书信息表的新图书的入库:图书信息表的创建完成后,根据指定的待入库的新图书的位置和信息,将新图书插入到图书表中待定的位置上;
(4)基于顺序存储结构的图书信息表的旧图书的出库:图书信息表的创建完成后,根据指定的代出库的位置,将该图书从图书信息表中删除;
(5)基于链式存储结构的图书信息表的创建和输出:定义一个包含图书信息的链表,读入相应的图书数据并使用尾插法的方式来完成图书信息表的创建;
(6)基于链式存储结构的图书信息表排序:图书信息表的创建完成后,将图书按照价格降序排序;
(7)基于链式存储结构的图书信息表的新图书的入库:图书信息表的创建完成后,根据指定的待入库的新图书的位置和信息,将新图书插入到图书表中待定的位置上;
(8)基于链式存储结构的图书信息表的旧图书的出库:图书信息表的创建完成后,根据指定的代出库的位置,将该图书从图书信息表中删除;
- //定义“书本”类型,包含编号(字符串类型)、名称(字符串类型)、价格(double型)三个信息
-
- typedef struct{
-
- char num[30];
-
- char name[60];
-
- double price;
-
- }Book;
-
- //定义信息表链式存储结构,包含书本和指向下一节点的指针域
-
- typedef struct Node{
-
- Book B;
-
- struct Node *next;
-
- }BLinkNode,*BLinkList;
-
- //定义信息表顺序存储结构,包含书本类型指针数组、书本数量和信息表总长度
-
- typedef struct {
-
- Book *B;
-
- int length;
-
- int ListSize;
-
- }BSqList;

- //顺序存储-顺序表的初始化
- Status SQ_InitList(BSqList *L){
- (*L).B=(Book*)malloc(List_Init_Size*sizeof(Book));
- if(!(*L).B) exit(OVERFLOW);
- (*L).length=0;
- (*L).ListSize=List_Init_Size;
- return OK;
- }
- //顺序存储-图书信息表的初始化建立
- Status SQ_CreatBSqList(BSqList *L){
- int i=0;
- Book bt,*newBase;
- scanf("%s %s %lf",bt.num,bt.name,&bt.price);
- while((strcmp(bt.num,"0"))&&(strcmp(bt.name,"0"))&&(bt.price!=0)) {
- if((*L).length>=(*L).ListSize){
- //判断空间是否足够,是否需要分配新空间
- newBase=(Book*)realloc((*L).B,((*L).ListSize+ListIncrease)*sizeof(Book));
- if(!newBase) exit(OVERFLOW);
- (*L).B=newBase;
- (*L).ListSize+=ListIncrease;
- }
- //录入图书信息
- (*L).B[i++]=bt;
- (*L).length++;
- scanf("%s %s %lf",bt.num,bt.name,&bt.price);
- }
- return OK;
- }
- //顺序存储-查找最贵图书
- void SQ_FindExcpensive(BSqList L){
- int i,num=0;
- //max为最贵书的价格,num为最贵书的本数
- int flag[List_Init_Size]={-1}; //标记最贵书在信息表中的位置
- double max;
- max=L.B[0].price; //假设第一本数就是最贵的
- for(i=0;i
- if(max
- num=1;max=L.B[i].price;flag[num-1]=i;
- continue;
- }
- if(max==L.B[i].price){
- num++;flag[num-1]=i;
- continue;
- }
- }
- printf("\n");
- printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");
- printf("查找完成,最贵图书数量:%d\n",num);
- for(i=0;i
- printf("==>%-10s\t%-20s\t%-15.2f\n",L.B[flag[i]].num,L.B[flag[i]].name,L.B[flag[i]].price);
- }
- printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");
- printf("\n");
- }
3.1.4 图书出库
- //顺序存储-图书入库
- Status SQ_Insert(BSqList *L,char c){
- int i,loc;
- Book bt,*newBase;
- if((*L).length>=(*L).ListSize){
- //判断剩余空间是否足够插入新图书,若不够则分配新空间
- newBase=(Book*)realloc((*L).B,((*L).ListSize+ListIncrease)*sizeof(Book));
- if(!newBase) exit(OVERFLOW);
- (*L).B=newBase;
- (*L).ListSize+=ListIncrease;
- }
- printf("输入入库位置:>>");
- scanf("%d",&loc);
- if(loc<1||loc>(*L).length+1) {
- printf("抱歉,入库位置非法!\n");
- return ERROR;
- } //判断入库位置是否合法
- printf("请输入图书书号、书名和价格:>>");
- scanf("%s %s %lf",bt.num,bt.name,&bt.price);
- for(i=(*L).length-1;i>=loc-1;i--){
- (*L).B[i+1]=(*L).B[i];
- }
- (*L).B[loc-1]=bt;
- (*L).length++; //新图书入库
- if(c=='N') printf("\n入库完成!\n");
- return OK;
- }
3.1.5 图书入库
- //顺序存储-输出图书信息表
- void selfPrintf(BLinkList L,int flag){
- BLinkList p;
- p=L->next;
- printf("\n\n");
- printf("================================================\n");
- if(flag==1) printf("==>排序完成!当前图书数量:%d\n",GetLength(L));
- if(flag==2) printf("==>入库完成!当前图书数量:%d\n",GetLength(L));
- if(flag==3) printf("==>出库完成!当前图书数量:%d\n",GetLength(L));
- if(flag==4) printf("==>当前图书数量:%d\n",GetLength(L));
- while(p){
- printf("==>%-10s\t%-10s\t%-15.2f\n",p->B.num,p->B.name,p->B.price);
- p=p->next;
- }
- printf("================================================\n");
- printf("\n\n");
- }
3.1.6 获取图书信息表中图书数量
- //顺序存储-获取图书信息表中图书数量
- int SQ_GetLength(BSqList L){
- return L.length;
- }
3.2 链式存储结构
链式存储结构与顺序存储结构实现的功能一致,区别只在于存储形式。
- //图书信息表的初始化建立:
- //链式存储-图书信息表的初始化建立
- Status creatRareLinkList(BLinkList *l){
- BLinkList head,rare,t;
- Book bt;
- head=(BLinkList)malloc(sizeof(BLinkNode)); //分配头结点
- rare=head;rare->next=NULL; //分配尾指针
- scanf("%s %s %lf",bt.num,bt.name,&bt.price); //读入书本信息
- while((strcmp(bt.num,"0"))&&(strcmp(bt.name,"0"))&&(bt.price!=0))
- //判断是否完成初始化的输入(是否为“0 0”
- {
- t=(BLinkList)malloc(sizeof(BLinkNode));
- t->B=bt;
- t->next=rare->next;
- rare->next=t;
- rare=rare->next; //尾插法分配新空间,将读入的图书信息存储
- scanf("%s %s %lf",bt.num,bt.name,&bt.price);
- }
- (*l)=head;
- return OK;
- }
-
- //按照价格对图书排序:
- //链式存储-按照价格对图书排序
- void Sort(BLinkList *L,char c){
- BLinkList re,p,q,pre;
- pre=*L;
- p=pre->next;
- re=p->next;
- p->next=NULL; //断开首元结点与后续节点的指针联系
- while(re){
- q=re;
- re=re->next; //re向后移动,由q保存当前未排序部分的第一个节点
- pre=*L;
- p=pre->next; //保证循环开始时p始终指向当前已排好顺序的金额最小值
- while(p){
- if(p->B.price
B.price){ - //比较p和q所保存节点的金额大小,并根据结果将q插入排序序列
- q->next=pre->next;
- pre->next=q;
- break;
- }
- if(p->B.price>q->B.price){
- //比较p和q所保存节点的金额大小,并根据结果将q插入排序序列
- if(p->next==NULL||p->next->B.price
B.price){ - q->next=p->next;
- p->next=q;
- break;
- }
- }
- pre=p;
- p=p->next;
- }
- }
- if(c=='N') printf("\n排序完成!\n");
- }
-
- //图书入库;
- //链式存储-图书入库
- Status Insert(BLinkList *L,char c){
- int i,len,loc;
- BLinkList t,p;
- Book bt;
- p=(*L);
- printf("请输入入库位置:>>");
- scanf("%d",&loc);
- printf("请输入图书书号、书名和价格:>>");
- scanf("%s %s %lf",bt.num,bt.name,&bt.price);
- len=GetLength(*L);
- if(loc<1||loc>len+1) {
- printf("抱歉,入库位置非法!\n");
- return ERROR;
- } //判断新图书入库位置是否合法
- for(i=1;i
next; //移动p指针到待入库位置的前驱位置 - t=(BLinkList)malloc(sizeof(BLinkNode));
- t->B=bt;
- t->next=p->next;
- p->next=t; //分配新图书空间并插入
- if(c=='N') printf("\n入库完成!\n");
- return OK;
- }
-
- //图书出库;
- //链式存储-图书出库
- Status Delet(BLinkList *L,char c){
- int i,len,loc;
- BLinkList p,q;
- p=(*L);
- printf("请输入出库位置:>>");
- scanf("%d",&loc);
- len=GetLength(*L);
- if(loc<1||loc>len) {
- printf("抱歉,出库位置非法!\n");
- return ERROR;
- } //判断新图书出库位置是否合法
- for(i=1;i
next; //移动p指针到待出库位置的前驱位置 - q=p->next;
- p->next=q->next;
- free(q); //图书出库
- if(c=='N') printf("\n出库完成!\n");
- return OK;
- }
-
- //输出图书信息表;
- //链式存储-输出图书信息表
- void SQ_SelfPrintf(BSqList L,int flag){
- int i;
- printf("\n");
- printf("================================================\n");
- if(flag==1) printf("==>查找完成!当前图书数量:%d\n",SQ_GetLength(L));
- if(flag==2) printf("==>入库完成!当前图书数量:%d\n",SQ_GetLength(L));
- if(flag==3) printf("==>出库完成!当前图书数量:%d\n",SQ_GetLength(L));
- //相应操作的提示
- if(flag==4) printf("==>当前图书数量:%d\n",SQ_GetLength(L));
- //信息表图书数量
- for(i=0;i
- printf("==>%-10s\t%-20s\t%-15.2f\n",L.B[i].num,L.B[i].name,L.B[i].price);
- }
- printf("================================================\n");
- printf("\n");
- }
-
- //获取图书信息表中图书数量:
- //链式存储-获取图书信息表中图书数量
- int GetLength(BLinkList L){
- BLinkList p;
- int cnt=0; //计数
- p=L->next;
- while(p){
- cnt++;
- p=p->next;
- }
- return cnt;
- }
3.3 主函数
- #include"Self_Function.h"
-
- int main(){
- char OS;
- printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
- printf("+ OSA:链式操作系统 OSB:顺序操作系统 +\n");
- printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
- printf("请输入操作系统(例如:A):>>");
- scanf("%c",&OS);
- printf("\n");
- if(OS=='A'){
- BLinkList BLA;
- int op,flag;
- char YON;
- printf("请输入初始信息,完成图书信息表的初始化:\n");
- creatRareLinkList(&BLA);
- do{
- printf("\n\n");
- op=0;
- flag=-1;
- YON='N';
- printf("**********************************************************************\n");
- printf("* 操作提示: *\n");
- printf("* OP1:按照价格对图书信息表进行排序; *\n");
- printf("* OP2:图书入库; *\n");
- printf("* OP3:图书出库; *\n");
- printf("* OP4:查看信息表; *\n");
- printf("* OP5:退出信息表; *\n");
- printf("* 注:1.2.3.4为操作指令 Y表示操作后查看表 N表示操作后不查看表 *\n");
- printf("**********************************************************************\n");
- printf("请输入操作指令(例如1 Y):>>");
- scanf("%d %c",&op,&YON);
- switch(op){
- case 1: Sort(&BLA,YON);
- if(YON=='Y') { flag=1; selfPrintf(BLA,flag); }
- break;
- case 2: Insert(&BLA,YON);
- if(YON=='Y') { flag=2; selfPrintf(BLA,flag); }
- break;
- case 3: Delet(&BLA,YON);
- if(YON=='Y') { flag=3; selfPrintf(BLA,flag); }
- break;
- case 4: flag=4; selfPrintf(BLA,flag);
- break;
- case 5:break;
- default:printf("输入操作有误,请重新输入!\n");
- }
-
- }while(op!=5);
- printf("已退出图书信息表,欢迎您下次使用!\n");
- }
- else if(OS=='B'){
- BSqList BSL;
- int op,flag;
- char YON;
- SQ_InitList(&BSL);
- printf("请输入初始信息,完成图书信息表的初始化:\n");
- SQ_CreatBSqList(&BSL);
- do{
- printf("\n\n");
- op=0;
- flag=-1;
- YON='N';
- printf("**********************************************************************\n");
- printf("* 操作提示: *\n");
- printf("* OP1:查找最贵图书; *\n");
- printf("* OP2:图书入库; *\n");
- printf("* OP3:图书出库; *\n");
- printf("* OP4:查看信息表; *\n");
- printf("* OP5:退出信息表; *\n");
- printf("* 注:1.2.3.4为操作指令 Y表示操作后查看表 N表示操作后不查看表 *\n");
- printf("**********************************************************************\n");
- printf("请输入操作指令(例如1 Y):>>");
- scanf("%d %c",&op,&YON);
- switch(op){
- case 1: SQ_FindExcpensive(BSL);
- if(YON=='Y') { flag=1; SQ_SelfPrintf(BSL, flag); }
- break;
- case 2: SQ_Insert(&BSL,YON);
- if(YON=='Y') { flag=2; SQ_SelfPrintf(BSL, flag); }
- break;
- case 3: SQ_Delet(&BSL,YON);
- if(YON=='Y') { flag=3; SQ_SelfPrintf(BSL, flag); }
- break;
- case 4: flag=4; SQ_SelfPrintf(BSL,flag);
- break;
- case 5:break;
- default:printf("输入操作有误,请重新输入!\n");
- }
-
- }while(op!=5);
- printf("已退出图书信息表,欢迎您下次使用!\n");
- }
- return 0;
- }
4 调试分析
4.1 调试过程存在的问题
(1)问题:在switch中输入是否查看信息表得判断条件时,程序总会自动先执行while循环输出下一轮的操作提示信息。
解决:将判断条件移到switch之外,直接与操作指令一同输入。
(2)问题:在使用malloc函数分配空间的时候,错误地将其参数void*写成了B*,但是B是顺序表中变量的名称不是数据类型,正确的数据类型应该是Book。
解决:将B改成Book。
(3)问题:i<=(*L).length后的分号写成了中文字符的分号。
解决:将分号改成英文字符的分号。
反思:在编程的时候一定要注意输入法的中英文情况,尽量在同一段时间集中 输入英文,提示、注释等中文字符另找一个时间集中输入,避免输入法切换带 来的问题。
(4)问题:查找最贵图书的输出结果错误。
解决:在for循环中两个if语块内加入continue语句,用于跳出判断。
(5)问题:当最贵的书为第一本书的时候,输出结果为乱码;
解决:乱码的原因在于数组的下标越界问题。将用于控制flag下标的j换成num的相关表达式来进行控制。
反思:在使用数组的过程中一定要注意下标的问题,下标问题不解决使用数组非常危险。下标的使用一定要注意。
4.2 时空复杂度

4.3 经验体会
(1)指针运算符的使用上。“.”和“->”都可以获取成员变量,但是它们的使用对象不同。“.”用于结构体变量获取成员变量;“->”用于结构体指针获取成员变量时使用。此外,当我们使用malloc函数得到结构体,此时的结构体就是结构体指针,使用“->”。
(2)程序编写上。一定要注意前后的关联性,例如在定义顺序表的过程中length错写成lenth,这就会导致后期大量返工使得效率低下。
(3)对数组的使用上。虽然数组一般情况下非常好用,但是数组的下标如果没有控制好便会造成很大的麻烦。因此在使用数组的时候一定要注意下标的问题,一定要在草稿纸上找到合理的下标变量,并且在草稿上进行多轮试验以确保下标的正确性。
(4)C语言是顺序执行,因此要考虑到程序语句的执行顺序。例如两个if语句在一起,但只希望程序执行一个,在if条件都满足的情况下一定要写如break或continue进行对另一个if的跳过。
-
相关阅读:
智慧旅游+数字化景区整体解决方案:文件全文83页,附下载
Redis不再开源,Linux基金会推出下一代开源替代方案!
Refractive index contrast of optical waveguide(光波导的折射率对比度)
【C语言基础】循环
觉非科技数据闭环系列 | BEV感知研发实践
如何设置让vs 在生成程序错误的情况下不去执行上一个可以执行的程序?
es DELETE index 源码分析
stencilJs学习之构建 Drawer 组件
Worthington脱氧核糖核酸及相关研究工具
Stream流 - 聚合操作和遍历操作
-
原文地址:https://blog.csdn.net/weixin_52099756/article/details/140024394