如何在结构中访问结构数组?

时间:2016-09-20 18:42:03

标签: 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_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

3 个答案:

答案 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_bookNULL。如下所示:

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)。