C语言图书管理系统实验报告如何实现核心功能?

99ANYc3cd6
预计阅读时长 46 分钟
位置: 首页 C语言 正文

C语言图书管理系统实验报告

实验名称 C语言图书管理系统设计与实现 实验日期 2025年10月27日
学生姓名 [你的姓名] 学 号 [你的学号]
指导教师 [教师姓名] 班 级 [你的班级]

实验目的

  1. 巩固C语言基础知识:熟练掌握C语言的基本语法,包括数据类型、运算符、流程控制语句(if-else, switch, for, while)等。
  2. 掌握核心数据结构:深入理解和应用结构体(struct)来组织复杂数据,并熟练运用文件指针(FILE*)进行数据的持久化存储与读取。
  3. 提升模块化编程能力:学习将一个复杂系统分解为若干个功能独立、逻辑清晰的函数,实现高内聚、低耦合的代码结构。
  4. 培养问题分析与解决能力:通过设计并实现一个完整的图书管理系统,锻炼从需求分析、系统设计到编码实现、测试调试的全过程能力。
  5. 理解用户交互设计:学习设计简单、友式的命令行用户界面,提升程序的可用性。

实验环境

  • 硬件环境:Intel Core i5 处理器, 8GB 内存
  • 软件环境
    • 操作系统:Windows 11
    • 开发工具:Visual Studio Code 1.85
    • 编译器:MinGW-w64 (GCC 13.2.0)
    • 终端:Windows Terminal

需求分析

本系统旨在模拟一个小型图书馆的日常图书管理操作,根据基本需求,系统需要具备以下核心功能:

  1. 图书信息录入:能够将新图书的信息(如ISBN、书名、作者、库存数量)添加到系统中。
  2. 图书信息浏览:能够以列表形式展示系统中所有图书的详细信息。
  3. 图书信息查询:提供多种查询方式,如按ISBN、按书名、按作者进行精确或模糊查询。
  4. 图书信息修改:能够根据ISBN查找到特定图书,并修改其信息(如书名、作者、库存等)。
  5. 图书信息删除:能够根据ISBN从系统中删除某本图书。
  6. 数据持久化:系统的图书数据需要保存在文件中,确保程序关闭后再次打开时,数据依然存在。

系统设计

1 功能模块设计

根据需求分析,将系统划分为以下几个主要功能模块,每个模块由一个或多个函数实现。

模块名称 功能描述 主要函数
主菜单模块 显示系统主菜单,接收用户输入并调用相应功能模块。 main()
录入模块 添加新图书信息到内存和文件中。 addBook()
浏览模块 显示所有图书的详细信息。 displayAllBooks()
查询模块 提供多种查询方式并显示结果。 searchBook()
修改模块 根据ISBN查找并修改图书信息。 modifyBook()
删除模块 根据ISBN查找并删除图书。 deleteBook()
文件操作模块 负责程序启动时从文件加载数据,退出时保存数据到文件。 loadData(), saveData()

2 数据结构设计

为了存储图书信息,设计一个名为 Book 的结构体类型。

// 图书信息结构体
typedef struct {
    char isbn[20];      // ISBN编号,作为唯一标识
    char title[100];    // 书名
    char author[50];    // 作者
    int quantity;       // 库存数量
} Book;

3 文件存储设计

为了实现数据持久化,使用文本文件 books.dat 来存储所有图书信息,文件格式采用每行存储一本图书的信息,字段之间用逗号()分隔,

978-7-111-54321-0,C Primer Plus,Stephen Prata,15
978-7-302-12345-6,C程序设计,谭浩强,30
978-7-115-67890-1,数据结构,严蔚敏,20

详细设计与实现

