#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define LEN sizeof(struct student)
struct student
{
int num;
char name[10];
float score;
struct student *next;
};
static unsigned inode=1; //定义全局变量,表示链表节点数(长度)
void fill(char c[],int n,char ch); //专门用于初始化字符数组:用c填充整个数组c[],n是数组长度
void del(struct student *ph,int n); //删除链表对象,n是用户指定要删除的序号
void insert(struct student *ph,int n); //插入链表节点,在ph的第n个节点之后插入,也可以在表头插入
void output(struct student *ph); //输出函数
struct student *input(void); //输入函数,函数会新申请一个空间,完成数据输入,返回空间首地址
void clearline(int n);
int main() //尝试动态链表的创建与删除
{
struct student *head,*ps,*pa,*pb; //head是头部,ps用来特别定位到头部,pa用来访问和遍历链表,pb用来备份节点地址
int u; //u用来读取用户指定要删除的序号
char flag='y'; //flag旗标用来记录用户选择
head=ps=pa=(struct student *)malloc(LEN); //所有指针初始化到链表头部
fill(pa->name,10,'\0'); //字符数组初始化
printf("请输入学生信息,格式如下,字段之间可以以TAB跳格:\n");
printf("学号\t姓名\t成绩\n");
while(flag!='n') {
scanf("%d %s %f",&pa->num,pa->name,&pa->score);
printf("Press any key input data continue,otherwise press n quit:");
flag=getche();
if(flag!='n') {
clearline(60);
pa->next=(struct student *)malloc(LEN);
pa=pa->next;
fill(pa->name,10,'\0');
inode++; //记住链表的节点数(长度)
}
}
pa->next=NULL;
output(ps);
//删除操作开始
printf("你想删除其中的哪一个学生?\n");
printf("请输入你要删除的信息列表序号:");
scanf("%d",&u);
if(u>inode) {
printf("输入错误!\n");
exit(1);
}
if(u==1) { //第一个节点的删除和其他不同
pb=head; //备份链表的原始头地址
ps=head->next; //备份下一个节点起始地址
free(pb); //释放链表的原始头节点
head=pb=pa=ps; //将新的链表头地址赋给pb和head以便下次调用
}
else
del(ps,u);
//删除操作结束
output(ps);
//插入操作开始
printf("你要在哪条记录之后插入记录?(要在开头插入记录,请输入0):");
scanf("%d",&u);
if(u>inode) {
printf("输入错误!\n");
exit(1);
}
if(u==0) {
pb=head; //记住原链表头地址
head=ps=pa=input(); //所有链表头部新地址确定
pa->next=pb; //原链表头部链接到新链表头部后面
inode++;
}
else
insert(ps,u);
//插入操作结束
output(ps);
return 0;
}
void fill(char c[],int n,char ch) //专门用于初始化字符数组:用c填充整个数组c[],n是数组长度
{
int i;
for(i=0;i<n;i++)
*(c+i)=ch;
}
void del(struct student *ph,int n)
{
int i;
struct student *pb,*pf;
pb=pf=ph; //所有指针初始化到链表头部
for(i=1;i<=n-2;i++) { //寻找目标节点的上一个节点
ph=ph->next;
}
if(n==inode) { //如果是最后一个节点,删除情况与其他不同
pb=ph->next;
ph->next=NULL;
free(pb);
}
else {
pb=ph->next; //备份目标节点地址
ph->next=(ph->next)->next; //将目标节点的下一个节点与上一个节点连接起来
free(pb); //释放目标节点的内存占用
}
inode--;
}
void insert(struct student *ph,int n) //需要链表首地址和插入点
{
int i;
struct student *pa,*pb,*p_new,*ps;
ps=pa=ph;
p_new=(struct student *)malloc(LEN);
fill(p_new->name,10,'\0'); //字符数组初始化
printf("请输入要插入的学生信息:\n");
printf("学号\t姓名\t成绩\n");
scanf("%d %s %f",&p_new->num,p_new->name,&p_new->score);
for(i=1;i
pa=pa->next;
pb=pa->next; //记住下一个节点地址
pa->next=p_new; //将新节点链接到插入点下面
p_new->next=pb; //将下一个节点链接到新节点下面
inode++;
}
void output(struct student *ph)
{
int i;
struct student *pa;
printf("\n*****输出信息列表*****\n");
printf("序号\t 学号\t姓名\t\t成绩\n");
for((i=1,pa=ph);pa->next!=NULL;(i++,pa=pa->next))
printf("-\t]\t%-8s\t%.2f\n",i,pa->num,pa->name,pa->score);
printf("-\t]\t%-8s\t%.2f\n",i,pa->num,pa->name,pa->score);
printf("一共有%d个对象\n",inode);
}
struct student *input(void)
{
struct student *pa;
pa=(struct student *)malloc(LEN);
printf("请输入要插入的学生信息:\n");
printf("学号\t姓名\t成绩\n");
scanf("%d %s %f",&pa->num,pa->name,&pa->score);
return pa;
}
void clearline(int n)
{
int space;
for((printf("\r"),space=0);(printf(" "),space<n);space++);
printf("\r"); //清除完屏幕提示信息光标回以行首开始下一次输入
}