【问题标题】:assignment from incompatible pointer type in linked list (C)链表中不兼容指针类型的赋值 (C)
【发布时间】:2012-03-13 22:19:04
【问题描述】:

我在创建链接列表以及我正在尝试创建的一些辅助函数时遇到了一些问题。我的代码如下:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "getNextWord.h"

#define MAX_WORD_SIZE 256

typedef struct{
int counter;
char* key;
struct node* next;
} node;

node* createNode(char* words){
    node* head;
    if(!(head=malloc(sizeof(node)))) return NULL;
    head->key=words;
    head->next=NULL;
    return head;
}

node* addToList(node* head, char* words){
    node* newNode;
    newNode=createNode(words);
    newNode->next = head;
    return newNode;
}

int find(node* head){
    if (head->next != NULL){
        node* next = head->next;

        while(head != NULL){
            if (strcmp(head->key,next->key)==0){
                head->counter++;
                head=head->next;
                return 1;
                }
            else{
                head=head->next;
                }
            }
    }
return 0;
}

void printList(node* head){
    node* pointer = head;
    while (pointer != NULL){
        printf("%s",pointer->key);
        pointer=pointer->next;
        }
    printf("\n");
}

int main(int argc, char* argv[]){

    if(argc<2){
        fprintf(stderr, "Not enough arguments given\n");
        }

    for(int i=1; i< argc; i++){
        FILE* fd=fopen(argv[i], "r");
        if(fd != NULL){
            char* words;
            node* head = NULL;
            while((words=getNextWord(fd)) != NULL){
                find(head);
                if (find(head) == 0){
                    createNode(words);
                    }
                printList(head);


                fprintf(stdout,"%s\n",words);
                }
            }

        else(printf("No such file exists"));
        fclose(fd);
        }
return 0;
}

我在 Internet 上环顾四周,似乎我正在关注大多数人在链表方面所做的事情。我之前没有收到任何错误,只是在以下函数中出现了一堆“警告:来自不兼容指针类型的赋值”:

addtolist (the line before the return)
find (before return one and the else line)
printlist (the last line in the while loop)

我知道代码不是很好,我不是最好的程序员,但我只是在努力学习。另外,我的 getnextword 确实有效,但如果需要它,我也可以发布它。

【问题讨论】:

    标签: c linked-list nodes traversal


    【解决方案1】:

    您正在混合两个不同的“命名空间”,struct 的“标签”命名空间和类似的命名空间以及 typedef 的标识符命名空间。最容易处理的是转发声明您将要使用的类型:

    typedef struct node node;
    

    然后您可以交替使用nodestruct node。甚至在里面

    struct node {
      // something
      node * next;
    };
    

    【讨论】:

    • 如果你说我不应该将事物命名为 node* node 那么这是有道理的。我将它们命名为 node* 其他东西(显然不完全是那个),那是我没有收到任何错误但仍然收到警告的时候,这在我的第一个 find 语句中以分段错误结束,现在这很有意义 -> next 在那一点上是 NULL 并且它应该崩溃。我可以把它改回来,把我的第一篇文章编辑成我以前的样子。
    • 另外,node*struct node* 是两个不同的东西,除非你让它们不是这里描述的两个不同的东西。
    【解决方案2】:
    typedef struct tag_node {
        int counter;
        char* key;
        struct tag_node* next;
    } node;
    

    对于初学者。

    顺便说一句,我无法想象你在main 中如何free() words(小心,它可能会泄漏)。

    编辑 - 我不小心有些样式

    【讨论】:

    • 这个消除了我收到的警告,但没有消除错误。我认为如果使用 typdef,你不需要在 struct 之后有一个名字,就在最后。但话又说回来,我对这一切都很陌生,很容易出错。
    【解决方案3】:

    试试这个:

    struct node {
      int counter;
      char* key;
      struct node* next;
    };
    

    您可能需要在代码中的其他位置将node 替换为struct node

    【讨论】:

    • 我不是每次都必须在“节点”前面添加“结构”吗?我认为这就是 typedef 的用途,因此您不必每次想要某种对您正在制作的内容的某种引用时都编写 struct。
    • @Defc0n - 是的,正如我在上一行中所说的那样。这是风格问题,一些程序员更喜欢typedef,其他人觉得它使代码更难阅读。它不是宏,因此它的行为与简单的文本替换略有不同。
    • 是的,我第一次阅读时似乎错过了那行。在我的辩护中,我只睡了大约 3 个小时。我摆脱了我遇到的错误,现在我只需要处理警告。
    【解决方案4】:

    多个问题:

    int find(node* node){
        node* next = node->next;  // what if next is NULL ?
        while(node != NULL){
            if (strcmp(node->key,next->key)==0){ // if next is NULL this will crash
                node->counter++;
                return 1;
                node=node->next;   // never reached since return 1 above.
                }
            else{
                node=node->next;
                }
        }
    return 0;
    }
    

    ....

    将 createlist 重命名为 createnode 可能很好,因为这似乎是函数。

    node* createList(char* words){
        node* node;
        if(!(node=malloc(sizeof(node)))) return NULL;
        node->key=words;
        node->next=NULL;
        return node;
    }
    

    'words' 中的字符串永远不会被存储,您需要创建单词的副本并存储它,例如:

    node->key = strdup(words);
    

    【讨论】:

    • 我的 getnextword 函数(我没有包含)确实已经对单词进行了 strdup。这仍然是必要的,还是会为同一件事分配内存两次?是的,在我做的地方返回 1 是愚蠢的错误,而不是在那里思考。另外,对于那里的第一个错误,我可以添加一个简单的 if (node->next != NULL) 然后该语句正确吗?
    猜你喜欢
    • 2021-06-07
    • 2019-08-09
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    相关资源
    最近更新 更多