我有以下两种结构:
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);
~~~~~~~~~~~~~~~~~~~~~~~~~~^ ~~~~~
编辑:我从Book *array[50];
删除指针后,我现在收到此错误:
error: incomplete definition of type 'struct book'
(s->array[s->num_books-1])->title = strdup(new_title);
~~~~~~~~~~~~~~~~~~~~~~~~~~^
我认为这是一个问题,主要无法看到书籍结构,所以我停止使用头文件并将所有内容放在一个文件中,但这没有帮助。
我还认为我没有正确初始化堆栈。
当我尝试在create_stack函数中初始化数组时,如下所示:
s->array = malloc(sizeof(BookPtr) * 50); //inside create_array function
这是我得到的错误:
array type 'BookPtr *[50]' is not assignable
答案 0 :(得分:2)
您已将Book
定义为指针到struct book
然后您正在定义类型为Book
的指针数组,这意味着它是一个数组指向指针指向struct book
。
将Book
定义为struct book
或从数组定义中的Book
之后删除指针。通常是前者,因为您没有将其明确命名为BookPtr
。
答案 1 :(得分:1)
目前还不清楚你是否解决了这个问题,所以也许一个简短的例子会有所帮助。无论您是在array
开始为X个书籍创建存储空间,还是创建array
作为一个X指针书籍的数组,您都需要一些方法来确保您不会添加更多书籍。你可以存储。处理此问题的显而易见的方法是向stack
结构中添加一个额外变量,以跟踪array
中的存储(或指针数量),然后realloc
array
需要。要跟踪array
可用的空间,您只需添加另一个计数器,例如max_books
,例如
enum { NBOOKS = 10 };
typedef struct {
char *title;
int pages;
} book;
typedef struct {
int num_books,
max_books;
book *array;
} stack;
由于当您只是为每本书创建存储时,将array
声明为指针数组没有任何好处,您也可以将数组声明为{{ 1}}并为一些合理预期的书籍数量分配存储空间。您的book *array;
并不遥远,但我会create_stack
略有不同,以便根据需要创建目标add_book
和NULL
。如下所示:
realloc
( note :关于为什么将堆栈作为/** 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
示例使用/输出
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { NBOOKS = 10 };
typedef struct {
char *title;
int pages;
} book;
typedef struct {
int num_books,
max_books;
book *array;
} stack;
stack *create_stack ();
book *add_book (stack **s, char *title, int pages);
void prn_stack (stack *s);
void free_stack (stack *s);
int main (void) {
stack *s1 = NULL; /* always initialize your pointers */
add_book (&s1, "Huck Finn", 631);
add_book (&s1, "Tom Sawyer", 582);
add_book (&s1, "The Quick Brown Fox", 1);
prn_stack (s1);
free_stack (s1);
return 0;
}
/** allocate stack and allocate storage for NBOOKS books */
stack *create_stack ()
{
stack *s = calloc (1, sizeof *s);
if (!s) {
fprintf (stderr, "error: virtual memory exhausted - stack.\n");
exit (EXIT_FAILURE);
}
s->array = calloc (NBOOKS, sizeof *(s->array));
if (!s->array) {
fprintf (stderr, "error: virtual memory exhausted - array.\n");
exit (EXIT_FAILURE);
}
s->num_books = 0;
s->max_books = NBOOKS;
return s;
}
/** 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]);
}
void prn_stack (stack *s)
{
if (!s) return;
printf ("\nThere are %d books in the stack:\n\n", s->num_books);
for (int i = 0; i < s->num_books; i++)
printf (" %2d. %-20s (%3d pages)\n", i, s->array[i].title, s->array[i].pages);
putchar ('\n');
}
void free_stack (stack *s)
{
if (!s) return;
for (int i = 0; i < s->num_books; i++)
free (s->array[i].title);
free (s->array);
free (s);
}
内存使用/错误检查
将$ ./bin/bookstack
There are 3 books in the stack:
0. Huck Finn (631 pages)
1. Tom Sawyer (582 pages)
2. The Quick Brown Fox ( 1 pages)
设置为NBOOKS
以强制重新分配并使用2
进行检查,您会发现:
valgrind
它应该是怎样的。仔细看看,如果您有任何问题,请告诉我。
答案 2 :(得分:0)
我无法发表评论,因此我将阐述David C. Rankin的评论。你对数组的定义不会起作用。
你可能应该使用以下其中一种......
这会为您提供一系列最多可容纳50本书籍的书籍:
Book array[50];
这为您提供了一个指向Book数组的指针,该数组没有大小限制,但需要更多开销。
Book *array;
如果您使用后者,则必须创建阵列,跟踪其当前长度,并在填充后将其放大(请参阅https://linux.die.net/man/3/realloc)。