1

这不是程序的最终实现,但程序本身有点长,所以我决定改为以小块的形式创建它。我遇到了一个错误,上面写着

函数 list_first 的隐式声明。

还有其他错误需要解决,但我想先获得一些帮助,然后自己处理其余的错误,尽管如果你愿意,欢迎你提供额外的帮助。这是代码:

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

// The type for a node in the list.
struct node
{
    struct node *next;
    struct node *prev;
    char *value;
};

// The type for a list.
typedef struct list
{
    struct node head;
} List;

// The type for a list position.
typedef struct list_pos
{
    struct node *node;
} ListPos;

List *list_create(void)
{
  List *lst = (List*)malloc(sizeof(List));
  if(lst == NULL)
  {
    printf("No more memory!\n");
  }

  return lst;
}

static struct node *make_node(const char *value)
{
  struct node *result = malloc(sizeof(struct node));
  result->value = strdup(value);
  result -> next = NULL;
  result -> prev = NULL;
  return result;
}
static void add_values(List *lst)
{
    ListPos pos = list_first(lst);
    pos = list_insert(pos, "Apple");
    pos = list_next(pos);
    pos = list_insert(pos, "Banana");
    pos = list_next(pos);
    pos = list_insert(pos, "Citrus");
}

ListPos list_end(List *lst)
{
    ListPos pos = {
        .node = &lst->head
    };
    return pos;
}

ListPos list_first(List *lst)
{
    ListPos pos = {
        .node = lst->head.next
    };
    return pos;
}
ListPos list_next(ListPos pos)
{
  struct node* node;

  //pos = node -> next;
  struct node *before = pos.node->prev;
  struct node *after = pos.node;

   node->next = after;
   after->prev = node;

  pos.node = node;
    return pos;
}
ListPos list_insert(ListPos pos, const char *value)
{
    // Create a new node.
    struct node *node = make_node(value);

    // Find nodes before and after (may be the same node: the head of the list).
    struct node *before = pos.node->prev;
    struct node *after = pos.node;

    // Link to node after.
    node->next = after;
    after->prev = node;

    // Link to node before.
    node->prev = before;
    before->next = node;

    // Return the position of the new element.
    pos.node = node;
    return pos;
}


int main(void)
{

    // Create an empty list.

      List *lst = list_create();
      add_values(lst);
    return 0;
}
4

3 回答 3

1

在函数中add_values

static void add_values(List *lst)
{
    ListPos pos = list_first(lst);
    //..

调用list_first尚未声明的函数。

您需要在函数list_first中使用它之前放置函数的声明add_values

例如

ListPos list_first(List *lst);

static void add_values(List *lst)
{
    ListPos pos = list_first(lst);
    //..

注意这个声明

typedef struct list
{
    struct node head;
} List;

没有多大意义。您应该使用列表的以下声明

typedef struct list
{
    struct node *head;
    struct node *tail;
} List;

该函数list_create不初始化动态分配对象的数据成员。

所以其他函数,例如list_first调用未定义的行为访问未初始化的数据成员head,如在此声明中

ListPos pos = {
    .node = lst->head.next
};
于 2022-01-24T18:56:16.707 回答
0

它必须是函数的原型或函数定义本身,位于使用函数的行之前。在你指定的函数和其他函数的 typedef 声明之后添加原型定义。

于 2022-01-24T18:54:25.943 回答
0

函数 list_first 的隐式声明。

这意味着编译器已经看到一个名为 的函数调用list_first,但是您(或您在编译单元中使用的包含文件)没有提供该函数的接口(它返回的类型,或传递给它)在旧 C 中,这是允许的,假设默认情况下(这可能太大胆了)该函数返回一个int值并采用此原型定义的未定义参数列表(这可能不是正确的):

int list_first();

因此,您可能需要在头文件(如果该函数是由您编写的)中为该函数提供正确的定义,并#include在源文件中提供正确的定义,或者只是#include在给出函数定义的文件中。

旧版本的标准允许这样做,编译器中显示了上面显示的默认行为,但标准的最新版本禁止它(好吧,如果你编写了函数,为什么不包含一个头文件来告诉编译器如何使用它?或者如果你没有,为什么让编译器猜测并且不提供正确的接口?)

于 2022-01-24T21:12:17.463 回答