链表的插入函数,调用的时候从第二次开始会覆盖值,求改

题目:
排队管理模拟
用程序实现模拟人的排队方式的一个的管理模型。适合于比如买餐,买票,或者是防疫出入校门和公共场所等场景的排队问题。
设计任务要求:
1)可以随时随机输入任意人名,比如Tom, Jerray, Jack, Sam等。有输入的人名,按回车键,则会立刻被程序安排进入排队机排队。并且显示出当前排队剩余多少人。
2)队首排队的人轮候结束需要出队时。当任意时候输入“出队”(或者Dequeue),立刻从队首取出一个人名输出到屏幕上,并且显示出当前还剩余有多少人在排队。
3)队列有容量限制,如果队列满(OVERFLOW),比如最多允许100人等候。则需要提示“当前排队人数已满”或“队列溢出”。

题目的要求我稍微做了修改,没有完全符合题目的逻辑,只实现其中的功能。
下边是代码,可以拿走跑一下。
问题就是插入第一次是可以插到最后的,但是再次插入就会覆盖掉刚才的值。
懵了,求解。。。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<malloc.h>
#define LEN sizeof(struct name)    //将LEN定义结构体类型长度 

/*
项目设计3:排队管理系统(模拟程序):
 
*/


typedef struct name{            //声明一个结构体,用来存放排队者的姓名 
    char username[30];        //排队者姓名类型是字符串,长度30 
    struct name *next;    // *next指针变量指向下一个节点 
}Name,*NAME;

int n=0;    //正儿八经全局变量,本文件中各个函数均可使用,代表排队的人数 

/*初始化排队者(函数)*/
struct name *creat(void){    //这个函数返回一个指向链表头的指针 ,实际上就是返回creat的值,就是链表中第一个节点的起始地址 
    struct name *head,*p1,*p2;    //创建头指针和分别用于开辟和绑定新节点的p1 p2
    char check[30];
    p1=p2=(struct name * ) malloc(LEN);    //开辟新的节点,实际上是开辟一个长度为LEN(自定义结构体)的内存区 
    printf("请在下方输入排队者的姓名:\n\n");
    gets(check); 
    if(strcmp(check,"ok")!=0){        //如果输入的不是"ok"
        strcpy(p1->username,check);    //让p1指向新的节点值 
        head=NULL;    //先使头指针值为空,表示链表中没有节点 (节点还没有被纳入链表),纳入链表工作在下边的循环体 
        while(1){    //开始循环 
            n+=1;    //n的值从0变为 1,象征链表出现第一个节点 ;n的值增加,代表排队的人数 
            if(n==1){
                head=p1;    //将p1的值赋给头指针,象征新节点被纳入链表  (这个新节点的值可以是"ok",但是这个节点肯定不会被纳入链表--->)
            }
            else{    //这个情况是下边出现紧跟排队者情况的处理 
                p2->next=p1;    /*此时的p1是下边的情况,已经指向了第二个节点值,让p1把自己指向的地址给此时还在指向第一个节点的p2的
                                 next成员*/ 
                p2=p1;    //再让p2也去指向p1指向的第二个节点,就完成了一二节点的绑定,链表形成了 
            }
            //printf("请在下方输入排队者的姓名:\n\n");
            gets(check);
            if(strcmp(check,"ok")==0){
                break;    //如果输入的是"ok"则跳出循环,录入工作完成 --->
            }else{
                p1=(struct name *)malloc(LEN);    //如果还不是ok,开辟第二个的节点 
                strcpy(p1->username,check);    //让p1指向第二个节点值 
            }
        }p2->next=NULL;    //<---(承接第34行注释)所以p2就不用指向这个新节点,链表收尾 
        return(head);    //对应第22行代码意义 返回链表中第一个节点的起始地址 
    }else{
        return 0;    //如果没有任何的新节点加入,返回空值 
    }
} 


