【问题标题】:Keep printing the last element in the linked list继续打印链表中的最后一个元素
【发布时间】:2021-11-24 00:41:57
【问题描述】:

我在 C 中创建了一个标准链表。它要求用户输入一个数字,如果用户输入 # 则程序结束。如果用户输入任何其他内容,程序将停止。

问题是我的程序永远运行并首先打印普通列表,然后保持打印链接列表的最后一个元素。 希望有人能告诉我我在哪里做错了。

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

typedef struct node {
    int data;
    struct node *next;
} NodeT;

void freeLL(NodeT *list) {
    NodeT *p, *temp;
    p = list;
    while (p != NULL) {
        temp = p->next;
        free(p);
        p = temp;
    }
}

void showLL(NodeT *list) {
    NodeT *temp = list;
    temp = temp->next;
    printf("Done. The list is ");
    printf("%d", temp->data);
    temp = temp->next;
    //iterate the entire linked list and print the data
    while (temp != NULL) {
        printf("-->");
        printf("%d", temp->data);
        temp = temp->next; 
    }
}

NodeT *joinLL(NodeT *list, int v) {
    NodeT *current = list;
    NodeT *head;
    head->data = v;
    head->next = NULL;
    while (current->next != NULL) {
        current = current->next;
    }
    current->next = head;
    return head;
}

int main() {
    int data;
    NodeT *list = NULL;
    list = (NodeT *)malloc(sizeof(NodeT));
    printf("Enter a number: ");
    if (scanf("%d", &data) != 1) {
        printf("Done. ");
    } else {
        printf("Enter a number: ");
        joinLL(list, data);
        while (1 == scanf("%d", &data)) { 
            printf("Enter a number: ");
            joinLL(list, data);
        }
        showLL(list);
        freeLL(list);
    }
    
    return 0;
}

我认为问题出在joinLL 函数中,它在链表末尾添加了一个新节点。

【问题讨论】:

  • list = malloc(...)之后,list-&gt;next的值没有被初始化。后来的代码(错误地)依赖于它被设置为 NULL。
  • 您应该减少冗余并将列表初始化为NULL,并通过调用joinLL为其分配空间。您需要更改 API 以实现这一点,但这比将其作为特殊情况分配更干净。
  • @Frankshi:您可以通过点击分数下方的灰色复选标记来接受其中一个答案

标签: c debugging linked-list memory-address


【解决方案1】:

由于内存访问错误,你的程序一直在运行,你没有为你的头部分配内存(你设置了一个指针,但是直接使用它而不初始化它)

改成这个可能会解决问题:

head=(NodeT*)malloc(sizeof(NodeT));
if(NULL==head)
{
   // failed : do something...
   return NULL;
}
head->data=v;
head->next=NULL;

刚测试的时候,发现还有一个问题:

    list = (NodeT*)malloc(sizeof(NodeT));

malloc 不会初始化你的list,所以你的list-&gt;next 最初指向的值是不确定的。


in c, malloc does not need to be cast.

【讨论】:

  • 我不是 C 程序员(不尝试),但转换 malloc 是冗余 (stackoverflow.com/questions/605845/…),除非你知道自己在做什么。如果你想确保读者知道值是什么,或者让 C 移植到 C++,那么它可能是可以接受的。
  • @FaranAiki emm,这是我的习惯...(我经常需要确保我的代码与 C++ 兼容)
  • 添加解释为什么使用演员表。现在,我通常使用// Unnecessary casting.,并在标题/评论中解释我为什么要转换。
【解决方案2】:

问题是您没有在joinLL 中分配元素:在main() 中仅分配了一个元素。

您应该始终在joinLL 中分配元素,并根据返回值更新head 指针。

类似地,freeLL 应该采用指向 head 的指针并将其设置为 NULL 以保持一致性。

这是修改后的版本:

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

typedef struct node {
    int data;
    struct node *next;
} NodeT;

void freeLL(NodeT *p) {
    while (p != NULL) {
        NodeT *temp = p->next;
        free(p);
        p = temp;
    }
}

void showLL(const NodeT *list) {
    NodeT *p = list;
    printf("The list is ");
    if (p == NULL) {
        printf("empty");
    } else {
        printf(" %d", temp->data);
        while ((p = p->next) != NULL) {
            printf("--> %d", temp->data);
        }
    }
    printf("\n");
}

NodeT *joinLL(NodeT *head, int v) {
    NodeT *newp = malloc(sizeof(*p));
    NodeT *current;

    if (newp == NULL) {
        fprintf(stderr, "allocation failure\n");
        exit(1);
    }
    newp->data = v;
    newp->next = NULL;
    if (head == NULL) {
        return newp;
    }
    for (current = head; current->next != NULL; current = current->next)
        continue;

    current->next = newp;
    return head;
}

int main() {
    NodeT *list = NULL;
    for (;;) {
        int data;
        printf("Enter a number: ");
        if (scanf("%d", &data) != 1) {
            printf("Done. ");
            break;
        }
        list = joinLL(list, data);
    }
    showLL(list);
    freeLL(list);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 2021-12-20
    相关资源
    最近更新 更多