pomelo_6364 2021-07-04 20:09 采纳率: 100%
浏览 26
已结题

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

题目:
排队管理模拟
用程序实现模拟人的排队方式的一个的管理模型。适合于比如买餐,买票,或者是防疫出入校门和公共场所等场景的排队问题。
设计任务要求:
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; 
    } 
}
  • 写回答

1条回答 默认 最新

  • Soda Wang 2021-07-04 22:36
    关注

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

    #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;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 9月16日
  • 已采纳回答 9月8日

悬赏问题

  • ¥15 不小心不正规的开发公司导致不给我们y码,
  • ¥15 我的代码无法在vc++中运行呀,错误很多
  • ¥50 求一个win系统下运行的可自动抓取arm64架构deb安装包和其依赖包的软件。
  • ¥60 fail to initialize keyboard hotkeys through kernel.0000000000
  • ¥30 ppOCRLabel导出识别结果失败
  • ¥15 Centos7 / PETGEM
  • ¥15 csmar数据进行spss描述性统计分析
  • ¥15 各位请问平行检验趋势图这样要怎么调整?说标准差差异太大了
  • ¥15 delphi webbrowser组件网页下拉菜单自动选择问题
  • ¥15 wpf界面一直接收PLC给过来的信号,导致UI界面操作起来会卡顿