/*打印排队者人数和姓名(函数)*/
void print(struct name *head){    //函数参数为结构体头指针 
    struct name *p;
    if(head!=NULL){    //头指针不为空 
        p=head;    //让指针p跟随头指针找到第一个节点 
        printf("\n\n\t当前队列人数:%d\n\n",n);
        do{
            printf("%s\t",p->username);    //输出指针指向的节点的值(姓名) 
            p=p->next;    //指针移动 指向下一个节点 
        }while(p!=NULL);{    //当指针p为空时,就是移动指向了 链表初始化结束最后一个节点后边的那个p1指向的无意义的节点 
            printf("\n\n\n---------------------\n\n\n");
        }
    }else printf("\n\t队列空闲无人\n");    //如果头指针是空的,说明根本不存在链表,象征不存在的队列 
} 


/*队首排队者出队(函数)*/
struct name *del(struct name *head){
    struct name *p;    //创建p指针
    if(head==NULL){
        printf("\n\t队列空闲无人\n");
        return(head);
    }
    p=head;    //让p指针指向头指针指向的第一个节点 
    head=head->next;    //头指针原本指向的节点里的next指针成员将自己指向的下一个节点的地址告诉自己,然后指他去了 
    free(p);    //第一个节点现在只被p指针指着了,free(p),释放掉他 
    printf("==此人已被移除队列==\n");
    return(head); 

}


/*退出模拟系统(函数)*/
//这个函数用来清空链表,并对应主函数switch中的语句结束整个程序 
struct name *exit(struct name *head){
    struct name *p0;    //和上一个队首者出队原理一样 
    while(head!=NULL){
        p0=head;    
        head=head->next;
        free(p0);    //这三个语句,头指针去找下一个,p0指针释放原来的节点,释放完了再去跟头指针,最终释放全部的链表节点 
    }return(head);
} 


/*新的排队者加入队列(函数) 就是在链表最后再加入一个节点  */
struct name *add(struct name *head,struct name *insert){    //参数有头指针和用于指向主函数用来接收新节点值的指针 
    
    struct name *p0,*p1,*p2;    //在基础上新增额外的p0指针用于指引新加入的节点 
    p0=(struct name *)malloc(LEN);    //给p0开辟长度为LEN(就是自定义结构体的长度)的内存区 
    p1=head;    //头指针传值给p1指针,让p1指向头节点 
    p0=insert;    //p0指向主函数里键入的新节点的值 
    if(head==NULL){    //如果头指针为空,说明链表为空,不存在 
        head=p0;    //p0指向的新节点赋给头指针 
        p0->next=NULL;    //让p0指针指向的节点的next成员的值为空,不在链入新的节点,链表收尾 
    }else{    //头指针不为空的话,说明链表存在 
        
        while(p1->next!=NULL){
            p2=p1;
            p1=p1->next;
        } 
        p1->next=p0;
        p0->next=NULL;
    }
    n+=1;
    return (head);
    
}


/*主函数*/
int main(void){
    struct name *head=NULL,message;
    char a[10];

    head=creat(); 
    printf("\n\n");
    while(1){
        printf("\n\n\n\n");
        printf("================================\n\n");
        printf(" 录入新的排队者-------------- 1 \n");
        printf(" 查看队列人数和信息---------- 2 \n");
        printf(" 队首者出队------------------ 3 \n");
        printf(" 退出------------------------ 4 \n\n");
        printf("================================\n");
        printf("  请输入一个序号来进行以上操作:");
        gets(a);
        switch(*a){
            case '1':{
                printf("要进入的人:");
                gets(message.username);
                //scanf("%s",&message.username);
                head=add(head,&message);
                break; 
            }
            case '2':{
                print(head);
                break;
            }
            case '3':{
                head=del(head);
                n=n-1;    //出队一个,排队中人数-1 
                break;
            }
            case '4':{
                head=exit(head);
                break;
            }
            default: printf("参数错误!请重新选择功能");break;
        }if(strcmp(a,"4")==0) break; 
    } 
}