1 核心函数设计

  1. *`void addBook(Book books[], int count)`**

    • 功能:向 books 数组中添加一本新书。
    • 实现:提示用户输入图书的ISBN、书名、作者和库存,首先检查ISBN是否已存在,若存在则提示更新库存;若不存在,则将新书信息追加到数组末尾,并更新图书总数 *count,最后调用 saveData() 保存到文件。
  2. void displayAllBooks(Book books[], int count)

    • 功能:以表格形式展示所有图书。
    • 实现:首先打印表头(如“序号”、“ISBN”、“书名”、“作者”、“库存”),然后遍历 books 数组,逐行打印每本图书的信息。count 为0,则提示“图书馆为空”。
  3. void searchBook(Book books[], int count)

    • 功能:提供菜单,让用户选择按ISBN、书名或作者进行查询。
    • 实现:内部定义 searchByIsbn(), searchByTitle(), searchByAuthor() 三个子函数,主函数接收用户选择,并调用相应的子函数,查询逻辑为遍历数组,进行字符串比较(strcmp)。
  4. void modifyBook(Book books[], int count)

    • 功能:根据ISBN修改图书信息。
    • 实现:提示用户输入要修改的ISBN,遍历数组查找,若找到,提示用户输入新的书名、作者和库存,并更新该图书的结构体成员,如果未找到,则提示“未找到该图书”,修改成功后调用 saveData()
  5. *`void deleteBook(Book books[], int count)`**

    • 功能:根据ISBN删除图书。
    • 实现:提示用户输入要删除的ISBN,遍历数组查找,若找到,将该图书之后的所有图书向前移动一位,覆盖掉要删除的图书,然后将图书总数 *count 减1,如果未找到,则提示“未找到该图书”,删除成功后调用 saveData()
  6. *`void loadData(Book books[], int count)`**

    • 功能:程序启动时从 books.dat 文件加载数据。
    • 实现:以读模式("r")打开文件,使用 fscanf 逐行读取文件内容,将解析出的数据存入 books 数组,并更新 *count,如果文件不存在,则不执行任何操作(首次运行)。
  7. void saveData(Book books[], int count)

    • 功能:将内存中的图书数据保存到 books.dat 文件。
    • 实现:以写模式("w")打开文件(会清空原文件内容),遍历 books 数组,使用 fprintf 将每本图书的信息按预定格式写入文件,最后关闭文件。

2 主程序流程图

graph TD
    A[开始] --> B{程序启动};
    B --> C[loadData()];
    C --> D[显示主菜单];
    D --> E{用户输入选择};
    E -- 1. 录入 --> F[addBook()];
    E -- 2. 浏览 --> G[displayAllBooks()];
    E -- 3. 查询 --> H[searchBook()];
    E -- 4. 修改 --> I[modifyBook()];
    E -- 5. 删除 --> J[deleteBook()];
    E -- 0. 退出 --> K[saveData()];
    K --> L[显示“感谢使用”];
    L --> M[结束];
    F --> D;
    G --> D;
    H --> D;
    I --> D;
    J --> D;

系统测试

为了验证系统的正确性和稳定性,设计了以下测试用例。

测试编号 测试步骤 预期结果 实际结果 是否通过
TC-01 启动程序。 显示“图书馆为空”或空列表。 显示“图书馆为空”。 通过
TC-02 选择“1. 录入图书”。
输入ISBN: 978-7-111-12345-6, 书名: C语言, 作者: 作者A, 库存: 10。
提示“添加成功!”,在浏览列表中能看到新添加的图书。 提示“添加成功!”,浏览列表显示新图书。 通过
TC-03 重复TC-02,输入相同的ISBN。 提示“该图书已存在,是否更新库存?”,选择“是”后库存相加。 提示“该图书已存在,是否更新库存?”,输入“Y”后库存变为20。 通过
TC-04 选择“3. 查询图书”。
选择“2. 按书名查询”。
输入: C语言。
显示所有书名为“C语言”的图书信息。 正确显示“C语言”这本书的信息。 通过
TC-05 选择“4. 修改图书”。
输入ISBN: 978-7-111-12345-6。
修改作者为“作者B”。
提示“修改成功!”,再次查询该书,作者已更新为“作者B”。 提示“修改成功!”,查询结果确认作者已更新。 通过
TC-06 选择“5. 删除图书”。
输入ISBN: 978-7-111-12345-6。
提示“删除成功!”,再次浏览,该书已不存在。 提示“删除成功!”,浏览列表中已无该书。 通过
TC-07 选择“5. 删除图书”。
输入一个不存在的ISBN。
提示“未找到该图书,删除失败!”。 提示“未找到该图书,删除失败!”。 通过
TC-08 完成所有操作后,选择“0. 退出”。
重新启动程序。
程序退出后重新启动,之前添加、修改的图书数据依然存在。 数据成功恢复,与退出前一致。 通过

实验总结与心得

