该功能应该将数据保存到结构指针的动态数组的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);
}
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);
OT,我在menu
功能中看到,您使用gets
。危险,应改为使用fgets
中的stdin
。在此链接中查看Why is the gets function so dangerous that it should not be used?
您的代码包含几个错误。
让我们从“ non-blocking”错误开始。即使那些可能非常关键并且必须纠正,但这些并不是您经历崩溃的真正原因。标准输入的刷新,
fflush(stdin);
。是标准未定义的内容,因此使用它会导致
gets()
是危险的,其使用should be avoided。void addBook()
功能中的问题realloc
增加可用空间:它需要原始指针和新大小。但是,您通过的library.books_count
仅是书籍的数量。这意味着,如果该库过去包含4本书,则尝试分配
5个字节。
您需要分配library.books_count * sizeof(Sbook)
字节。
library.bookp = realloc(library.bookp, library.books_count * sizeof(Sbook));
尽管可以设置为pass structures to functions as values,但不建议这样做。第一个原因是您将使进程的堆栈超载(整个结构将分配在堆栈区域中,这在PC应用程序中很大,但在嵌入式系统中非常有限)。第二个原因将给您带来功能问题。
library.bookp
指针的更新将在函数外部不可用,从而导致(1)指向无效内存地址位置的原始结构(2)新分配的内存泄漏,没有人能够free()
。通过地址传递结构,而使用指向结构的指针
:void addBook(Slib *library, int i)
{
(library->books_count)++;
library->bookp = realloc(library->bookp, library->books_count * sizeof(Sbook));
/* and so on... */
}
/* Call from main */
int main()
{
Slib library;
/* Omissis */
menu(Choice);
if(strcmp(Choice,"add")==0)
{
addBook(&library, i);
}
free(library.bookp);
return 0;
}