目前还不清楚你是否解决了这个问题,所以也许一个简短的例子会有所帮助。无论您是在开始时在 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 声明为 指针数组 没有任何好处,因此您不妨将数组声明为 book *array; 和为一些合理预期的书籍分配存储空间。你的create_stack 离我不远了,但我会做add_book 有点不同,以便根据需要创建堆栈,如果它当前是NULL 和realloc。类似于以下内容:
/** 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]);
}
(note:关于为什么堆栈以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 TO 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)
应该是这样的。如果您有任何问题,请查看并告诉我。