通过本次实验,我成功地设计并实现了一个功能完善的C语言图书管理系统,在实践过程中,我获得了以下几点收获与体会:

  1. 理论与实践的结合:本次实验将课堂上学习的C语言理论知识,如结构体、文件操作、函数等,应用于解决一个实际问题,极大地加深了我对这些知识点的理解和记忆。
  2. 模块化编程的重要性:将系统划分为多个功能模块,使得代码结构清晰,易于编写、阅读和维护,所有文件操作都集中在 loadDatasaveData 函数中,当需要修改存储格式时,只需改动这两个函数,而不会影响其他业务逻辑。
  3. 细节决定成败:在编码过程中,许多细节需要特别注意,
    • 边界条件:数组访问时防止越界,文件打开失败时的处理。
    • 数据唯一性:在添加和修改时,确保ISBN的唯一性是关键。
    • 用户体验:提供清晰的菜单和提示信息,能让用户更方便地使用程序。
  4. 调试能力的提升:在实现查询、删除等功能时,遇到了一些逻辑错误,例如删除图书后数组元素没有正确前移,导致数据错乱,通过使用 printf 进行打印调试,逐步定位并解决了问题,这锻炼了我的调试和排错能力。

存在的不足与展望

  • 功能扩展性:当前系统功能相对基础,未来可以增加借阅、归还、用户管理等功能,使其成为一个更完整的图书馆管理系统。
  • 数据结构优化:对于图书数量巨大的情况,使用线性查找效率较低,未来可以引入链表或哈希表等更高效的数据结构来优化查询、插入和删除操作。
  • 界面美化:当前是纯命令行界面,可以增加颜色、进度条等,使界面更美观。

本次实验是一次宝贵的实践经历,不仅巩固了我的C语言编程技能,也培养了我分析问题、设计解决方案和动手实现的综合能力。