帮你改了改!这样结构其实不一样了呢!你看看如何变成你的风格吧!

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define new(x) (x*)malloc(sizeof (x))
/*
   项目设计3:排队管理系统(模拟程序):
   */

typedef struct name{            //声明一个结构体,用来存放排队者的姓名 
    char username[30];        //排队者姓名类型是字符串,长度30 
    struct name * next;    // *next指针变量指向下一个节点 
}Name,*pName;
/*初始化排队者(函数)*/
pName create(void){    //这个函数返回一个指向链表头的指针 ,实际上就是返回create的值,就是链表中第一个节点的起始地址 
    pName head, p1, p2;    //创建头指针和分别用于开辟和绑定新节点的p1 p2
    head=p1=p2=NULL;
    char check[30];
    printf("请在下方输入排队者的姓名:\n");
    while(1){    //开始循环 
        scanf("%s", check); 
        if(strcmp(check,"ok")!=0){        //如果输入的不是"ok"
            p1=new(Name);
            strcpy(p1->username,check);    //让p1指向新的节点值 
            if(head==NULL){
                head=p1;    //将p1的值赋给头指针,象征新节点被纳入链表  (这个新节点的值可以是"ok",但是这个节点肯定不会被纳入链表--->)
                p2=head;
            }
            else{    //这个情况是下边出现紧跟排队者情况的处理 
                p2->next=p1;
                p2=p2->next;
            }
        }
        else{
            break;
        }
    }
    return head;
} 

/*打印排队者人数和姓名(函数)*/
void print(pName head){    //函数参数为结构体头指针 
    int n=0;
    while(head!=NULL){    //头指针不为空 
        n+=1;
        printf("%s ",head->username);    //输出指针指向的节点的值(姓名) 
        head=head->next;    //指针移动 指向下一个节点 
    }
    printf("当前队列人数:%d\n",n);
} 

/*队首排队者出队(函数)*/
pName del(pName head){
    pName p;    //创建p指针
    if(head==NULL){
        printf("队列空闲无人\n");
        return(head);
    }
    printf("此人已被移除队列: %s\n", head->username);
    p=head;    //让p指针指向头指针指向的第一个节点 
    head=head->next;    //头指针原本指向的节点里的next指针成员将自己指向的下一个节点的地址告诉自己,然后指他去了 
    free(p);    //第一个节点现在只被p指针指着了,free(p),释放掉他 
    return(head); 
}

/*退出模拟系统(函数)*/
//这个函数用来清空链表,并对应主函数switch中的语句结束整个程序 
pName exit_system(pName head){
    pName p0;    //和上一个队首者出队原理一样 
    while(head!=NULL){
        p0=head;    
        head=head->next;
        free(p0);    //这三个语句,头指针去找下一个,p0指针释放原来的节点,释放完了再去跟头指针,最终释放全部的链表节点 
    }return(head);
} 

/*新的排队者加入队列(函数) 就是在链表最后再加入一个节点  */
pName add(pName head){    //参数有头指针和用于指向主函数用来接收新节点值的指针 
    pName insert=new(Name);
    printf("要进入的人:");
    scanf("%s", insert->username);
    if(head==NULL){
        head=insert;
        return head;
    }
    pName p=head;
    while(head->next!=NULL){
        head=head->next;
    }
    head->next=insert;
    return p;
}

/*主函数*/
int main(void){
    pName head=create(); 
    int a=0;
    while(1){
        printf(" 1录入新的排队者");
        printf(" 2查看队列人数和信息");
        printf(" 3队首者出队");
        printf(" 4退出: ");
        scanf("%d", &a);
        switch(a){
            case 1:
                head=add(head);
                break; 

            case 2:
                print(head);
                break;

            case 3:
                head=del(head);
                break;

            case 4:
                head=exit_system(head);
                break;

            default: printf("参数错误!请重新选择功能");break;
        } 
        if(a==4){
            break;
        }
    } 
    return 0;
}