MST

星途 面试题库

面试题:C语言结构体与回调函数的内存管理及高级应用

设计一个系统,用于管理图书馆的书籍。定义一个结构体 `struct Book`,包含书名(动态分配的字符数组)、作者(动态分配的字符数组)、出版年份(整数)和借阅状态(布尔值)。再定义一个结构体 `struct Library`,包含一个 `struct Book` 类型的指针数组(初始大小为10,可动态扩容),以及当前书籍数量。编写一个函数 `addBook`,用于向图书馆中添加一本新书,包括动态分配书名和作者的内存。编写一个回调函数 `searchBookByAuthor`,用于在图书馆中查找指定作者的所有书籍,并返回这些书籍的信息。编写一个函数 `removeBook`,用于从图书馆中移除一本指定书名的书,同时正确释放相关内存。最后,编写一个函数 `resizeLibrary`,当图书馆书籍数量达到数组容量时,使用回调函数 `reallocateBooks` 对 `struct Library` 中的书籍数组进行动态扩容,确保系统的内存管理高效且无内存泄漏。请详细说明你的设计思路,并编写完整的代码实现。
40.1万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 结构体定义
    • struct Book 结构体用于存储每本书的信息,包括书名、作者、出版年份和借阅状态。书名和作者使用动态分配的字符数组,以便适应不同长度的字符串。
    • struct Library 结构体用于管理图书馆的书籍,包含一个 struct Book 类型的指针数组和当前书籍数量。数组初始大小为10,可动态扩容。
  2. 函数实现
    • addBook 函数负责向图书馆添加新书。在添加新书时,为书名和作者动态分配内存,并将新书信息添加到图书馆的书籍数组中。如果书籍数量达到数组容量,调用 resizeLibrary 函数进行扩容。
    • searchBookByAuthor 回调函数用于在图书馆中查找指定作者的所有书籍,并返回这些书籍的信息。通过遍历图书馆的书籍数组,比较作者名字符串来实现查找。
    • removeBook 函数用于从图书馆中移除指定书名的书。找到该书后,释放书名和作者的内存,将数组中后续书籍向前移动,更新书籍数量。
    • resizeLibrary 函数在书籍数量达到数组容量时调用 reallocateBooks 回调函数对书籍数组进行动态扩容。reallocateBooks 函数负责重新分配内存并复制原数组内容。

代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义Book结构体
struct Book {
    char *title;
    char *author;
    int year;
    int isBorrowed;
};

// 定义Library结构体
struct Library {
    struct Book **books;
    int capacity;
    int count;
};

// 初始化图书馆
struct Library* createLibrary() {
    struct Library *library = (struct Library*)malloc(sizeof(struct Library));
    library->capacity = 10;
    library->count = 0;
    library->books = (struct Book**)malloc(library->capacity * sizeof(struct Book*));
    return library;
}

// 向图书馆添加新书
void addBook(struct Library *library, const char *title, const char *author, int year, int isBorrowed) {
    if (library->count == library->capacity) {
        resizeLibrary(library);
    }
    struct Book *newBook = (struct Book*)malloc(sizeof(struct Book));
    newBook->title = (char*)malloc(strlen(title) + 1);
    newBook->author = (char*)malloc(strlen(author) + 1);
    strcpy(newBook->title, title);
    strcpy(newBook->author, author);
    newBook->year = year;
    newBook->isBorrowed = isBorrowed;
    library->books[library->count++] = newBook;
}

// 查找指定作者的所有书籍
struct Book** searchBookByAuthor(struct Library *library, const char *author, int *resultCount) {
    int count = 0;
    for (int i = 0; i < library->count; i++) {
        if (strcmp(library->books[i]->author, author) == 0) {
            count++;
        }
    }
    struct Book **result = (struct Book**)malloc(count * sizeof(struct Book*));
    int index = 0;
    for (int i = 0; i < library->count; i++) {
        if (strcmp(library->books[i]->author, author) == 0) {
            result[index++] = library->books[i];
        }
    }
    *resultCount = count;
    return result;
}

// 从图书馆移除指定书名的书
void removeBook(struct Library *library, const char *title) {
    for (int i = 0; i < library->count; i++) {
        if (strcmp(library->books[i]->title, title) == 0) {
            free(library->books[i]->title);
            free(library->books[i]->author);
            free(library->books[i]);
            for (int j = i; j < library->count - 1; j++) {
                library->books[j] = library->books[j + 1];
            }
            library->count--;
            break;
        }
    }
}

// 动态扩容图书馆书籍数组的回调函数
void reallocateBooks(struct Library *library) {
    library->capacity *= 2;
    struct Book **newBooks = (struct Book**)malloc(library->capacity * sizeof(struct Book*));
    for (int i = 0; i < library->count; i++) {
        newBooks[i] = library->books[i];
    }
    free(library->books);
    library->books = newBooks;
}

// 动态扩容图书馆
void resizeLibrary(struct Library *library) {
    reallocateBooks(library);
}

// 释放图书馆内存
void freeLibrary(struct Library *library) {
    for (int i = 0; i < library->count; i++) {
        free(library->books[i]->title);
        free(library->books[i]->author);
        free(library->books[i]);
    }
    free(library->books);
    free(library);
}

int main() {
    struct Library *library = createLibrary();
    addBook(library, "C Programming Language", "Brian W. Kernighan", 1988, 0);
    addBook(library, "The Mythical Man - Month", "Frederick P. Brooks Jr.", 1975, 0);
    int resultCount;
    struct Book **result = searchBookByAuthor(library, "Brian W. Kernighan", &resultCount);
    for (int i = 0; i < resultCount; i++) {
        printf("Title: %s, Author: %s, Year: %d, Borrowed: %s\n", result[i]->title, result[i]->author, result[i]->year, result[i]->isBorrowed? "Yes" : "No");
    }
    free(result);
    removeBook(library, "C Programming Language");
    freeLibrary(library);
    return 0;
}