【问题标题】:Linked list nodes added to the same address添加到相同地址的链表节点
【发布时间】:2019-10-19 13:57:27
【问题描述】:

我正在使用 fgetc 并分隔单词来读取 UTF-8 格式的文本文件。我做了一个附加函数来将每个单词添加到一个链表中,但是当我打印出单词的地址时,它们都是相同的,表明它们只是被覆盖了。如何正确地将数据添加到我的列表中?

我还做了一个打印命令来遍历列表,虽然数据在我的附加函数中正确打印出来,但打印函数只是给出了一个垃圾值。

struct node
{
    void *data;
    struct node *next;
};

我将 def this 输入到linked_list

每当我得到一个新单词时,我都会在 main 中调用 append 函数。

void append(linked_list *list, void *word)
{

    if(list->data == NULL)
    {
        list->data = word;
        list->next = NULL;
                //printf("WORD: %s\n", (char *)list->data);
        //printf("ADDRESS %p\n", list->data);
    }
    else
    {
        linked_list *new_node;
        new_node = malloc(sizeof(linked_list));
        new_node->data = word;
        new_node->next = NULL;

        while(list->next != NULL)
        {
            if(list->next == NULL)
            {
                list->next = new_node;
            }

        }
                //printf("WORD: %s\n", (char *)list->data);
        //printf("ADDRESS %p\n", list->data);

    }

}

这是我的打印功能

void print_list(linked_list *list) {

    if(list == NULL)
    {
        printf("Print: the list is empty!\n");
    }

    while (list != NULL) {
        printf("DATA %s\n", (char *)list->data);
        list = list->next;
    } 

}

我希望打印功能可以打印

'DATA the_word' 用于所有单词,但我得到 'DATA �'

附加函数中的打印给出:

WORD: The
ADDRESS 0x55b6fa2314b0

WORD: Project
ADDRESS 0x55b6fa2314b0

WORD: Gutenberg
ADDRESS 0x55b6fa2314b0

WORD: EBook
ADDRESS 0x55b6fa2314b0

WORD: of
ADDRESS 0x55b6fa2314b0

WORD: Pride
ADDRESS 0x55b6fa2314b0

WORD: and
ADDRESS 0x55b6fa2314b0

WORD: Prejudice,
ADDRESS 0x55b6fa2314b0

WORD: by
ADDRESS 0x55b6fa2314b0

WORD: Jane
ADDRESS 0x55b6fa2314b0

WORD: Austen
ADDRESS 0x55b6fa2314b0

【问题讨论】:

  • “它们都是一样的”——是的,因为您可能将它们扫描到同一个缓冲区中,然后只存储该缓冲区的地址。您应该在存储字符串时对其进行复制。 (strdup 可能有用,但不是标准功能。)
  • 目前还不清楚这个程序是如何做任何事情的,因为while(list->next != NULL) 循环永远不会终止。

标签: c linked-list malloc


【解决方案1】:

这个程序有很多问题。

  1. 空列表的表示。看起来您已经选择用没有数据的虚拟节点来表示一个空列表。虽然这在技术上本身并没有错,但这并不是最直观和最直接的表示。通常一个空列表简单地用一个空指针表示。请参阅this SO question 了解更多信息。
  2. 加法循环错误。目前尚不清楚您的函数如何向列表中添加多个节点。

    while(list->next != NULL)
    {
        // at this point, list->next != NULL, by definition (see loop condition)
        if(list->next == NULL) // this is always false
        {
            list->next = new_node; // this is never executed
        }
        // the loop body doesn't modify anything
    }
    

    另一个答案有办法纠正,这里不再赘述。

  3. 最后但同样重要的是,您所抱怨的错误是 very common pitfall 的结果。

【讨论】:

  • 您链接的问题的解决方案解决了该问题。我得到数据并将其存储在正确的地址。但是你能解释一下首先将数据复制到另一个指针中会产生怎样的影响吗?
  • @js_hammer08 你需要了解数组和指针在 C 中是如何工作的,它们之间有什么区别,以及它们之间的联系是什么。这超出了这个答案的范围。
【解决方案2】:

问题出在这部分:

while(list->next != NULL)
{
    if(list->next == NULL)
    {
        list->next = new_node;
    }

}

你不去下一个节点,总是在第一个节点。复制list(不更改列表本身)并遍历它:

linked_list *copy = list;

while(copy->next != NULL)
{
    copy = copy->next;
}

copy->next = new_node;


【讨论】:

  • 这仍然给我相同的输出!
  • 打印功能?我应该提一下,当我在 valgrind 下运行程序时,它确实给了我正确的数据和不同的地址。当我运行它时,我会得到所有单词的垃圾值。 void print_list(linked_list *list) { if(list == NULL) { printf("Print: the list is empty!\n"); } while (list != NULL) { printf("DATA %s\n", (char *)list->data); list = list->next; } }
  • 但是你在哪里打印地址?
  • @js_hammer08 您需要发布minimal reproducible example,而不是随意编辑的片段集合。
猜你喜欢
  • 2020-01-22
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多