题目 题目 题目
综合任务:使用链表编程实现图书信息(书名、单价)管理
功 能:
1.图书信息录入:从键盘输入n(n<10)本书的书名和单价用于构造图书链表,然后输出所有图书信息;
2.图书信息排序:按照单价从高到低的顺序进行排序后输出图书信息;
3.图书信息插入:实现新增图书信息(图书信息插入链表后,单价排序保持降序)并输出图书信息;
4.图书信息查找:实现图书按名查找并输出结果;
5.图书信息删除:实现按书名删除图书信息后输出图书信息;
6.图书信息修改:实现按书名修改图书单价后输出图书信息;
7.图书信息统计:实现统计图书数量及图书总价并输出结果;
8.图书信息浏览。
要 求:
- 使用单向链表作为图书信息的存储结构;
- 编写函数实现各模块功能;
- 在主函数中设计一个菜单,选择相关功能后按要求输入数据并调用各函数实现;
做题流程 做题流程 做题流程
- 流程:首先在main函数内定义一个head头指针,通过一个菜单函数输出菜单;根据菜单,用户输入数字来操作图书信息;用switch,case函数来匹配各个数字对应的功能,功能则由函数实现。
- 菜单函数:照着菜单的样子设计一下即可。设计如下:
void get_a_menu()
{
printf(" ********Menu*******\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");
printf(" *****9-退出系统*****\n");
}
- 信息录入函数:需要的参数为链表的头指针,返回值也为链表的头指针。循环增加结点,最后输出内容。
BOOK *input(BOOK *head)
{
BOOK *tail=head,*p;
int flag; char temp[30];
printf("\n输入‘1’开始录入图书信息,输入其他退出:");
scanf("%d",&flag);getchar();
while(flag==1)
{
p=(BOOK *)malloc(sizeof(BOOK));
printf("\n输入书名:");gets(temp);
p->book_name=(char *)malloc(strlen(temp)+1);
strcpy(p->book_name,temp);
printf("\n输入价格:");scanf("%lf",&p->book_price);
p->next=NULL;
if(head==NULL)
{
head=p;
tail=p;
}
else
{
tail->next=p;
tail=p;
}
printf("\n输入‘1’继续录入图书信息,输入其他结束输入:");
scanf("%d",&flag);getchar();
}
if(head!=NULL)
{
p=head; printf("\n输入完成,录入图书信息如下:\n");
printf("书名\t价格\n");
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
return head;
}
- 信息排序函数:参数和返回值均为头指针。题目要求按照图书价格高低降序排列。排序的思路是:从第一个结点开始,找到图书价格最高的结点,与第一个结点交换数据,;然后从第二个结点开始,找到剩余结点的最大值,与第二个结点交换数据,依次进行。因此设计时需要用到嵌套的两层循环,并且交换时使用了指针(如果不使用指针,交换时则定位不到是和哪一个结点交换的,有点麻烦)。最后输出排序完成后的数据。设计的代码如下:
BOOK *sort(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法排序!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
while(p!=NULL)
{
double *max=&p->book_price; char **max_name=&p->book_name;
BOOK *q=p;
while(q->next!=NULL)
{
if(*max<q->next->book_price)
{
max=&q->next->book_price;
max_name=&q->next->book_name;
}
q=q->next;
}
double temp;temp=p->book_price; char *temp_name=p->book_name;
p->book_price=*max; *max=temp; p->book_name=*max_name;*max_name=temp_name;
p=p->next;
}
printf("\n排序完成,排序结果如下:\n");
printf("书名\t价格\n");p=head;
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
return head;
}
}
- 信息插入函数:形参和返回值也都是head指针。插入的设计:先声明一个结构体指针,申请空间,初始化成员数据,然后令p->next=head,即使p指向head,从头部前插入,最后head=p,返回head。(可以通过循环一次性插入多个的,这里只插入一个)。题目要求插入后保持降序,在最后再调用一下排序函数即可。设计的代码如下:
BOOK *insert(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法插入!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p; char temp[30];
p=(BOOK *)malloc(sizeof(BOOK));
getchar();printf("\n输入插入图书的书名:");gets(temp);
p->book_name=(char *)malloc(strlen(temp)+1);
strcpy(p->book_name,temp);
printf("\n输入插入图书的价格:");scanf("%lf",&p->book_price);
p->next=head;
head=p; printf("插入完成。\n");
}
sort(head);
return head;
}
- 信息查找函数:思想比较简单,先通过用户输入初始化一个字符数组key,遍历链表,如果key与链表某结点的书名成员相等,则输出该节点的信息。需要注意的使的是,判断两个字符指针是否相等的方法不能是:key==p->book_name,可以完成判断的有strcmp函数,若二者相等,则返回0。参数和返回值也均为head头指针。该函数的设计如下:
BOOK *search(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法查找!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
printf("\n请输入你想查找的书的书名:");
char key[30];getchar();gets(key);
while(p!=NULL)
{
if(strcmp(key,p->book_name)==0)
{
printf("查找成功,信息如下:\n");
printf("书名\t价格\n");
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
break;
}
p=p->next;
}
if(p==NULL)
{
printf("\n查找失败,没有录入此书信息。\n");
}
}
return head;
}
- 信息删除函数:思路:从头指针开始,通过循环找到要删除的结点,与查找相同;然后又通过循环找的删除结点p的上一个结点q,令q->next=p->next,这样删除结点就脱离链表了。函数设计如下:
BOOK *remove_book(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法删除!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
printf("\n请输入你想删除的书的书名:");
char key[30];getchar();gets(key);
while(p!=NULL)
{
if(strcmp(key,p->book_name)==0)
{
BOOK *q=head;
while(q!=NULL)
{
if(q->next==p)
{
q->next=p->next;
break;
}
q=q->next;
}
break;
}
p=p->next;
}
if(p==NULL)
{
printf("\n删除失败,没有录入此书信息。\n");
}
else
{
printf("\n删除完成,现图书信息如下:\n");
printf("书名\t价格\n");p=head;
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
}
return head;
}
- 信息修改函数:同搜索函数一样,循环找到要修改的结点;然后进行修改即可。最后输出一下修改后的信息即可。设计的函数如下:
BOOK *modify(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法删除!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
printf("\n请输入你想修改的书的书名:");
char key[30];getchar();gets(key);
while(p!=NULL)
{
if(strcmp(key,p->book_name)==0)
{
printf("\n输入该书修改后的单价:");
scanf("%lf",&p->book_price);
break;
}
p=p->next;
}
if(p==NULL)
{
printf("\n修改失败,没有录入此书信息。\n");
}
else
{
printf("\n修改完成,现图书信息如下:\n");
printf("书名\t价格\n");p=head;
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
}
return head;
}
- 信息统计函数:题目要求统计出图书的总本数,和总价格。只需要先声明两个变量,然后遍历链表,每次都加上本数和价格即可。不需要返回值。函数设计如下:
void count(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法统计!\n 输入‘1’进行图书信息录入。\n");
}
else
{
int number=0;double price=0;
BOOK *p=head;
while(p!=NULL)
{
number++;
price+=p->book_price;
p=p->next;
}
printf("\n经统计,录入图书共有%d本,共%.1f元。\n",number,price);
}
}
- 信息浏览函数:这个前面其实使用了很多次。只需遍历列表,输出相应的数据即可。设计的函数如下:
void browse(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法浏览!\n 输入‘1’进行图书信息录入。\n");
}
else
{
printf("图书信息如下:\n");
BOOK *p=head;
printf("书名\t价格\n");
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
}
最后答案 最后答案 最后答案
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct book_inf
{
char *book_name;
double book_price;
struct book_inf *next;
};
typedef struct book_inf BOOK;
void get_a_menu();
BOOK *input(BOOK *);
BOOK *sort(BOOK *);
BOOK *insert(BOOK *);
BOOK *search(BOOK *);
BOOK *remove_book(BOOK *);
BOOK *modify(BOOK *);
void count(BOOK *);
void browse(BOOK *);
int main()
{
BOOK *head=NULL;
get_a_menu();
while(1)
{
int n;
printf("\n输入相应序号操作图书信息:");
scanf("%d",&n);
switch(n)
{
case 1:head=input(head);break;
case 2:head=sort(head);break;
case 3:head=insert(head);break;
case 4:head=search(head);break;
case 5:head=remove_book(head);break;
case 6:head=modify(head); break;
case 7:count(head);break;
case 8:browse(head);break;
case 9:exit(0);break;
}
}
return 0;
}
void get_a_menu()
{
printf(" ********Menu*******\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");
printf(" *****9-退出系统*****\n");
}
BOOK *input(BOOK *head)
{
BOOK *tail=head,*p;
int flag; char temp[30];
printf("\n输入‘1’开始录入图书信息,输入其他退出:");
scanf("%d",&flag);getchar();
while(flag==1)
{
p=(BOOK *)malloc(sizeof(BOOK));
printf("\n输入书名:");gets(temp);
p->book_name=(char *)malloc(strlen(temp)+1);
strcpy(p->book_name,temp);
printf("\n输入价格:");scanf("%lf",&p->book_price);
p->next=NULL;
if(head==NULL)
{
head=p;
tail=p;
}
else
{
tail->next=p;
tail=p;
}
printf("\n输入‘1’继续录入图书信息,输入其他结束输入:");
scanf("%d",&flag);getchar();
}
if(head!=NULL)
{
p=head; printf("\n输入完成,录入图书信息如下:\n");
printf("书名\t价格\n");
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
return head;
}
BOOK *sort(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法排序!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
while(p!=NULL)
{
double *max=&p->book_price; char **max_name=&p->book_name;
BOOK *q=p;
while(q->next!=NULL)
{
if(*max<q->next->book_price)
{
max=&q->next->book_price;
max_name=&q->next->book_name;
}
q=q->next;
}
double temp;temp=p->book_price; char *temp_name=p->book_name;
p->book_price=*max; *max=temp; p->book_name=*max_name;*max_name=temp_name;
p=p->next;
}
printf("\n排序完成,排序结果如下:\n");
printf("书名\t价格\n");p=head;
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
return head;
}
}
BOOK *insert(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法插入!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p; char temp[30];
p=(BOOK *)malloc(sizeof(BOOK));
getchar();printf("\n输入插入图书的书名:");gets(temp);
p->book_name=(char *)malloc(strlen(temp)+1);
strcpy(p->book_name,temp);
printf("\n输入插入图书的价格:");scanf("%lf",&p->book_price);
p->next=head;
head=p; printf("插入完成。\n");
}
sort(head);
return head;
}
BOOK *search(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法查找!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
printf("\n请输入你想查找的书的书名:");
char key[30];getchar();gets(key);
while(p!=NULL)
{
if(strcmp(key,p->book_name)==0)
{
printf("查找成功,信息如下:\n");
printf("书名\t价格\n");
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
break;
}
p=p->next;
}
if(p==NULL)
{
printf("\n查找失败,没有录入此书信息。\n");
}
}
return head;
}
BOOK *remove_book(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法删除!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
printf("\n请输入你想删除的书的书名:");
char key[30];getchar();gets(key);
while(p!=NULL)
{
if(strcmp(key,p->book_name)==0)
{
BOOK *q=head;
while(q!=NULL)
{
if(q->next==p)
{
q->next=p->next;
break;
}
q=q->next;
}
break;
}
p=p->next;
}
if(p==NULL)
{
printf("\n删除失败,没有录入此书信息。\n");
}
else
{
printf("\n删除完成,现图书信息如下:\n");
printf("书名\t价格\n");p=head;
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
}
return head;
}
BOOK *modify(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法删除!\n 输入‘1’进行图书信息录入。\n");
}
else
{
BOOK *p=head;
printf("\n请输入你想修改的书的书名:");
char key[30];getchar();gets(key);
while(p!=NULL)
{
if(strcmp(key,p->book_name)==0)
{
printf("\n输入该书修改后的单价:");
scanf("%lf",&p->book_price);
break;
}
p=p->next;
}
if(p==NULL)
{
printf("\n修改失败,没有录入此书信息。\n");
}
else
{
printf("\n修改完成,现图书信息如下:\n");
printf("书名\t价格\n");p=head;
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
}
return head;
}
void count(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法统计!\n 输入‘1’进行图书信息录入。\n");
}
else
{
int number=0;double price=0;
BOOK *p=head;
while(p!=NULL)
{
number++;
price+=p->book_price;
p=p->next;
}
printf("\n经统计,录入图书共有%d本,共%.1f元。\n",number,price);
}
}
void browse(BOOK *head)
{
if(head==NULL)
{
printf("你还未录入图书信息,无法浏览!\n 输入‘1’进行图书信息录入。\n");
}
else
{
printf("图书信息如下:\n");
BOOK *p=head;
printf("书名\t价格\n");
while(p!=NULL)
{
printf("\n%s\t%.1f\n",p->book_name,p->book_price);
p=p->next;
}
}
}
小结 小结 小结
- 链表根据其某一成员的大小排序,可以使用指针
- 排序进行替换字符串时用到二重指针
- 链表逐一查找某一字符串数据,不能用 = = 判断,应该用strcmp函数判断。