关于c语言链表的输出问题

在void UMS_444()中,while的循环条件是p->next!=NULL。p 指向倒数第二个节点,而 p->next 是最后一个节点,可以正常进入while。之后p指向最后一个结点,最后一个结点next为NULL,不符合while的条件,按理说不会进入循环,最后一个结点的数据也无法输出。但在我的测试中,最后一个数据仍然能正常输出,求高人指点

node1* user_link()
{
    node1 *head=(node1 *)malloc(sizeof(node1));
    node1 *last;
    head->next=NULL;
    last=head;
    FILE *fp;
    fp=fopen("user.txt","r");
    while(!feof(fp))
    {
        node1 *s=(node1 *)malloc(sizeof(node1));
        fscanf(fp,"%d %s %d",&s->data.num,s->data.mima,&s->data.leixing);
        last->next=s;
        s->next=NULL;
        last=s;
    }
    fclose(fp);
    return head;
}      
                                                                                                                                                                                              
 void UMS_444()
{
    node1 *head=user_link();
    node1 *p=head->next;
    while(p->next!=NULL)
    {
        printf("%d   ",p->data.num);
        printf("%s   ",p->data.mima);
        printf("%d   ",p->data.leixing);
        printf("\n");
        p=p->next;
    }
}

在UMS_4440函数中,while循环的条件是p->next!=NULL。由于最后一个节点的next指针为NULL,因此该条件不成立,循环不会执行。但是,由于在user_link()函数中最后一个节点的next指针被设置为NULL之前已经将数据读入了内存,因此在UMS_4440函数中仍然可以访问最后一个节点的数据。

while(!feof(fp)) 这个判断会读到最后一个EOF标记后结束,
就是说你读到的最后一个数据并不是看到的最后一个数据,而是EOF,所以最后一个p指向的内容是EOF,并不是你理解的最后一个数据
参见下面的博客,搜下 feof 的解释,有很多
https://blog.csdn.net/weixin_41170125/article/details/126806010?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_utm_term~default-4-126806010-blog-94599703.235^v38^pc_relevant_anti_t3&spm=1001.2101.3001.4242.3&utm_relevant_index=7

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 以下回答来自chatgpt:

    问题分析: 这个问题可能是由于链表结构定义的问题导致的,例如最后一个节点的next可能没有置为NULL。也有可能是在循环输出的过程中,没有正确地判断循环条件,导致节点被重复输出。

    解决方案: 1. 检查链表结构定义是否正确,最后一个节点的next是否被置为NULL。如果没有,可以在创建链表时手动将最后一个节点的next赋值为NULL。 2. 对于循环输出时节点被重复输出的问题,可以在循环体内加入判断条件,判断当前节点是否为最后一个节点。如果是,则跳出循环。

    以下是代码示例:

    typedef struct Node {
        int data;
        struct Node *next;
    }node;
    
    void UMS_444(node *head) {
        node *p = head;
        while(p->next != NULL) {
            printf("%d ", p->data);
            p = p->next;
            if(p->next == NULL) {
                printf("%d ", p->data);
                break;
            }
        }
    }
    

    在这个示例代码中,增加了一个判断条件,如果当前节点是最后一个节点,就会跳出循环,避免了最后一个节点被重复输出的问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^