核心代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_BOOKS 1000
#define FILENAME "books.dat"
// 图书信息结构体
typedef struct {
    char isbn[20];
    char title[100];
    char author[50];
    int quantity;
} Book;
// 函数声明
void showMenu();
void addBook(Book books[], int *count);
void displayAllBooks(Book books[], int count);
void searchBook(Book books[], int count);
void modifyBook(Book books[], int count);
void deleteBook(Book books[], int *count);
void loadData(Book books[], int *count);
void saveData(Book books[], int count);
int main() {
    Book books[MAX_BOOKS];
    int bookCount = 0;
    int choice;
    // 启动时加载数据
    loadData(books, &bookCount);
    do {
        showMenu();
        printf("请输入您的选择: ");
        scanf("%d", &choice);
        while (getchar() != '\n'); // 清空输入缓冲区
        switch (choice) {
            case 1:
                addBook(books, &bookCount);
                break;
            case 2:
                displayAllBooks(books, bookCount);
                break;
            case 3:
                searchBook(books, bookCount);
                break;
            case 4:
                modifyBook(books, bookCount);
                break;
            case 5:
                deleteBook(books, &bookCount);
                break;
            case 0:
                printf("正在保存数据并退出系统...\n");
                saveData(books, bookCount);
                printf("感谢使用,再见!\n");
                break;
            default:
                printf("无效的选择,请重新输入!\n");
        }
    } while (choice != 0);
    return 0;
}
// 显示主菜单
void showMenu() {
    printf("\n========== 图书馆管理系统 ==========\n");
    printf("  1. 录入图书\n");
    printf("  2. 浏览图书\n");
    printf("  3. 查询图书\n");
    printf("  4. 修改图书\n");
    printf("  5. 删除图书\n");
    printf("  0. 退出系统\n");
    printf("====================================\n");
}
// 录入图书
void addBook(Book books[], int *count) {
    if (*count >= MAX_BOOKS) {
        printf("图书馆已满,无法添加更多图书!\n");
        return;
    }
    Book newBook;
    printf("请输入ISBN: ");
    scanf("%19s", newBook.isbn);
    while (getchar() != '\n'); // 清空输入缓冲区
    // 检查ISBN是否已存在
    for (int i = 0; i < *count; i++) {
        if (strcmp(books[i].isbn, newBook.isbn) == 0) {
            printf("该图书已存在,是否更新库存?(y/n): ");
            char ch;
            scanf(" %c", &ch);
            if (ch == 'y' || ch == 'Y') {
                printf("请输入增加的库存数量: ");
                int addQty;
                scanf("%d", &addQty);
                books[i].quantity += addQty;
                printf("库存更新成功!\n");
                saveData(books, *count);
            }
            return;
        }
    }
    printf("请输入书名: ");
    fgets(newBook.title, sizeof(newBook.title), stdin);
    newBook.title[strcspn(newBook.title, "\n")] = 0; // 去除换行符
    printf("请输入作者: ");
    fgets(newBook.author, sizeof(newBook.author), stdin);
    newBook.author[strcspn(newBook.author, "\n")] = 0;
    printf("请输入库存数量: ");
    scanf("%d", &newBook.quantity);
    books[*count] = newBook;
    (*count)++;
    printf("图书添加成功!\n");
    saveData(books, *count);
}
// 浏览所有图书
void displayAllBooks(Book books[], int count) {
    if (count == 0) {
        printf("图书馆为空,没有图书可显示,\n");
        return;
    }
    printf("\n%-5s %-20s %-30s %-20s %-10s\n", "序号", "ISBN", "书名", "作者", "库存");
    printf("--------------------------------------------------------------------------------\n");
    for (int i = 0; i < count; i++) {
        printf("%-5d %-20s %-30s %-20s %-10d\n", i + 1, books[i].isbn, books[i].title, books[i].author, books[i].quantity);
    }
}
// 查询图书 (示例:实现按ISBN查询)
void searchBook(Book books[], int count) {
    if (count == 0) {
        printf("图书馆为空,无法查询,\n");
        return;
    }
    printf("请输入要查询的ISBN: ");
    char isbn[20];
    scanf("%19s", isbn);
    int found = 0;
    printf("\n查询结果:\n");
    printf("%-20s %-30s %-20s %-10s\n", "ISBN", "书名", "作者", "库存");
    printf("------------------------------------------------------------\n");
    for (int i = 0; i < count; i++) {
        if (strstr(books[i].isbn, isbn) != NULL) { // 模糊查询
            printf("%-20s %-30s %-20s %-10d\n", books[i].isbn, books[i].title, books[i].author, books[i].quantity);
            found = 1;
        }
    }
    if (!found) {
        printf("未找到ISBN包含 \"%s\" 的图书,\n", isbn);
    }
}
// 修改图书
void modifyBook(Book books[], int count) {
    if (count == 0) {
        printf("图书馆为空,无法修改,\n");
        return;
    }
    printf("请输入要修改的图书ISBN: ");
    char isbn[20];
    scanf("%19s", isbn);
    for (int i = 0; i < count; i++) {
        if (strcmp(books[i].isbn, isbn) == 0) {
            printf("找到图书,请输入新的信息:\n");
            printf("请输入新书名: ");
            fgets(books[i].title, sizeof(books[i].title), stdin);
            books[i].title[strcspn(books[i].title, "\n")] = 0;
            printf("请输入新作者: ");
            fgets(books[i].author, sizeof(books[i].author), stdin);
            books[i].author[strcspn(books[i].author, "\n")] = 0;
            printf("请输入新库存数量: ");
            scanf("%d", &books[i].quantity);
            printf("图书信息修改成功!\n");
            saveData(books, count);
            return;
        }
    }
    printf("未找到ISBN为 \"%s\" 的图书,\n", isbn);
}
// 删除图书
void deleteBook(Book books[], int *count) {
    if (*count == 0) {
        printf("图书馆为空,无法删除,\n");
        return;
    }
    printf("请输入要删除的图书ISBN: ");
    char isbn[20];
    scanf("%19s", isbn);
    for (int i = 0; i < *count; i++) {
        if (strcmp(books[i].isbn, isbn) == 0) {
            // 将后面的元素前移
            for (int j = i; j < *count - 1; j++) {
                books[j] = books[j + 1];
            }
            (*count)--;
            printf("图书删除成功!\n");
            saveData(books, *count);
            return;
        }
    }
    printf("未找到ISBN为 \"%s\" 的图书,\n", isbn);
}
// 从文件加载数据
void loadData(Book books[], int *count) {
    FILE *fp = fopen(FILENAME, "r");
    if (fp == NULL) {
        // 文件不存在,首次运行
        return;
    }
    *count = 0;
    while (fscanf(fp, "%19[^,],%99[^,],%49[^,],%d\n", books[*count].isbn, books[*count].title, books[*count].author, &books[*count].quantity) == 4) {
        (*count)++;
        if (*count >= MAX_BOOKS) break;
    }
    fclose(fp);
}
// 保存数据到文件
void saveData(Book books[], int count) {
    FILE *fp = fopen(FILENAME, "w");
    if (fp == NULL) {
        printf("错误:无法打开文件进行保存!\n");
        return;
    }
    for (int i = 0; i < count; i++) {
        fprintf(fp, "%s,%s,%s,%d\n", books[i].isbn, books[i].title, books[i].author, books[i].quantity);
    }
    fclose(fp);
}
-- 展开阅读全文 --
头像
织梦手机版文章列表页如何实现?
« 上一篇 03-04
stm8s的c语言编程例程
下一篇 » 03-04

相关文章

取消
微信二维码
支付宝二维码

目录[+]