C语言图书管理系统问题:添加多本书后仅显示最后一本信息
问题分析与解决方案
你的图书管理系统添加多本后只显示最后一本,核心原因是所有图书记录都指向了同一块内存空间——每次添加时你都在覆盖同一个结构体变量的数据,而非为每本图书分配独立存储。
常见错误代码示例(对应你的问题)
假设你的代码类似这样:
#include <stdio.h> #include <string.h> typedef struct { char name[50]; char author[50]; float price; int pages; } Book; Book book; // 单个结构体变量,被重复覆盖 Book *books[100]; int count = 0; void addBook() { printf("书名:"); scanf("%s", book.name); printf("作者:"); scanf("%s", book.author); printf("价格:"); scanf("%f", &book.price); printf("页数:"); scanf("%d", &book.pages); books[count++] = &book; // 每次都存同一个地址 } void displayBooks() { for (int i = 0; i < count; i++) { printf("图书%d:%s | %s | %.2f | %d\n", i+1, books[i]->name, books[i]->author, books[i]->price, books[i]->pages); } } int main() { addBook(); addBook(); displayBooks(); return 0; }
这里book是全局/局部的单个变量,每次调用addBook都会覆盖它的内容,books数组里存的都是同一个&book地址,所以显示时所有条目都指向最后一次输入的数据。
两种修正方案
方案1:使用固定大小的结构体数组(适合已知最大图书数量的场景)
直接用数组存储每本图书的结构体,每本图书占用独立的数组元素:
#include <stdio.h> #include <string.h> #define MAX_BOOKS 100 // 设定最大存储数量 typedef struct { char name[50]; char author[50]; float price; int pages; } Book; Book books[MAX_BOOKS]; int count = 0; void addBook() { if (count >= MAX_BOOKS) { printf("已达最大存储上限,无法添加新图书\n"); return; } printf("书名:"); scanf("%s", books[count].name); printf("作者:"); scanf("%s", books[count].author); printf("价格:"); scanf("%f", &books[count].price); printf("页数:"); scanf("%d", &books[count].pages); count++; // 计数加1,下一本存在下一个数组位置 } void displayBooks() { for (int i = 0; i < count; i++) { printf("图书%d:%s | %s | %.2f | %d\n", i+1, books[i].name, books[i].author, books[i].price, books[i].pages); } } int main() { addBook(); addBook(); displayBooks(); return 0; }
方案2:使用动态内存分配(适合不确定最大数量的场景)
通过malloc为每本图书分配独立内存,再用realloc扩展存储指针的数组:
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { char name[50]; char author[50]; float price; int pages; } Book; Book **books = NULL; // 存储图书指针的动态数组 int count = 0; void addBook() { // 为新图书分配内存 Book *newBook = (Book*)malloc(sizeof(Book)); if (!newBook) { printf("内存分配失败,无法添加图书\n"); return; } printf("书名:"); scanf("%s", newBook->name); printf("作者:"); scanf("%s", newBook->author); printf("价格:"); scanf("%f", &newBook->price); printf("页数:"); scanf("%d", &newBook->pages); // 扩展指针数组的容量 Book **temp = (Book**)realloc(books, (count + 1) * sizeof(Book*)); if (!temp) { printf("数组扩容失败,已释放当前图书内存\n"); free(newBook); return; } books = temp; books[count++] = newBook; } void displayBooks() { for (int i = 0; i < count; i++) { printf("图书%d:%s | %s | %.2f | %d\n", i+1, books[i]->name, books[i]->author, books[i]->price, books[i]->pages); } } // 记得释放动态分配的内存,避免泄漏 void freeBooks() { for (int i = 0; i < count; i++) { free(books[i]); } free(books); } int main() { addBook(); addBook(); displayBooks(); freeBooks(); return 0; }
核心要点
- 每本图书必须拥有独立的内存空间,不能复用同一个结构体变量
- 固定数组实现简单,适合场景明确的情况;动态分配更灵活,但需要注意内存释放
- 调试时可以打印每个图书记录的地址,确认是否指向不同内存区域
内容的提问来源于stack exchange,提问作者Omar Ahmed
相关产品推荐
相关产品推荐

