代码之家  ›  专栏  ›  技术社区  ›  Srikar Appalaraju Tonetel

C中的链接列表

  •  3
  • Srikar Appalaraju Tonetel  · 技术社区  · 14 年前

    我在运行这个链表实现(将单词作为数据包含)时遇到一些问题。问题是当我试图打印链接列表中的单词(我插入的)时,我什么也得不到。我做错了什么,把我的头撞碎了?我希望这不是什么傻事。总之,这是密码-

    typedef struct node
    {
        void *data;
        struct node *next;
    } NODE;
    
    NODE *new_node(void *data)
    {
        NODE *new = malloc(sizeof(NODE));
        if(new)
        {
            new->data = data;
            new->next = NULL;
            return new;
        }
        else
        {
            return NULL;
        }
    }
    
    void print_list(NODE *head, void (print_fn) (void*))
    {
        if(head && head->next)
        {
            while(head->next)
            {
                if(print_fn)
                    print_fn(head->data);
                else
                    printf("Word: %s\n", (char *)head->data);
                head = head->next;
            }
        }
        return;
    }
    
    void append(NODE **head, NODE *node)                                                                                  
    {
        NODE *tmp = *head;
        if(tmp && node)
        {
            while(tmp->next)
                tmp = tmp->next; 
            (*head)->next = node; /*add as last node*/
        }
        return;
    }
    
    
    NODE *create_list()
    {
        FILE *dict_file = fopen("trial.txt", "r");
    
        if(dict_file)
        {
            NODE *head = new_node(NULL);
            if(!head) return NULL;
    
            char word[20];
            int first  = TRUE;
            memset(word, '\0', 20);
    
            while(fgets(word, sizeof(word), dict_file) != NULL )
            {
                if(first)
                {
                    head->data = (void*)word;
                    first = FALSE;
                }
                else
                {
                    append(&head, new_node((void*)word));
                }
            }
            fclose(dict_file);
            return head;
        }
        else
        {
            printf("ERROR: File not found");
            return NULL;
        }
    }
    
    int main(int argc, char *argv[])
    {
        NODE *head = create_list();
    
        if(!head)
        {
            printf("ERROR: Either malloc() failed or data not found\n");
            return FALSE;
        }
        else
        {
            print_list(head, NULL);
            return TRUE;
        }
    }
    
    2 回复  |  直到 12 年前
        1
  •  15
  •   Venemo    14 年前

    这已成为一个相当长的答案。别把这当成个人问题,但你犯了不少新手错误。我在大学里见过很多人,我帮助他们学习了C语言和编程,所以我习惯了注意到这些事情。

    我能找到的重要问题

    • 将指向堆栈变量的指针赋给 words
      这是完全错误的,因为一旦执行从创建该值的函数中退出,该值就会被覆盖。 解决方案:将该变量的内容复制到堆变量中。

    • 你的 append 功能故障
      它将附加元素添加到第二个位置,而不是最后一个位置。请注意,末尾也不需要返回。也不需要使用双指针作为 追加 方法。另外,分配后 head tmp ,检查TMP是无效的 NULL 还有,因为它不会 无效的 如果 不是 无效的 . 另外,我建议检查新节点 无效的 也。如果是 无效的 ,这样可以避免对整个集合进行迭代。

    • 这个 create_list 函数次优
      首先,区分第一种情况和其他情况是徒劳的。引入另一个指针(称为 current 在我的代码中)将不再需要检查它是否是第一个。接下来,你总是打电话给 追加 功能上 因此,您总是需要对整个集合进行迭代。这也可以通过引入 现在的 变量。(开始时,应为其指定 )

    • 这个 print_list 功能错误
      如果只有一个节点,则不会打印任何内容。它还冗余地检查指针是否为空。(循环的开始也会检查它。)此循环结束时的RETURN语句 void 功能也是不必要的。

    • 当你不使用它的时候,你应该释放内存
      @巴尔塔萨克写了一篇很好的 clear 在他的回答中,你应该使用它。:)

    不是很严重的错误,但是你应该意识到它们

    • 你不应该使用 void* 而不是 char* 如果你知道 data 会员 NODE 结构将存储字符,为什么要使用 空洞* ?这是不好的做法!(当然,除非你有充分的理由。)

    • 使用 new Word作为变量名使您的代码不符合C++。因此,我建议不要这样做。

    • 请采用更好的编码方式-这将使您的代码更容易阅读

    • 不一致:如果在 打印列表 您不需要分配一个新的变量来遍历集合(就像处理 川芎嗪 变量在 追加 )那么,将参数命名为 . (我把它改名为 node 在我的代码中)

    这是固定代码

    (请注意,可能有一些小的语法错误,因为我在浏览器中键入了代码,但实际上没有对其进行测试。)

    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct node
    {
        void *data;
        struct node *next;
    } NODE;
    
    NODE *new_node(void *data)
    {
        NODE *newNode = (NODE*)malloc(sizeof(NODE));
        if (newNode)
        {
            newNode->data = data;
            newNode->next = NULL;
            return newNode;
        }
        return NULL;
    }
    
    void append(NODE *head, NODE *node)
    {
        if (head && node)
        {
            NODE *tmp = head;
            while (tmp->next)
                tmp = tmp->next; 
            tmp->next = node; /* add as last node */
        }
    }
    
    void print_list(NODE *node, void (print_fn) (void*))
    {
        while (node)
        {
            if (print_fn)
                print_fn(node->data);
            else
                printf("Word: %s\n", (char *)node->data);
    
            node = node->next;
        }
    }
    
    NODE *create_list()
    {
        FILE *dict_file = fopen("trial.txt", "r");
    
        if (dict_file)
        {
            NODE *head = NULL;
            NODE *current = head;
    
            char word[20];
            memset(word, '\0', 20);
    
            while (fgets(word, sizeof(word), dict_file))
            {
                // Creating a variable on the heap
                char *data = calloc(sizeof(word) + 1, sizeof(char));
                // Copying the contents of words to it
                strcpy(data, word);
    
                append(current, new_node((void*)data));
                if (current->next)
                    current = current->next
            }
            fclose(dict_file);
            return head;
        }
        else
        {
            printf("ERROR: File not found");
        }
        return NULL;
    }
    
    int main(int argc, char *argv[])
    {
        NODE *head = create_list();
    
        if (!head)
        {
            printf("ERROR: Either malloc() failed or data not found\n");
        }
        else
        {
            print_list(head, NULL);
        }
        return 0;
    }
    
        2
  •  1
  •   Baltasarq    14 年前

    小心点,因为 马尔洛() 当内存不足时,导数可以用一个空指针来回答。事实上,考虑到你还需要 清除() 方法释放所有数据以及节点本身。

    void clear(NODE *node)
    {
        NODE * temp = NULL;
    
        while( node != NULL ) {
           temp = node->next;
           free( node->data );
           free( node );
    
           node = temp;
        }
    }
    

    main()函数应将退出代码返回到exit_success或exit_failure操作系统,而不是true或false。

    int main(int argc, char *argv[])
    {
        NODE *head = create_list();
        int toret = EXIT_SUCCESS;
    
        if(!head)
        {
            printf("ERROR: Either malloc() failed or data not found\n");
            toret = EXIT_FAILURE;
            clear( head );
        }
        else
        {
            print_list(head, NULL);
            clear( head );
        }
    
        return toret;
    }