关于C语言链表的问题

问题遇到的现象和发生背景

输入如下十个学生的成绩数据,每个学生信息包括 学号 、姓名 、考试成绩 ,实验成绩。同时计算每个学生的总评成绩( =考试成绩60% + 实验成绩40%)并保存至每个结构体的totalmark。输入格式如下:
71250 李霞 95 82
69753 李友友 88 86
12254 东方亮 87 88
61256 张男 73 85
30258 孙杰 25 88
11260 柯以乐 82 76
33262 谢涛 91 85
29263 叶林 80 75
22483 陈翔 80 76
71525 王子 71 88

编写函数实现建立链表:struct student * create( int n), n是学生人数。函数中输入n个学生的信息,同时计算总评成绩,按照总评成绩从高到低的方式形成有序链表。返回链表头指针。

问题相关代码,请勿粘贴截图
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define len sizeof(stu)
typedef struct student
{
    float stunum;          
    char name[20];    
      float examscore;    
      float labscore;
      float totalmark;    
    struct student * next;  

} stu ;

//定义全局变量.m,t,s[20]用于交换变量 
int i=0;
float t=0,m=0;
char s[20];
stu *p; 

stu *create(int n)//n是学生人数
{    
    stu *head,*p1,*p2;
    printf("依次输入学生 学号 姓名 考试成绩 实验成绩\n");
    
    for(i=0;i<n;i++)//建立链表 
    {
        p1=malloc(len);
        
        if(i=0)
        {
            head=p2=p1;//开始head p1 p2都指向新节点 
            scanf("%f %s %f %f",&p1->stunum,&p1->name,&p1->examscore,&p1->labscore);
            p1->next=NULL;
        }
        else
        {
            p2->next=p1;
            p2=p1;//先将末尾节点指向新节点,在将p2指向新节点 
            scanf("%f %s %f %f",&p1->stunum,&p1->name,&p1->examscore,&p1->labscore);
            p1->next=NULL;
        } 
    }
    

    
    
    
    
    for(i=0;i<n;i++)//计算学生总评成绩 
    {
        p->totalmark=0.6*p->examscore+0.4*p->labscore; 
    }


    for(i=0;i<n;i++)//按成绩对学生进行排序
    {
        for(p=head,p=p->next,p1=head;p1;p=p->next,p1=p1->next)
        {
            if(p1->totalmark<p->totalmark)
            {
                m=p->totalmark;p->totalmark=p1->totalmark;p1->totalmark=m;
                t=p->stunum;p->stunum=p1->stunum;p1->stunum=t;
                m=p->examscore;p->examscore=p1->examscore;p1->examscore=m;
                m=p->labscore;p->labscore=p1->labscore;p1->labscore=m;
                strcpy(s,p->name);strcpy(p->name,p1->name);strcpy(p1->name,s);//用到#include<string.h> 
            }
        }
    }  
    
    return head; //返回头指针 
}



int main()
{
    int n;
    printf("输入学生人数:\n");
    scanf("%d",&n);//输入学生人数
    
    p=create(n); //p 赋值链表头指针 
    
    for(i=0;i<n;i++)
    {
        printf("stunum:%f name:%s examscore:%f labscore:%f totalmark:%f\n",p->stunum,p->name,p->examscore,p->labscore,p->totalmark);
    }
    
    
    return 0;
    
    
}
运行结果及报错内容

编译无错误 但不能正常运行:

输入学生人数:
10
依次输入学生 学号 姓名 考试成绩 实验成绩


Process exited after 3.497 seconds with return value 3221225477
请按任意键继续

我的解答思路和尝试过的方法
我想要达到的结果

(1)p1=malloc(len);这么写不对啊,而且 len是宏定义中定义的,宏定义会预编译,预编译的时候根本不知道stu结构体是什么东西,得出的大小不一定正确。
(2)if(i=0)这里,漏写了一个=,应该是 if(i==0)
(3)
scanf("%f %s %f %f",&p1->stunum,&p1->name,&p1->examscore,&p1->labscore);这里改成
scanf("%f %s %f %f",&p1->stunum,p1->name,&p1->examscore,&p1->labscore);
(4)
for(i=0;i<n;i++)//计算学生总评成绩
{
p->totalmark=0.6p->examscore+0.4p->labscore;
}
这里,还有main函数中的输出,for循环中的p一直不变,输出的内容都一样,而且没有给p赋值的地方,是一个野指针,程序会崩掉的
(5)其它问题不说了,代码修改如下:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct student
{
    float stunum;          
    char name[20];    
    float examscore;    
    float labscore;
    float totalmark;    
    struct student * next;  
} stu ;

int len = sizeof(stu);

//定义全局变量.m,t,s[20]用于交换变量 
int i=0;
float t=0,m=0;
char s[20];
stu *p; 




struct student* sort_s(struct student *head)   //排序
{
    if(NULL == head)    //若链表为空则不用排序
    {
        return NULL;
    }
    if(NULL == head->next)  //若链表中只有一个数,则不用比较
    {
        printf("min is head\n");
        return head;
    }
    struct student *min_pre = NULL;
    struct student *min = head;
    struct student *tmp = head;
    struct student *new_list = NULL;   
    struct student *tail_sort = NULL;

