C 如何访问结构中的结构数组?

C 如何访问结构中的结构数组?,c,arrays,struct,stack,C,Arrays,Struct,Stack,我有以下两种结构: typedef struct stack * StackPtr; typedef struct book * BookPtr; struct book { char *title; int pages; }; struct stack { int num_books; Book array[50] // changed from Book *array[50] }; 以下是我初始化每个结构的方式: StackPtr create_stac

我有以下两种结构:

typedef struct stack * StackPtr;
typedef struct book * BookPtr;

struct book {
    char *title;
    int pages;
};

struct stack {
    int num_books;
    Book array[50] // changed from Book *array[50]
};
以下是我初始化每个结构的方式:

StackPtr create_stack(void) {
    StackPtr s = malloc(sizeof(struct stack));
    s->num_books = 0;
    return s;
}

BookPtr create_book(char *title, int pages) {
    BookPtr b = malloc(sizeof(struct book));
    b->title = strdup(title);
    b->pages = pages;
    return b;
}
我正在尝试使用堆栈结构中的数组访问该书的标题和页面。我就是这样做的:

例如,如果我想访问和修改结构中最后一本书的标题和页面,我可以这样做:

(s->array[s->num_books-1])->title = strdup(new_title);
(s->array[s->num_books-1])->pages = new_pages;
但是,我遇到了以下错误:

error: member reference base type 'Book' (aka 'struct book *') is not a structure or union
        (s->array[s->num_books-1])->title = strdup(new_title);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^ ~~~~~
error: incomplete definition of type 'struct book'
        (s->array[s->num_books-1])->title = strdup(new_title);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^

编辑:在我从
Book*数组[50]中删除指针之后我现在遇到此错误:

error: member reference base type 'Book' (aka 'struct book *') is not a structure or union
        (s->array[s->num_books-1])->title = strdup(new_title);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^ ~~~~~
error: incomplete definition of type 'struct book'
        (s->array[s->num_books-1])->title = strdup(new_title);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^
我认为这是因为main无法查看书籍结构的问题,所以我停止使用头文件,将所有内容都放在一个文件中,但这没有帮助

我还认为我没有正确初始化堆栈

当我尝试在create_stack函数中初始化数组时,如下所示:

s->array = malloc(sizeof(BookPtr) * 50); //inside create_array function
这是我得到的错误:

array type 'BookPtr *[50]' is not assignable

您已经将
Book
定义为指向
struct Book
的指针,然后定义了
Book
类型的指针数组,这意味着它是指向
struct Book
的指针数组


在数组定义中将
Book
定义为
struct Book
,或者从
Book
之后删除指针。通常是前者,因为您没有清楚地将其命名为
BookPtr

我无法评论,因此我将详细阐述大卫·C·兰金的评论。你对数组的定义不起作用

您可能应该使用以下选项之一

这将为您提供最多可容纳50本书的书籍阵列:

Book array[50];
这将为您提供一个指向书籍数组的指针,该数组没有大小限制,但需要更多开销

Book *array;

如果使用后者,则必须创建阵列,跟踪其当前长度,并在填充后使其变大(请参见)。

目前尚不清楚是否解决了此问题,因此也许一个简短的示例会有所帮助。无论您是在开始时为
array
中的X个图书创建存储,还是将
array
创建为指向图书的X个指针数组,您都需要某种方法来确保添加的图书不会超过存储量。处理这一问题的明显方法是向
堆栈
结构添加一个附加变量,用于跟踪
数组
中的存储(或可用指针数),然后根据需要添加
realloc
数组
。要跟踪可用的
数组中的空间,只需添加另一个计数器,例如
max\u books
,即可

enum { NBOOKS = 10 };

typedef struct {
    char *title;
    int pages;
} book;

typedef struct {
    int num_books,
        max_books;
    book *array;
} stack;
由于在为每本书创建存储时,将
数组
声明为指针数组没有任何好处,因此您也可以将数组声明为
book*array并为开始时合理预期的图书数量分配存储空间。您的
create_stack
已经不远了,但是如果当前
NULL
realloc
是需要的,我会做一些不同的
add_book
来创建堆栈。如下所示:

/** since add_book may create the stack, you must pass the address
 *  of the stack to add_book so that any changes to s are available
 *  back in the calling funciton.
 */
book *add_book (stack **s, char *title, int pages)
{
    if (!title) return NULL;        /* validate title */
    if (!*s) *s = create_stack ();  /* if stack NULL, create */

    /* check num_books against max_books and realloc as required */
    if ((*s)->num_books == (*s)->max_books) {
        void *tmp = realloc ((*s)->array, ((*s)->max_books + NBOOKS) * 
                            sizeof *((*s)->array));
        if (!tmp) {
            fprintf (stderr, "error: memory exhausted - realloc array.\n");
            return NULL;
        }
        (*s)->array = tmp;
        (*s)->max_books += NBOOKS;
    }

    /* allocate/copy title, assign pages, increment num_books */
    (*s)->array[(*s)->num_books].title = strdup (title);
    (*s)->array[(*s)->num_books].pages = pages;
    ((*s)->num_books)++;

    /* change return as desired, I just return the address of the book
     * to indicate success and provide a way to validate the add.
     */
    return &((*s)->array[(*s)->num_books - 1]);
}
(注意:关于堆栈作为
stack**
传递给函数的原因的注释)

这些基本上就是创建一堆书所需的更改,这些更改允许您添加任意数量的书(直到耗尽计算机内存)。将示例放在一起,您可以执行如下操作(注意:常量
NBOOKS
必须大于零,您可以添加支票以确保)

内存使用/错误检查

NBOOKS
设置为
2
以强制重新分配并使用
valgrind
进行检查,您将发现:

$ valgrind ./bin/bookstack
==15521== Memcheck, a memory error detector
==15521== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15521== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==15521== Command: ./bin/bookstack
==15521==

There are 3 books in the stack:

   0.  Huck Finn             (631 pages)
   1.  Tom Sawyer            (582 pages)
   2.  The Quick Brown Fox   (  1 pages)

==15521==
==15521== HEAP SUMMARY:
==15521==     in use at exit: 0 bytes in 0 blocks
==15521==   total heap usage: 6 allocs, 6 frees, 153 bytes allocated
==15521==
==15521== All heap blocks were freed -- no leaks are possible
==15521==
==15521== For counts of detected and suppressed errors, rerun with: -v
==15521== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

应该是这样的。仔细检查一下,如果有任何问题,请告诉我。

Book*array[50]创建指向book 50而非50 struct book的指针数组。
typedef struct stack*stack
是一种误导性的
typedef
。使用
typedef结构堆栈
typedef结构堆栈*StackPtr
@David你能详细说明一下吗?当然,如果你想创建一个包含50个struct book的数组,请使用
book array[50],然后您将访问类似于
s->book[i]的内容。标题
。如果您创建一个指向struct book的未初始化指针数组(例如
book*数组[50];
),则必须为每个指针分配内存,然后才能将值分配给成员等(可以这样做,您只需管理每个书的内存分配)决不能
typedef
指针!我这样做了,但是我在这一行得到了类型“structbook”的不完整定义:
(s->array[s->num_books-1])->title=strdup(title)我不明白。您是否可以编辑原始帖子以添加新代码而不删除原始代码?