前提:最近看到蛮多链表的课设,然后发现其实都差不多,图书管理系统,学生信息等,然后把去年的学生信息管理系统改了改,改成图书管理系统
效果如下:
①界面
②输入,不一定5个,最后####结尾就好,这里本人并不想改
③打印,这里是乱序的,然后有分类情况
**④排序,**我根据书名排序的,如果要实现名字相同,时间早的在前,再加一句if判断重新交换赋值即可,这里就不赘述了
**讲一下分类的算法(敲重点):**我在结构体中设置了一个order变量,他表示这个节点的出版社是否相同,相同为0,不同为1。然后我们通过循环,将第一个与后面的节点比较,找有没有相同的出版社,有的话,那个q->order就要被置0,最后你在判断这个p->order==1?即可,因为是顺序遍历,所以他保证最开头的那些都是1,这样就完成了分类,虽然排序一次也可以
算法:
void calu(pNode pHead)
{
printf("\n");
int sum=0;
pNode p=pHead->next;
// pNode q=p->next;
while(p!=NULL)
{
int cnt=0;
pNode q=p->next;
while(q!=NULL)
{
if(!strcmp(p->club,q->club)&&p->order==1)
{
cnt+=q->num;
q->order=0;//&&p->order==1
}
q=q->next;
}
if(p->order==1)
{
printf("%s的藏书量:%d本\n",p->club,cnt+p->num);
}
// printf("%s的藏书量:%d本\n",p->club,cnt);
sum+=p->num;
p=p->next;
}
printf("总藏书量:%d本\n",sum);
}
排序,遍历(两重)有个要注意的是,最后内嵌循环的那个q,q需要最后重新指向p->next;不然q遍历一次之后就是NULL,这个容易忘记,我写在这里提醒自己
同样的因为这个order,插入记得给他赋值1,其他问题不大
其他的增删改查都差不多,这里的效果我就不放了,我直接上代码好了
/*头文件*/
#include <stdio.h>
#include<dos.h> /*dos.h包含了与dos相关的结构、flags等数据,还有dos相关的低级IO函数、
内存访问函数、中断访问函数等等。 */
#include<stdlib.h> /*其它说明*/
#include<string.h> /*字符串函数*/
#include<ctype.h> /*字符操作函数*/
#define N 5
int length=3;
struct Node /*定义结构体数组用于缓存数据*/
{
char name[20];//书名
char write[20];//作者
char club[20];//出版社
char no[20];// ISBM
char time[20];//出版时间
float price;//价格
char kind[20];//leibie
int num;//数量
int order;//标记计数情况
struct Node *next;
};
typedef struct Node*pNode;
/*函数原型*/
int menu_select(); /*菜单函数*/
pNode create(); /*创建链表*/
void print(pNode pHead); /* 显示全部记录*/
void search(pNode pHead); /*查找记录*/
void dele(pNode pHead); /*删除记录*/
void sort(pNode pHead); /*排序*/
void calu(pNode pHead); /*计数*/
/*主函数界面*/
main()
{
for(;;) /*循环无限次*/
{
pNode head;
switch(menu_select())
{
case 1:
head=create();
break;/*创建图书库*/
case 2:
print(head);
break;/*显示图书信息*/
case 3:
search(head);
break;/*查询*/
case 4:
dele(head);
print(head);//打印每次的情况
break;/*删除*/
case 5:
sort(head);
print(head);//打印每次的情况
break;/*排序*/
case 6:
insert(head);//数据插入
print(head);//打印每次的情况
break; /*&new表示返回地址*/
case 7:exit(0); /*如菜单返回值为7则程序结束*/
}
}
}
/*菜单选择函数*/
menu_select()
{
system("color f2");//背景色白色,字体绿色
int n;
printf("按任一键进入主菜单......"); /*按任一键进入主菜单*/
getch(); /*从键盘读取一个字符,但不显示于屏幕*/
system("cls"); /*清屏*/
printf("********************************************************************************\n");
printf("\t\t Welcome to\n");
printf("\n\t\t 图书馆里系统\n");
printf("*************************************MENU***************************************\n");
printf("\t\t\t1. 输入图书信息\n"); /*输入图书信息*/
printf("\t\t\t2. 显示图书信息\n"); /*显示图书信息*/
printf("\t\t\t3. 查询书籍信息\n"); /*查询书籍信息*/
printf("\t\t\t4. 删除图书信息\n"); /*删除图书信息*/
printf("\t\t\t5. 排序图书信息\n"); /*排序图书信息*/
printf("\t\t\t6. 插入图书信息\n"); /*插入图书信息*/
printf("\t\t\t7. 退出\n"); /*退出*/
printf("********************************************************************************\n");
do
{
printf("\n\t\t\t输入你的操作序号(1~7):");
scanf("%d",&n);
}while(n<1||n>9); /*如果选择项不在1~7之间则重输*/
return(n); /*返回选择项,主函数根据该数调用相应的函数*/
}
/*
/*输入函数*/
/* 显示全部记录函数*/
void print(pNode pHead)
{
int i=0; /* 统计记录条数*/
int sum=0;//总图书量
system("cls");
printf("\n************************************图书信息******************************************\n");
printf("----------------------------------------------------------------------------------------\n");
printf("| 序号 | 书名 | 作者 | 出版社 | ISBN | 出版时间 | 价格(元)| 类别 | 数量 |\n");
printf("----------------------------------------------------------------------------------------\n");
pNode p=pHead->next;//跳过头节点,头节点为空 ,否则报错
pNode q=p->next;
while(p!=NULL)
{
//pNode p=pHead->next;//跳过头节点,头节点为空 ,否则报错
printf("| %3d | %4s | %-4s | %3s | %3s | %3s | %3g | %4s | %-5d|\n",
i, p->name,p->write,p->club,p->no,p->time,p->price,p->kind,p->num);
i++;
p=p->next;
}
calu(pHead);
printf("-----------------------------------------------------------------------------------------\n");
printf("**************************************END************************************************\n");
}
void calu(pNode pHead)
{
printf("\n");
int sum=0;
pNode p=pHead->next;
// pNode q=p->next;
while(p!=NULL)
{
int cnt=0;
pNode q=p->next;
while(q!=NULL)
{
if(!strcmp(p->club,q->club)&&p->order==1)
{
cnt+=q->num;
q->order=0;//&&p->order==1
}
q=q->next;
}
if(p->order==1)
{
printf("%s的藏书量:%d本\n",p->club,cnt+p->num);
}
// printf("%s的藏书量:%d本\n",p->club,cnt);
sum+=p->num;
p=p->next;
}
printf("总藏书量:%d本\n",sum);
}
void insert(pNode pHead)//数据插入,前插
{
char name[20],write[20],club[20],no[20],time[20],kind[20];
float price;
int num;
int pos;
printf("| 位置 | 书名 | 作者 | 出版社 | ISBN | 出版时间 | 价格 | 类别 | 数量 |\n");
scanf("%d",&pos);
scanf("%s",name);//书名
scanf("%s",write);//作者
scanf("%s",club);//出版社
scanf("%s",no);//ISBN
scanf("%s",time);//出版时间
scanf("%f",&price);//价格
scanf("%s",kind);//类别
scanf("%d",&num);//数量
int i=0;
pNode p=pHead;
while((p!=NULL)&&(i<pos))//查找位置,即他的前一位置
{
p=p->next;
i++;
}
if(p==NULL||i>pos)//插入位置非法或者节点创立失败
{
printf("插入位置非法或者节点创立失败,数据从0开始编号 ");
exit(1);
}
pNode new_node=(pNode)malloc(sizeof(struct Node));//创立一个节点
//数据插入
new_node->num=num;
new_node->price=price;
new_node->order=1;
strcpy(new_node->name,name);
strcpy(new_node->write,write);
strcpy(new_node->club,club);
strcpy(new_node->no,no);
strcpy(new_node->time,time);
strcpy(new_node->kind,kind);
//让该节点指向p节点下一个节点,p节点为该节点下一指向位置
new_node->next=p->next;
p->next=new_node;
}
void sort(pNode pHead)//排序 从小到大
{
int i,j;
pNode p,q;
p=pHead->next;q=p->next;
while(p!=NULL)// 交换思路和数组交换一致,定义两个节点,P一定要指向头节点的下一个节点,因为头节点为空
{
while(q!=NULL)//q节点只需指向p节点下一个节点即可,毕竟j=i+1,所以q在p下一个节点
{
if(strcmp(p->name,q->name)<0)//根据书名查找
{
int temp;temp=p->num;p->num=q->num;q->num=temp;
float t;t=p->price;p->price=q->price;q->price=t;
char c[20];
strcpy(c,p->name);strcpy(p->name,q->name);strcpy(q->name,c);
strcpy(c,p->write);strcpy(p->write,q->write);strcpy(q->write,c);
strcpy(c,p->club);strcpy(p->club,q->club);strcpy(q->club,c);
strcpy(c,p->no);strcpy(p->no,q->no);strcpy(q->no,c);
strcpy(c,p->time);strcpy(p->time,q->time);strcpy(q->time,c);
strcpy(c,p->kind);strcpy(p->kind,q->kind);strcpy(q->kind,c);
}
q=q->next;
}
q=p->next;
p=p->next;
}
}
void dele(pNode head)//数据删除
{
char ID[20];
printf("请输入你要删除的书的ID: \n");
scanf("%s",ID);
if(head->next==NULL)
{
printf("空链表,长度无效");//头节点下一节点,为空,则失败,因为没有数据,也是保证数据长度有效
exit(1);
}
pNode p=head;//头节点赋值
head=head->next;//头节点指向下一节点
while(head!=NULL)//循环查找
{
if(!strcmp(head->no,ID))//ID如果相等则让p指向head的下一个节点,同时释放head,因为head永远指向p的下两个节点
{
p->next=head->next;
free(head);//释放野指针
}
head=head->next;//两个节点不断指向下一个节点查找
p=p->next;
}
}
void search(pNode head)//数据查找,根据书名查找
{
char Name[20];
printf("请输入你要查找的书名: \n");
scanf("%s",Name);
int flag=0;
if(head->next==NULL)
{
printf("空链表,长度无效");
exit(1);
}
pNode p=head->next;
while(p!=NULL)//顺序查找
{
if(!strcmp(p->name,Name))
{
printf("| 书名 | 作者 | 出版社 | ISBN | 出版时间 | 价格 | 类别 | 数量 |\n");
printf("-------------------------------------------------------------------------------\n");
printf("| %4s | %-4s | %3s | %3s | %3s | %3g | %4s | %-5d|\n",
p->name,p->write,p->club,p->no,p->time,p->price,p->kind,p->num);
//printf("| %3d | %4s | %-4s | %3s | %3s | %3s | %3g | %4s | %-5d|\n",p->name,p->write,p->club,p->no,p->time,p->price,p->kind,p->num);
flag=1;
}
p=p->next;
}
if(!flag)
{
printf("记录中未有此书\n");
}
}
pNode create()//信息读入和链表创建
{
//人数就三个,所以长度为三
printf("请输入书籍信息,输入5个即可\n| 书名 | 作者 | 出版社 | ISBN | 出版时间 | 价格(元)| 类别 | 数量 |\n");
pNode pHead=(pNode)malloc(sizeof(struct Node));//建立头节点
int i;
if(pHead==NULL)//头节点创立是否成功
{
printf("创建失败");
exit(1);//检验是否成功 ,失败就退出
}
else
{
pNode pTail=pHead;//尾节点
pHead->next=NULL; //头节点指向空
while(1)//循环创建节点
{
pNode p=(pNode)malloc(sizeof(struct Node));//创建节点,让他指向下一个
if(p==NULL)
{
printf("创建失败");
exit(1);//检验是否成功
}
else
{
scanf("%s",p->name);//书名
if(!strcmp(p->name,"####"))
{
break;
}
scanf("%s",p->write);//作者
scanf("%s",p->club);//出版社
scanf("%s",p->no);//ISBN
scanf("%s",p->time);//出版时间
scanf("%f",&p->price);//价格
scanf("%s",p->kind);//类别
scanf("%d",&p->num);//数量
p->order=1;
pTail->next=p;//不断 创建节点,最后总指向空
p->next=NULL;
pTail=p;
}
}
}
return pHead;
}
/*
相关输入
汇编语言 王爽 新华社 1111 2013.1.1 50 科技 1
数据结构 陈玉 风华社 2020 2010.1.3 40 编程 2
悲惨世界 雨果 凤凰社 2391 2000.1.4 50 人文 3
天才世界 译名 新华社 2032 2012.3.5 50 图书 4
盗墓笔记 三叔 凤凰社 2021 2009.5.3 60 玄幻 5
终极笔记 三叔 凤凰社 2022 2010.5.4 50 玄幻 4
*/
以上书籍名字等信息写错,只是测试案例,互喷