C 中的链表

发布于 2024-09-19 22:11:45 字数 2036 浏览 1 评论 0原文

我在运行此链表实现(包含单词作为数据)时遇到一些问题。问题是当我尝试打印链接列表中的单词(我插入的)时,我什么也没得到。我做错了什么,为此伤透了脑筋?我希望这不是一件愚蠢的事情。无论如何,这是代码 -

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;
    }
}

I am having some trouble running this linked list implementation (containing words as data). Problem is when I try to print the words (that I inserted) in the Linked List,I get nothing. What am I doing wrong, breaking my head over this? I hope it's not something silly. Anyway here's the code -

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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一抹微笑 2024-09-26 22:11:45

这已经成为一个相当长的答案。不要认为这是针对你个人的,但你已经犯了很多新手错误。我在大学里遇到过很多人,我帮助他们学习了 C 语言和一般的编程,所以我已经习惯了注意到这些事情。

我可以找到的重要问题

  • 您将指向堆栈变量的指针分配给words
    这完全是糟糕的,因为一旦执行结束创建它的函数,该值就会被覆盖。 解决方案:将该变量的内容复制到堆变量中。

  • 您的 append 函数有错误
    它将附加元素添加到第二个位置而不是最后一个位置。请注意,您也不需要最后返回。要求双指针作为 append 方法的输入也是没有意义的。另外,在将 head 分配给 tmp 后,检查 tmp 是否为 NULL 也是徒劳的,因为它不会是 NULL 如果 head 不是 NULL。另外,我建议也检查新节点是否为 NULL。如果它是 NULL,这可以让您免于迭代整个集合。

  • create_list 函数不是最优的
    首先,区分第一种情况和其他情况是徒劳的。引入另一个指针(在我的代码中称为current)将消除检查它是否是第一个的需要。接下来,您总是在 head 上调用 append 函数,因此您始终需要迭代整个集合。这也可以通过引入 current 变量来优化。 (在开始时,应分配 head 的值。)

  • print_list 函数是错误的
    如果只有一个节点,它不会打印任何内容。它还冗余地检查指针是否为空。 (循环的开头也会检查它。)此 void 函数末尾的 return 语句也是不必要的。

  • 不使用内存时应释放内存
    @Baltasarq 在他的答案中写了一个很好的 clear 函数,你应该使用它。 :)

不是严重错误,但您应该注意它们

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

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

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

  • 不一致:如果在print_list 您没有分配新变量来遍历集合(就像您在 append 中使用 tmp 变量一样),那么它会产生误导将参数命名为 head。 (我在代码中将其重命名为 node。)

这是固定代码

(请注意,可能存在小的语法错误,因为我在浏览器中输入了代码而没有实际测试它。)< /em>

#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;
}

This has become quite a long answer. Don't take this personally, but you have made quite a few rookie mistakes. I have met with many people at university whom I helped to learn the C language and programming in general, so I've got used to notice these kinds of things.

The important issues I could find

  • You assign a pointer to a stack variable to words
    This is completely bad, because that value will be overwritten once the execution gets out of the function that creates it. Solution: copy the content of that variable into a heap variable.

  • Your append function is faulty
    It adds the appended element to the second place instead of the last place. Note that you don't need the return at the end either. There is also no point in requiring a double-pointer as input to the append method. Also, after assigning head to tmp, it is futile to check tmp against NULL as well, since it won't be NULL if head isn't NULL. Also, I recommend checking the new node against NULL as well. If it is NULL, this saves you from iterating over the entire collection.

  • The create_list function is sub-optimal
    Fist, the distinction between the first and the other cases are futile. Introducing another pointer (called current in my code) will eliminate the need to check whether it is the first or not. Next, you always call the append function on the head, thus you always need to iterate over the entire collection. This can be also optimized by introducing the current variable. (Which, at start, should be assigned the value of head.)

  • The print_list function is errornous
    It doesn't print anything if there is only one node. It also redundantly checks the pointers for null. (The beginning of the loop checks it, too.) The return statement at the end of this void function is also unnecessary.

  • You should free up memory when you don't use it
    @Baltasarq wrote a nice clear function in his answer, you should use it. :)

Not serious errors, but you should be aware of them

  • You should not use void* instead of char*
    If you know that the data member of the NODE structure is going to store characters, why do you use void*? It is bad practice! (Unless you have a good reason, of course.)

  • Using the new word as a variable name makes your code not compliant with C++. Thus, I recommend against it.

  • Adopt a better coding style, please - it will make your code so much easier to read

  • Inconsistency: if in print_list you don't allocate a new variable to go through the collection (like you do with the tmp variable in append) then it is misguiding to name the parameter as head. (I renamed it to node in my code.)

Here is the fixed code

(Note that there may be small syntax errors because I typed the code into the browser without actually testing it.)

#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;
}
西瓜 2024-09-26 22:11:45

请小心,因为当内存不足时,malloc() 及其派生函数可以使用 NULL 指针进行应答。事实上,请考虑到您还需要一个 clear() 方法来释放所有数据以及节点本身。

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;
}

Be careful, since malloc() and derivatives can answer with a NULL pointer when there is not enough memory. In fact, take into account that you'll also need a clear() method that free's all the data, as well as the nodes themselves.

void clear(NODE *node)
{
    NODE * temp = NULL;

    while( node != NULL ) {
       temp = node->next;
       free( node->data );
       free( node );

       node = temp;
    }
}

Your main() function should return an exit code to the operating system of EXIT_SUCCESS or EXIT_FAILURE, instead of TRUE or 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文