题目描述:
现在想将学生绩点组成一个链表。链表结点内容包括学生姓名,学号,绩点
输入是一组学生的姓名、学号和绩点,以链表形式存储。
删除绩点小于平均绩点的学生结点,成为一个新链表。
后按照输入的顺序,依序输出新链表的学生信息。
平均绩点是输入的所有学生绩点取算术平均值。
输入描述: 输入包括若干行。 每行是一个学生的姓名、学号和绩点,以空格隔开。 最后一行是*.
输出描述: 输出包括学生姓名。 每个学生姓名一行。
样例输入:
sddv 005 3.6
jjjbjb 1465 1.5
jdsf 0156 2.8
scc 003 1.5
wzwa 008 4.2
*
样例输出:
sddv
jdsf
wzwa
提示:本题需要创建自定义链表创建函数creat(),链表删除函数delete()。我认为在链表的使用过程中遇到最多的问题应该是“
信号: SIGSEGV (Segmentation fault)
”这个信号,代表程序包括非法内存访问,数组越界,指针漂移,调用系统禁用的系统函数等。可想而知当遍历链表时需要用到循环,当循环走到链表倒数第二个节点时,p=p->next会直接使p=NULL形成空指针,此时你再想用p->score这样的语句去取出某些成员的值,势必出现上述信号,写代码过程中要注意这点。
代码实现:(编译环境:CLion 2022.2.4)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int n;
struct student
{
char name[100];
char num[100];
double score;
struct student *next;
};
struct student *creat()
{
struct student *head=NULL,*p1,*p2;
char end[10];
strcpy(end,"*");
int i=0;
do
{
p1=(struct student *)malloc(sizeof(struct student));
scanf("%s",p1->name);
if(*(p1->name)!=*end)
{
scanf("%s", p1->num);
scanf("%lf", &p1->score);
}
else
{
break;
}
if(i==0)
{
p2=head=p1;
}
else
{
p2->next=p1;
p1->next=NULL;
p2=p1;
}
i++;
n=i;
}while(p1);
return(head);
}
void delete(struct student *head,int i)
{
struct student *p=head,*q;
int j=0;
while(p&&j<i-1)
{
p=p->next;
j++;
}
q=p->next;
p->next=q->next;
free(q);
}
int main()
{
struct student *head,*p;
head=creat();
p=head;
double sum=0,average;
int i=0;
do
{
sum=sum+p->score;
p=p->next;
i++;
}while(i<n);
p=head;
average=sum/n;
int k=0;
for(i=0;i<n;i++)
{
if(p==NULL)
{
break;
}
if(p->score<average)
{
delete(head,k);
i=0;
p=head;
k=0;
}
p=p->next;
k++;
}
p=head;
for(i=0;i<n;i++)
{
if(p!=NULL) {
printf("%s\n", p->name);
p=p->next;
}
}
return 0;
}
注意:至少对于CLion来说,如果你直接输入数据运行的话,系统是不会给出
“信号: SIGSEGV (Segmentation fault)”这个信号的,只是很有可能代码正常退出然而什么也不会输出,此时调试是至关重要的了,调试过程中可以看到每一步的数据动态变化,并且会清楚指明上述信号发生在哪一句,帮你更快而精确的找到bug。