鱼C论坛

 找回密码
 立即注册
查看: 965|回复: 6

[已解决]求助,c语言结构体和链表的问题

[复制链接]
发表于 2021-1-19 17:02:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这个程序,第一次循环执行完成后,head,p1,p2是指向同一个节点的,在执行第二次循环时,循环体内(*p2).next=p1,p1把地址给了p2的next。

我理解的head和p2是两个不同的结构体变量,p2的next被p1改变,head的next值应该不变呐。

但是我执行printf("%d\n%d\n",(*p2).next,(*head).next);把他们地址打印出来发现是一样的,这是为什么啊?

按照链表的定义,这里head的next值是必须要变才能跟后面链接上的,但是我的理解head的next应该是不变的啊,大佬们我的理解哪里出了问题。
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

#define LEN sizeof(struct student)

struct student *creat();
void print(struct student *head);

struct student 
{
        int num;//存放学生编号;
        float score;//存放学生分数;
        struct student *next;
}*stu,*p1,*p2;

int n;//记录输入次数

int main(void)
{
        struct student *stu;

        stu=creat();
        print(stu);

        printf("\n\n");
        system("pause");
}

struct student *creat()
{
        struct student *head;
        struct student *p1,*p2;

        p1=p2=(struct student *)malloc(LEN);
                                                                                
        printf("Please enter the num:");
        scanf("%d",&(*p1).num);
        printf("Please enter the score:");
        scanf("%f",&(*p1).score);

        head=NULL;//初始化头节点
        n=0;

        while(0!=(*p1).num)
        {
                n++;
                if(1==n)
                {
                        head=p1;
                }
                else 
                {
                        (*p2).next=p1;
                        if(n==2)
                        {
                                printf("%d\n%d\n",(*p2).next,(*head).next);
                        }
                }

                p2=p1;
                p1=(struct student *)malloc(LEN);//再次给p1分配长度,开辟新节点

                printf("Please enter the num:");
                scanf("%d",&(*p1).num);
                printf("Please enter the score:");
                scanf("%f",&(*p1).score);
        }

        (*p2).next=NULL;

        return head;

}
void print(struct student *head)
{
        struct student *p;
        printf("\nThere are %d record!\n\n",n);

        p=head;
        if(NULL!=head)
        {
                do
                {
                        printf("学号为%d的成绩是:%f\n",(*p).num,(*p).score);
                        p=(*p).next;
                }while(p);
        }
}
最佳答案
2021-1-19 17:47:12
本帖最后由 jackz007 于 2021-1-19 17:51 编辑

        为你重写了链表创建函数,并加上了详细注释
struct student * creat()
{
        struct student * head , * p1 , * p2                                        ;
        int num                                                                    ;
        for(p1 = p2 = head = NULL ;;) {
                printf("Please enter the num : ")                                  ;
                scanf("%d" , & num)                                                ;
                if(num > 0) {                                                           // 只有在确定 num 为正整数时才分配内存,创建节点
                        if((p1 = (struct student *) malloc(sizeof(struct student)))) {  // 判定内存分配是否成功
                                p1 -> num = num                                    ;    // 到了这里,说明内存分配很成功,结构成员赋值
                                printf("Please enter the score : ")                ;    // 结构成员赋值
                                scanf("%f" , & p1 -> score)                        ;    // 结构成员赋值
                                p1 -> next = NULL                                  ;    // 结构成员赋值
                                if(p2) p2 -> next = p1                             ;    // p1 不是首节点,让上一个节点的 next 域指向 p1
                                else  head = p1                                    ;    // p1 是首节点,让链表头指针指向首节点 p1
                                p2 = p1                                            ;    // 腾出 p1 准备新建下一个节点
                        } else {                                                        // 如果内存分配失败
                                for(p1 = head ; p1 ; p1 = p2) {                         // 释放所有链表节点所占用的内存
                                        p2 = p1 -> next                            ;    // 释放所有链表节点所占用的内存
                                        free(p1)                                   ;    // 释放所有链表节点所占用的内存
                                }
                                fprintf(stderr , "\n")                             ;
                                fprintf(stderr , "Failed to allocate memeory .\n") ;
                                fprintf(stderr , "\n")                             ;
                        }
                } else {                                                                // 输入 num 为 0 或负值结束链表创建
                        break                                                      ;    // 结束循环
                }
        }
        return head                                                                ;    // 返回头节点指针
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-1-19 17:47:12 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2021-1-19 17:51 编辑

