如何用C语言结构体实现可动态添加图书的图书馆系统
动态藏书图书馆系统实现方案
问题原因
把结构体里的固定长度books[10]数组改成book*指针后代码运行失败,核心原因是这个指针没有被分配合法的堆内存,初始状态是未初始化的野指针,直接执行l->books[l->noBooks] = *b属于非法内存写入,会直接触发段错误。
动态扩容的核心逻辑是在添加图书时按需申请/扩大内存空间,不需要提前预知总藏书量。
具体实现代码
1. 修改library头文件
新增容量记录字段、初始化和销毁接口,避免野指针和内存泄漏:
// library.h #ifndef _LIBRARY_ #define _LIBRARY_ #include "book.h" typedef struct { int noBooks; // 当前实际存书数量 int capacity; // 当前已分配内存可容纳的最大图书数 book* books; // 指向动态分配的图书数组 } library; void initLibrary(library* l); void destroyLibrary(library* l); void addBook(book* b, library* l); #endif
2. 实现library对应的逻辑
采用经典的倍增扩容策略:初始给一个小容量,存满后把容量翻倍再重新申请内存,减少内存重分配的频次,保证添加操作的效率。
// library.c #include "library.h" // 初始可容纳2本图书,后续存满自动翻倍扩容 #define INIT_CAPACITY 2 void initLibrary(library* l) { l->noBooks = 0; l->capacity = INIT_CAPACITY; // 申请初始容量的堆内存 l->books = (book*)malloc(sizeof(book) * l->capacity); } void destroyLibrary(library* l) { // 释放动态申请的内存,避免泄漏 free(l->books); l->books = NULL; l->noBooks = 0; l->capacity = 0; } void addBook(book* b, library* l) { // 剩余容量不足时先扩容 if (l->noBooks >= l->capacity) { l->capacity *= 2; l->books = (book*)realloc(l->books, sizeof(book) * l->capacity); } l->books[l->noBooks] = *b; l->noBooks++; }
3. 修正原有代码的笔误并调整调用逻辑
原有代码里有两个小笔误需要修正:
book.h里#include <stdio.h>末尾多了一个多余的.,会触发编译警告main.cpp里给b2设置id的时候误写为b1.id = 2,会导致b2的id未初始化
调整后的main代码:
//main.cpp #include<iostream> extern "C" { #include "book.h" #include "library.h" } int main() { std::cout << "Start" << std::endl; book b1; strcpy_s(b1.author, "Ab"); b1.id = 1; strcpy_s(b1.title, "Ab"); book b2; strcpy_s(b2.author, "Df"); b2.id = 2; // 修正原笔误 strcpy_s(b2.title, "Df"); library l1; initLibrary(&l1); // 使用前必须先初始化,申请合法内存 addBook(&b1, &l1); addBook(&b2, &l1); std::cout << l1.books[0].author << "\n"; std::cout << l1.books[1].author; destroyLibrary(&l1); // 用完释放内存 return 0; }
补充说明
- 上述示例为了代码简洁省略了
malloc/realloc的返回值判空,正式使用时需要判断返回值是否为NULL,处理内存分配失败的异常场景 - 倍增扩容的策略可以保证添加图书的均摊时间复杂度为O(1),效率远高于每添加一本书就重新分配一次内存的方案
- 所有通过
malloc/realloc申请的堆内存,必须在不用时调用free释放,否则会造成内存泄漏
内容的提问来源于stack exchange,提问作者user19536537
相关产品推荐
相关产品推荐

