You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 09:48:16