        为你重写了链表创建函数,并加上了详细注释
struct student * creat()
{
        struct student * head , * p1 , * p2                                        ;
        int num                                                                    ;
        for(p1 = p2 = head = NULL ;;) {
                printf("Please enter the num : ")                                  ;
                scanf("%d" , & num)                                                ;
                if(num > 0) {                                                           // 只有在确定 num 为正整数时才分配内存,创建节点
                        if((p1 = (struct student *) malloc(sizeof(struct student)))) {  // 判定内存分配是否成功
                                p1 -> num = num                                    ;    // 到了这里,说明内存分配很成功,结构成员赋值
                                printf("Please enter the score : ")                ;    // 结构成员赋值
                                scanf("%f" , & p1 -> score)                        ;    // 结构成员赋值
                                p1 -> next = NULL                                  ;    // 结构成员赋值
                                if(p2) p2 -> next = p1                             ;    // p1 不是首节点,让上一个节点的 next 域指向 p1
                                else  head = p1                                    ;    // p1 是首节点,让链表头指针指向首节点 p1
                                p2 = p1                                            ;    // 腾出 p1 准备新建下一个节点
                        } else {                                                        // 如果内存分配失败
                                for(p1 = head ; p1 ; p1 = p2) {                         // 释放所有链表节点所占用的内存
                                        p2 = p1 -> next                            ;    // 释放所有链表节点所占用的内存
                                        free(p1)                                   ;    // 释放所有链表节点所占用的内存
                                }
                                fprintf(stderr , "\n")                             ;
                                fprintf(stderr , "Failed to allocate memeory .\n") ;
                                fprintf(stderr , "\n")                             ;
                        }
                } else {                                                                // 输入 num 为 0 或负值结束链表创建
                        break                                                      ;    // 结束循环
                }
        }
        return head                                                                ;    // 返回头节点指针
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

 楼主| 发表于 2021-1-20 09:35:19 | 显示全部楼层
jackz007 发表于 2021-1-19 17:47
为你重写了链表创建函数,并加上了详细注释

谢谢,但是我还是那个疑问啊,链表头指针是怎么指向下一个的,head=p1;是把p1内容给head吗,如果是指向p1不应该是head->next=p1,这样把p1的地址给head的内容吗,然后才能链接上吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-20 10:28:59 | 显示全部楼层
本帖最后由 jackz007 于 2021-1-20 10:41 编辑
MeowMoo 发表于 2021-1-20 09:35
谢谢,但是我还是那个疑问啊,链表头指针是怎么指向下一个的,head=p1;是把p1内容给head吗,如果是指向p ...


        head = p1 就是让 head 指向链表首节点。
        head 和 p1 都是指针,你可以把它理解成一种特殊的整型变量,是可以被赋值的,其数值就是内存地址,就好比是宾馆的房间编号。有 3 位客人入住一家宾馆,第一个人被分配到1802,p1 = 1802,head = p1,p2 = p1,第二个客人被分配到1303, p1 = 1303,1802 的客人知道这个信息, p2 -> next = p1 , p2 = p1,第三个客人被分配到1605,p1 = 1605,1303 的客人知道这个信息,p2 -> next = p1,我们想要找到所有的 3 个客人,只需要知道 head = 1802,这样,三位客人不都可以被找到了吗。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-20 10:56:32 | 显示全部楼层
jackz007 发表于 2021-1-20 10:28
head = p1 就是让 head 指向链表首节点。
        head 和 p1 都是指针,你可以把它理解成一 ...

意思是这个传递过程只有结构体变量地址的传递,没有结构体变量成员的值的传递吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-20 11:26:47 | 显示全部楼层
MeowMoo 发表于 2021-1-20 10:56
意思是这个传递过程只有结构体变量地址的传递,没有结构体变量成员的值的传递吗?


      是的,你得清楚,指针和节点是有本质区别的,客人是节点,而指针,只是门牌号 -- 只不过是一个数字而已。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-20 13:24:54 | 显示全部楼层
jackz007 发表于 2021-1-20 11:26
是的,你得清楚,指针和节点是有本质区别的,客人是节点,而指针,只是门牌号 -- 只不过是一个数 ...

好的,明白了,非常感谢大佬!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-12 06:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表