这个函数的作用是将数据保存到 library.books_count
结构指针的动态数组的实例。然而它并没有。一个类似的函数 addexistingBooks()
做得完美无缺。问题出在哪里?realloc()
?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char book_name[32];
char book_genre[32];
char author[32];
int page_count;
float price;
}Sbook;
typedef struct
{
char library_name[32];
Sbook * bookp;
int books_count;
}Slib;
void menu(char String[50]);
void addexistingBooks(Slib library, int i);
void addBook(Slib library, int i);
int main()
{
Slib library;
int i=0;
char Choice[30];
printf("Enter amount of books inside the library: ");
scanf("%d", &(library.books_count));
library.bookp = (Sbook *)calloc(library.books_count,sizeof (Sbook));
fflush(stdin);
addexistingBooks(library, i);
menu(Choice);
if(strcmp(Choice,"add")==0)
{
addBook(library, i);
}
free(library.bookp);
return 0;
}
void menu(char String[30])
{
printf("Welcome to the library. If you read about heresy, prepare to be purged \n");
printf("Please choose a command, by writing the appropriate command: \n");
printf("1. Write 'add' to add a book. \n");
printf("2. Write 'remove' to remove a book. \n");
printf("3. Write 'redact' to redact a book. \n");
printf("4. Write 'Sort by criteria' to sort the books, where criteria can stand for: 1.bookname, 2.author, 3.genre, 4.price. \n");
printf("Enter your command: ");
gets(String);
}
void addexistingBooks(Slib library, int i)
{
for(i=0;i<library.books_count;i++)
{
printf("Enter the name of the book: \n");
fgets(library.bookp[i].book_name,32,stdin);
printf("Enter the genre of the book: \n");
fgets(library.bookp[i].book_genre,32,stdin);
printf("Enter the author of the book: \n");
fgets(library.bookp[i].author,32,stdin);
printf("Enter the page count of the book: \n");
scanf("%d", &(library.bookp[i].page_count));
printf("Enter the price of the book: \n");
scanf("%f", &(library.bookp[i].price));
fflush(stdin);
}
}
void addBook(Slib library, int i)
{
(library.books_count)++;
realloc(library.bookp,library.books_count);
fflush(stdin);
if(library.bookp==NULL)
{
exit(1);
}
printf("Enter the name of the book: \n");
fgets(library.bookp[i].book_name,32,stdin);
printf("Enter the genre of the book: \n");
fgets(library.bookp[i].book_genre,32,stdin);
printf("Enter the author of the book: \n");
fgets(library.bookp[i].author,32,stdin);
printf("Enter the page count of the book: \n");
scanf("%d", &(library.bookp[i].page_count));
printf("Enter the price of the book: \n");
scanf("%f", &(library.bookp[i].price));
fflush(stdin);
}
你的代码包含几个错误。
让我们从以下几个方面入手 "无障碍" 的错误。那些,即使他们可以真正的批评和。不得不 被纠正,并不是你遇到的崩溃的真正原因。
fflush(stdin);
是标准没有定义的东西,所以使用它就会导致 未定义行为* 在某些环境中可以起作用,在另一些环境中则不能起作用,而且在某些环境中(最坏的环境)可能会起作用。看来 来工作,但其实它是有害的。建议避免使用。gets()
是危险的,因为它没有对用户插入的字符串的大小提供任何控制,而且它的用法是 应避免.void addBook()
功能您可以尝试使用以下方法增加可用空间 realloc
:
void *realloc(void *ptr, size_t size)。
它需要原始指针和新的大小。但你传递的是 library.books_count
那只是书的数量。意思是说,如果图书馆以前有4本书,你试着把它分配给 5个字节 仅仅是。
而您需要分配 library.books_count * sizeof(Sbook)
字节。
此外,它还返回一个新的指针。你需要把它分配给图书指针。
library.bookp = realloc(library.bookp, library.books_count * sizeof(Sbook));
main()
你初始化一个 i
变量,但你从来没有更新过它,因为你直接把书的数量存储在了 library.books_count
.然后你把它传给 addexistingBooks()
,而且这是多余的,因为你可以用 library.books_count
本身的循环,就像你实际做的那样。你可以使用它作为循环变量,但你不需要有这个参数。只要用
void addexistingBooks(Slib library, )
{
int i; /* If your C version is C99 or later, you can declare it in the loop itself */
for(i=0;i<library.books_count;i++)
{
/* Omissis */
}
}
最后你把它传给 addBook()
不仅仅是多余的(因为你可以简单地将新书存放在索引中。library.books_count-1
但它是积极有害的,因为你总是在更新索引0(因为参数 i
是0)。)
事实上,通过值传递的参数是 副本 的变量,这意味着对它们的任何改变都不会反映到原始结构中。这意味着对它们的任何改变都不会反映到原始结构中。在你的例子中,更新 library.bookp
指针在函数外部将不可用,导致了 (1) 原始结构指向一个无效的内存地址位置(成为一个 悬针), (2) 新分配的内存的泄漏,没有人能够做到这一点。free()
.
按地址传递结构,而不是使用 结构指针. addBook()
职能,考虑到 i
移除参数,将成为如下
void addBook(Slib *library)
{
int i = library->books_count;
(library->books_count)++;
library->bookp = realloc(library->bookp, library->books_count * sizeof(Sbook));
/* and so on... the value of 'i' is now library->books_count-1 */
}
/* Call from main */
int main()
{
Slib library;
/* Omissis */
menu(Choice);
if(strcmp(Choice,"add")==0)
{
addBook(&library, i);
}
free(library.bookp);
return 0;
}
定义 realloc
职能。
void *realloc(void *ptr, size_t size);
所以,你的 realloc
功能。
realloc(library.bookp,library.books_count);
应该改成:
library.bookp = realloc(library.bookp,sizeof(Sbook)*library.books_count);
加时赛,我看到在你的 menu
功能,您可以使用 gets
. 很危险的,你应该用 fgets
从 stdin
取而代之的是 请看这个链接 为什么get函数如此危险,不应该使用?