    while(head)
    {
        min = head;
        tmp = head;
        while(tmp->next)
        {
            if(min->totalmark > tmp->next->totalmark)
            {
                min = tmp->next;
                min_pre = tmp;
            }
            tmp = tmp->next;
        }
        if(min == head)
        {
            head = head->next;
        }
        else
        {
            min_pre->next = min->next;
            min->next = NULL;
        }
        if(NULL == new_list)    //按照尾插将最小的数组成新的链表
        {
            tail_sort = min;
            new_list = tail_sort;
        }
        else
        {
            tail_sort->next = min;
            tail_sort = min;
        }
    }
    return new_list;
}


stu *create(int n)//n是学生人数
{    
    stu *head,*p1,*p2;
    printf("依次输入学生 学号 姓名 考试成绩 实验成绩\n");
    for(i=0;i<n;i++)//建立链表 
    {
        p1=(stu *)malloc(len);
        if(i==0)
        {
            head=p2=p1;//开始head p1 p2都指向新节点 
            scanf("%f %s %f %f",&p1->stunum,p1->name,&p1->examscore,&p1->labscore);
            p1->next=NULL;
        }
        else
        {
            p2->next=p1;
            p2=p1;//先将末尾节点指向新节点,在将p2指向新节点 
            scanf("%f %s %f %f",&p1->stunum,p1->name,&p1->examscore,&p1->labscore);
            p1->next=NULL;
        } 
    }


    p = head;
    for(i=0;i<n && p!=NULL;i++)//计算学生总评成绩 
    {
        p->totalmark=0.6*p->examscore+0.4*p->labscore; 
        p = p->next;
    }

    head = sort_s(head);
    return head; //返回头指针 
}

int main()
{
    int n;
    stu* ps;
    printf("输入学生人数:\n");
    scanf("%d",&n);//输入学生人数
    p=create(n); //p 赋值链表头指针 
    ps = p; //用ps,否则链表头就丢失了
    for(i=0;i<n && ps!=NULL;i++)
    {
        printf("stunum:%f name:%s examscore:%f labscore:%f totalmark:%f\n",ps->stunum,ps->name,ps->examscore,ps->labscore,ps->totalmark);
        ps = ps->next;
    }

    return 0;

}

应该出现程序崩溃直接退出了
create函数中,if(i=0)改为 if(i==0),不然if(i=0)是不成立的,所以执行else的代码段,这时候p2是没有分配空间的,p2->next=p1就崩溃了

第29行:
p1=(stu *)malloc(sizeof(stu));
加断点调试下吧

i=0改成了i==0 ;取消了宏定义;数组输入的时候去掉了&; for(p;p;p=p->next), p1=(stu*)malloc(sizeof(stu));这两处也改了。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student
{
    float stunum;          
    char name[20];    
      float examscore;    
      float labscore;
      float totalmark;    
    struct student * next;  
} stu ;
//定义全局变量.m,t,s[20]用于交换变量 
int i=0;
float t=0,m=0;
char s[20];
stu *p=NULL; 

stu *create(int n)//n是学生人数
{    
    stu *head,*p1,*p2;
    printf("依次输入学生 学号 姓名 考试成绩 实验成绩\n");
    for(i=0;i<n;i++)//建立链表 
    {
        p1=(stu*)malloc(sizeof(stu));
        if(i==0)
        {
            head=p2=p1;//开始head p1 p2都指向新节点 
            scanf("%f %s %f %f",&p1->stunum,p1->name,&p1->examscore,&p1->labscore);
            p1->next=NULL;
        }
        else
        {
            p2->next=p1;
            p2=p1;//先将末尾节点指向新节点,再将p2指向新节点 
            scanf("%f %s %f %f",&p1->stunum,p1->name,&p1->examscore,&p1->labscore);
            p1->next=NULL;
        } 
    }
    
    
    
    for(p;p;p=p->next)//计算学生总评成绩 
    {
        p->totalmark=0.6*p->examscore+0.4*p->labscore; 
    }
    
    for(i=0;i<n;i++)//按成绩对学生进行排序
    {
        for(p=head,p=p->next,p1=head;p1;p=p->next,p1=p1->next)
        {
            if(p1->totalmark<p->totalmark)
            {
                m=p->totalmark;p->totalmark=p1->totalmark;p1->totalmark=m;
                t=p->stunum;p->stunum=p1->stunum;p1->stunum=t;
                m=p->examscore;p->examscore=p1->examscore;p1->examscore=m;
                m=p->labscore;p->labscore=p1->labscore;p1->labscore=m;
                strcpy(s,p->name);strcpy(p->name,p1->name);strcpy(p1->name,s);//用到#include<string.h> 
            }
        }
    }  
    
    return head; //返回头指针 
}



int main()
{
    int n;
    printf("输入学生人数:\n");
    scanf("%d",&n);//输入学生人数
    
    p=create(n); //p 赋值链表头指针 
    
    for(p;p;p=p->next)
    {
        printf("stunum:%f name:%s examscore:%f labscore:%f totalmark:%f\n",p->stunum,p->name,p->examscore,p->labscore,p->totalmark);
    }
    
    
    return 0;
    
    
}



img

还有哪里需要改吗
谢谢各位了