功能不保存数据

问题描述 投票:0回答:2

该功能应该将数据保存到结构指针的动态数组的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);
}
c pointers structure dynamic-memory-allocation
2个回答
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);

OT,我在menu功能中看到,您使用gets。危险,应改为使用fgets中的stdin。在此链接中查看Why is the gets function so dangerous that it should not be used?


0
投票

您的代码包含几个错误。

让我们从“ non-blocking”错误开始。即使那些可能非常关键并且必须纠正,但这些并不是您经历崩溃的真正原因。

    标准输入的刷新,fflush(stdin);。是标准未定义的内容,因此使用它会导致
  • undefined behavior

:在某些环境中它可以工作,在其他环境中它不能工作,并且在某些环境中(最坏的情况)它[[似乎起作用,但实际上是有害的。建议避免使用它。功能gets()是危险的,其使用should be avoided
  • 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));

    尽管可以设置为pass structures to functions as values,但不建议这样做。第一个原因是您将使进程的堆栈超载(整个结构将分配在堆栈区域中,这在PC应用程序中很大,但在嵌入式系统中非常有限)。第二个原因将给您带来功能问题。
      实际上,按值传递的参数是传递给函数的变量的
    1. 副本
    。这意味着对它们所做的任何更改都不会反映到原始结构中。在您的情况下,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; }

    © www.soinside.com 2019 - 2024. All rights reserved.