说我有这个结构:
struct Book
{
int book_id;
struct Book *book_ptr;
};
/* navigation pointers */
struct Book *front;
struct Book *rear;
我想在我的记忆中添加一个新的Book
,所以我有这个功能:
void add_book() {
struct Book *temp;
temp = (struct Book*)malloc(sizeof(struct Book));
temp->book_id = t;
t++;
temp->book_ptr = NULL;
if (rear == NULL)
{
front = temp;
rear = temp;
}
else
{
rear->book_ptr = temp;
rear = temp;
}
}
如果我想要一个我的Books
列表:
void see_all_the_books()
{
struct Book *temp;
temp = front;
if (front == NULL)
{
printf("> YOU HAVEN'T ADDED ANY BOOK YET\n");
}
while (temp)
{
printf("Book #%d\n", temp->book_id);
temp = temp->book_ptr;
}
}
相当简单,而且有效。
但如果我不想使用链接列表该怎么办?我想做的是每次我正在制作新书时将rear
指针移动一个块。
然后我的结构将是这样的:
struct Book
{
int book_id;
};
/* navigation pointers */
struct Book *front;
struct Book *rear;
每次我想添加Book
:
void add_book() {
struct Book *temp;
temp = (struct Book*)malloc(sizeof(struct Book));
temp->book_id = t;
t++;
if (rear == NULL)
{
printf("Your FIRST book has been added\n");
front = temp;
rear = temp;
}
else
{
rear++; // MOVED TO NEXT BLOCK
rear = temp; // OBVIOUSLY WRONG
printf("ANOTHER book has been added\n");
}
}
我在上一段代码中需要更改哪些内容?
答案 0 :(得分:1)
您在struct Book
中分配新add_book
的方法引发了一些微妙的问题。这样做是没有错的,事实上它很常见,但你必须注意如何将所需的参数传递给add_book
。要在main()
中成功创建指针数组并使用add_book
为每个添加的新书分配,您必须将指针数组的地址传递给{{1}在需要更多指针的情况下处理重新分配。您还需要一种方法来传递和跟踪已分配的指针数和当前可用的最大指针数。因此add_book
的基本声明如下所示:
add_book
struct Book *add_book (struct Book ***book, int id, size_t *idx, size_t *nmax);
是***book
中声明的指针数组的地址,main()
是要分配给id
的新值,book_id
是要添加的idx
的当前索引和struct Book
是可填写的指针数。
注意:您正在向nmax
功能传递指向idx
和nmax
的指针。这允许您在add_book
中增加/更改其值,同时在add_book
中提供更新的值。 main()
的完整原型可能如下所示:
add_book
注意,因为您已将 struct Book *add_book (struct Book ***book, int id, size_t *idx, size_t *nmax)
{
if (!book || !*book) return NULL;
size_t n = *idx;
(*book)[*idx] = xcalloc (1, sizeof **book);
(*book)[*idx]-> book_id = id;
(*idx)++;
if (*idx == *nmax) { /* realloc if nmax reached, update nmax */
void *tmp = realloc (*book, *nmax * 2 * sizeof tmp);
if (!tmp) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
return NULL;
}
*book = tmp; /* use memset to initialize all new pointers NULL */
memset (*book + *nmax, 0, *nmax * sizeof tmp);
*nmax *= 2;
}
return (*book)[n];
}
的地址传递给该函数,因此您必须取消引用Book
(即Book
)在*book
中,以便正确使用指针数组。另请注意,add_book
只是一个错误检查函数,它调用xcalloc
以防止在测试每次分配calloc
的返回时使逻辑混乱。
Windows注意事项: Visual Studio中的编译器不知道calloc
只是返回函数名称的宏。因此,如果您使用visual studio编译代码,只需将__func__
替换为__func__
。
一个完整的例子将有所帮助。下面将所有部分组合在一起,以使用一组指针来保存您的"function name"
集合。注意:在下面的示例中,最大图书数定义为struct Book
,但8
被强制重新分配10 book_id
Book
时add_book
,*idx == *nmax
。
*idx & *nmax = 8
Sampe输入(10 int)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NBOOKS 8
struct Book {
int book_id;
};
void *xcalloc (size_t n, size_t s);
struct Book *add_book (struct Book ***book, int id, size_t *idx, size_t *nmax);
int main (void) {
size_t idx = 0;
size_t nbooks = 0;
size_t nmax = NBOOKS;
int id = 0;
struct Book **Book = NULL;
/* create NBOOKS pointers to struct Book */
Book = xcalloc (NBOOKS, sizeof *Book);
/* read integer input from stdin */
while (scanf ("%d", &id) == 1)
add_book (&Book, id, &idx, &nmax);
nbooks = idx; /* save the number of books added */
/* print the book_id for each book */
for (idx = 0; idx < nbooks; idx++)
printf (" Book[%2zu] : %d\n", idx, Book[idx]->book_id);
/* free all allocated memory */
for (idx = 0; idx < nbooks; idx++)
free (Book[idx]);
free (Book);
return 0;
}
/* add one struct Book to array of pointers to Book with book_id = 'id'
* NOTE: since you must protect against writing beyond the last pointer
* you must pass the ADDRESS OF Book (the reason for ***) in the event a
* realloc occurs. Otherwise the address of Book in main() will never
* reflect the reallocation. (pointers to idx and nmax are passed so their
* updated values are available in main() ).
*/
struct Book *add_book (struct Book ***book, int id, size_t *idx, size_t *nmax)
{
if (!book || !*book) return NULL;
size_t n = *idx;
(*book)[*idx] = xcalloc (1, sizeof **book);
(*book)[*idx]-> book_id = id;
(*idx)++;
if (*idx == *nmax) { /* realloc if nmax reached, update nmax */
void *tmp = realloc (*book, *nmax * 2 * sizeof tmp);
if (!tmp) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
return NULL;
}
*book = tmp; /* use memset to initialize all new pointers NULL */
memset (*book + *nmax, 0, *nmax * sizeof tmp);
*nmax *= 2;
}
return (*book)[n];
}
/** xcalloc allocates memory using calloc and validates the return.
* xcalloc allocates memory and reports an error if the value is
* null, returning a memory address only if the value is nonzero
* freeing the caller of validating within the body of code.
*/
void *xcalloc (size_t n, size_t s)
{
register void *memptr = calloc (n, s);
if (memptr == 0) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
return memptr;
}
<强>输出
$ cat dat/10int_nl.txt
8572
-2213
6434
16330
3034
12346
4855
16985
11250
1495
内存错误检查
$ ./bin/struct_book_simple <dat/10int_nl.txt
Book[ 0] : 8572
Book[ 1] : -2213
Book[ 2] : 6434
Book[ 3] : 16330
Book[ 4] : 3034
Book[ 5] : 12346
Book[ 6] : 4855
Book[ 7] : 16985
Book[ 8] : 11250
Book[ 9] : 1495
答案 1 :(得分:0)
您需要创建一个指针数组,每个指针都指向一本书。这将需要您的代码稍微改变,因为将不再需要前后。
int maxbooks = somenumber;
Struct book *books= malloc(maxbooks*sizeof(struct book));
int numbooks = 0;
addbook()
{
(books+numbooks)->book_id = t;
numbooks++;
}