C链表中的指针问题

时间:2019-02-13 16:49:15

标签: c

这是我的代码(在链接列表上工作):

typedef struct node {
   int data;
   struct node_t* next;
} node_t;

typedef struct list{
   node_t* head;
} list_t;

node_t* create_node(void){
   node_t* tmp = malloc(sizeof(node_t));
   if (tmp == NULL){
      fprintf(stderr, "Error while allocating memory for node\n");
      exit(EXIT_FAILURE);
   }
   return tmp;
}

void list_insert(list_t* list, node_t* node, int data){
   if (node == NULL){
      node_t* new = create_node();
      new->next = list->head;
      list->head = new;
      new->data = data;
   }
   else{
      node_t* current = list->head;
      while(current != node){
         current = current->next;
      }
      node_t* new = create_node();
      new->next = current->next;
      current->next = new;
      new->data = data;
   }
}

我在list_insert函数中确实得到了一些警告,但是我无法弄清它们的原因。如果作为参数传递的nodeNULL,则此函数应在开头插入一个新节点,否则应在作为参数传递的node之后插入一个新节点。

在此代码段中:

if (node == NULL){
   node_t* new = create_node();
   new->next = list->head;
   list->head = new;
   new->data = data;
}

分配new->next = list->head;不正确。有任何猜测吗?

2 个答案:

答案 0 :(得分:1)

在您对struct node的定义中:

typedef struct node {
        int data;
        struct node_t* next;
    } node_t;

您将next定义为指向struct node_t的指针,但是没有这种类型。您要struct node

typedef struct node {
        int data;
        struct node* next;
    } node_t;

答案 1 :(得分:1)

您不需要typedef struct list{ ...},只需要一个node_t *类型的变量,该变量始终包含列表的头,空时为NULL。

例如:

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

typedef struct node {
  int data;
  struct node * next;
} node_t;

node_t* create_node(int data)
{
  node_t* tmp = malloc(sizeof(node_t));

  if (tmp == NULL){
    fprintf(stderr, "Error while allocating memory for node\n");
    exit(EXIT_FAILURE);
  }
  tmp->data = data;
  tmp->next = NULL;
  return tmp;
}

void list_append(node_t ** l, node_t* node){
  if (*l == NULL) {
    *l = node;
  }
  else {
    while ((*l)->next != NULL)
      l = &(*l)->next;

    (*l)->next = node;
  }
}

/* l, *l, where and node must not be NULL */
int list_insert(node_t ** l, node_t* where, node_t* node) {
  if (*l != where) {
    for (;;) {
      if (*l == NULL)
        return 0;
      l = &(*l)->next;
      if (*l = where)
        break;
    }
  }

  node->next = *l;
  *l = node;
  return 1;
}

void pr(node_t * l)
{
  printf("list is :");
  while (l != NULL) {
    printf(" %d", l->data);
    l = l->next;
  }
  putchar('\n');
}

void clear(node_t ** head)
{
  node_t * l = *head;

  while (l != NULL) {
    node_t * n = l->next;
    free(l);
    l = n;
  }

  *head = NULL;
}

int main()
{
  node_t * head = NULL;
  node_t * n3 = create_node(3);

  list_append(&head, create_node(1));
  list_append(&head, n3);
  pr(head);

  list_insert(&head, n3, create_node(2));
  pr(head);  

  list_insert(&head, head, create_node(0));
  pr(head);

  clear(&head);
  pr(head);

  return 0;
}

我当时更改了创建内容以便能够提供数据,这一点更加清晰了(就像C ++中的构造函数一样)

编译和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
list is : 1 3
list is : 1 2 3
list is : 0 1 2 3
list is :
pi@raspberrypi:/tmp $ valgrind ./a.out
==27963== Memcheck, a memory error detector
==27963== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27963== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==27963== Command: ./a.out
==27963== 
list is : 1 3
list is : 1 2 3
list is : 0 1 2 3
list is :
==27963== 
==27963== HEAP SUMMARY:
==27963==     in use at exit: 0 bytes in 0 blocks
==27963==   total heap usage: 5 allocs, 5 frees, 1,056 bytes allocated
==27963== 
==27963== All heap blocks were freed -- no leaks are possible
==27963== 
==27963== For counts of detected and suppressed errors, rerun with: -v
==27963== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)