C语言 链表产生警告的函数

qzlgjiam  于 2023-08-03  发布在  其他
关注(0)|答案(4)|浏览(90)

在循环单链表的开头插入节点的函数产生错误:[Warning] assignment from incompatible pointer type在第21行。
这是什么意思,我该如何修复它?

#include <stdio.h>
#include <stdlib.h>
struct Node
{
    int info;
    struct node *next;
};
typedef struct Node node;
node *head = NULL;
node *tail = NULL;

void insertAtBeginning()
{
    int i;
    node *temp = head;
    node *NewPtr = NULL;
    NewPtr = (node *)malloc(sizeof(node));
    printf("\nEnter a value\n");
    scanf("%d", &i);
    NewPtr -> info = i;
    NewPtr -> next = NewPtr;                 //Line 21
    if(head == NULL)
    {
        head = NewPtr;
        NewPtr-> next = NewPtr;
    }
    else
    {
        while(temp -> next != head)
        {
            temp = temp->next;
        }
        NewPtr -> next = head;
        temp -> next = NewPtr;
        head = NewPtr;
    }
}

字符串

fkaflof6

fkaflof61#

您混合了类型和typedefstruct node不存在,但您尝试在struct Node定义中使用它。
要解决这个问题,您可以将nodetypedef * 放在struct Node的实际定义 * 之前,并在任何地方使用node(而不是struct node,因为它不存在)。

typedef struct Node node;

struct Node
{
    int info;
    node *next; // note: node, not struct node
};

字符串

pbpqsu0x

pbpqsu0x2#

您在结构声明中有一个拼写错误

struct Node
{
    int info;
    struct node *next;
};

字符串
结构的标记名称为Node。所以在这个结构中你要写

struct Node *next;


代替了

struct node *next;


否则这条线

struct node *next;


引入了一个新的不完整类型说明符struct node
但是在任何情况下,函数insertAtBeginning的定义都是无效的。该函数完全忘记了在文件作用域中声明的指针tail和指针head

node *head = NULL;
node *tail = NULL;


该函数可以如下所示

int insertAtBeginning( void )
{
    node *NewPtr = malloc( sizeof( node ) );
    int success = NewPtr != NULL;

    if ( success )
    {
        int i;

        printf( "\nEnter a value: " );
        scanf( "%d", &i );

        NewPtr -> info = i;

        if ( head == NULL )
        {
            NewPtr -> next = NewPtr;
            tail = NewPtr;
        }
        else
        {
            NewPtr -> next = head;
            tail->next = NewPtr;
        }

        head = NewPtr;
    }

    return success;
}


请注意,除了使用文件作用域指针headtail之外,还可以声明一个结构,如

struct List
{
    struct Node *head;
    struct Node *tail;
};


并在main中声明一个结构类型的对象,如

struct List list = { .head = NULL, .tail = NULL };


因为当函数依赖于全局变量时,这是一种糟糕的方法,而这是可以避免的。
同样,函数的调用者应该传递一个将被添加到列表中的值。
在这种情况下,函数将如下所示

int insertAtBeginning( struct List *list, int info )
{
    node *NewPtr = malloc( sizeof( node ) );
    int success = NewPtr != NULL;

    if ( success )
    {
        NewPtr -> info = info;

        if ( list->head == NULL )
        {
            NewPtr -> next = NewPtr;
            list->tail = NewPtr;
        }
        else
        {
            NewPtr -> next = list->head;
            list->tail->next = NewPtr;
        }
        list->head = NewPtr;
    }

    return success;
}


在main中调用函数

int info;

printf( "\nEnter a value: " );
scanf( "%d", &info );

insertAtBeginning( &list, info );

ahy6op9u

ahy6op9u3#

struct Node
{
    int info;
    struct node *next;
};
typedef struct Node node;

字符串
这是错误的。尚未定义struct node。只有struct Node

这样就可以了:

struct Node
{
    int          info;
    struct Node* next;
};

typedef struct Node node;


因为struct Node是已知的,所以可以将next声明为struct Node*

也可以:

typedef struct Node node;


struct Node
{
    int   info;
    node* next;
};


这里的nodestruct Node,因此可以将next声明为node*

注意事项

有点跑题了,但是考虑到你正在创建一个链表。列表是节点的列表。节点不是列表。如果你把节点当作一个列表来写代码,你会有额外的工作,代码的意义也会减少。

示例

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

typedef int Info;  // here we have a list of int

// this is a Node
typedef struct st_node
{
    Info            info;
    struct st_node* next;
} Node;

// this is a List of Nodes
typedef struct
{
    Node*  head;
    Node*  tail;
    size_t size;
} List;

List* list_create();  // returns a pointer to a new List
List* list_delete(List*);  // destroy List and returns NULL
int   insert_b(
      Info*, List*);       // Insert an element into a List


这样我们就不需要全局变量headtail,代码可以管理任何列表。
每个节点都包含一个Info对象,它可以是任何对象,因此在声明Node之前的typedef可以将Info转换为任何对象,如

typedef int Info;  // here we have a list of int


所以我们有一个int列表。
而且insert接收一个指向元素的指针和一个指向List的指针,所以很容易在同一段代码中管理多个列表。

C示例

int main(void)
{
    List* my_list = list_create();
    Info  my_item = 12;
    insert_b(&my_item, my_list);
    for (Info i = 0; i < 1000; i += 1)
        insert_b(&my_item, my_list);
    my_list = list_delete(my_list);
    return 0;
}


上面的代码创建了一个列表,并在其中插入了1001个元素。并且每次调用时都不等待用户输入值。

gopyfrb3

gopyfrb34#

嘿试试这个代码是优化。

#include <stdio.h>
    #include <stdlib.h>
    struct node
     {
      int data;
       struct node *next;
    }*tail;

     void insertAtBeginning()
     {
     struct node *newnode;
     newnode=(struct node *)malloc(sizeof(struct node));
       printf("enter data:");
      scanf("%d",&newnode->data);
     newnode->next=0;
   if(tail==0){
    tail=newnode;
   tail->next=newnode;

   }
   else{
   newnode->next=tail->next;
   tail->next=newnode;
    }

字符串
}

相关问题