图书信息管理系统 - C语言设计方案
项目概述与目标
本项目旨在设计并实现一个基于C语言的、命令行界面的图书信息管理系统,系统应能对图书信息(如书名、作者、ISBN、库存数量等)进行高效的增、删、改、查操作,并能将数据持久化存储到文件中,以便在程序关闭后重新打开时数据依然存在。

(图片来源网络,侵删)
核心目标:
- 数据管理:实现对图书信息的结构化存储和管理。
- 基本操作:提供添加、删除、修改、查询图书的核心功能。
- 用户交互:提供清晰、友好的命令行菜单界面。
- 数据持久化:将图书数据保存到文件,实现数据的长期存储。
- 代码结构:采用模块化设计,使代码清晰、易于维护和扩展。
功能分析
系统应具备以下主要功能:
- 主菜单:作为系统入口,提供所有功能的选项。
- 添加图书:允许用户输入新图书的信息(书名、作者、ISBN、库存),并将其保存到系统中。
- 删除图书:通过ISBN号或书名查找图书,并将其从系统中移除。
- 修改图书信息:通过ISBN号或书名查找图书,并允许用户修改其任意字段(如书名、作者、库存)。
- 查询图书:
- 按ISBN查询:精确查找特定ISBN的图书。
- 按书名查询:模糊查找包含关键字的图书。
- 按作者查询:模糊查找包含关键字的图书。
- 显示所有图书:以列表形式展示系统中所有图书的信息。
- 数据保存与加载:
- 保存:将当前系统中的所有图书信息写入到文件(如
books.dat)。 - 加载:程序启动时,自动从文件中读取已有的图书信息,恢复到系统中。
- 保存:将当前系统中的所有图书信息写入到文件(如
- 退出系统:在退出前,自动保存所有数据,并释放内存。
系统设计
数据结构设计
使用 struct(结构体)来定义图书的数据模型。
// 图书信息结构体
typedef struct {
char title[100]; // 书名
char author[50]; // 作者
char isbn[20]; // ISBN号,作为唯一标识
int stock; // 库存数量
} Book;
核心数据结构
为了高效地管理图书,特别是通过ISBN进行快速查找,我们选择链表作为核心数据结构。

(图片来源网络,侵删)
- 优点:
- 动态大小:可以随时添加或删除图书,无需预先定义数组大小。
- 灵活性高:内存按需分配,不会造成浪费。
- 缺点:
查询速度相对较慢(对于大数据量而言,但对于本课程设计完全足够)。
// 图书链表节点
typedef struct BookNode {
Book book; // 图书数据
struct BookNode *next; // 指向下一个节点的指针
} BookNode;
// 定义链表头指针
BookNode *bookList = NULL;
函数模块设计
将功能分解为独立的函数,每个函数负责一个具体的任务,提高代码的可读性和复用性。
| 函数类别 | 函数名 | 功能描述 |
|---|---|---|
| 主控模块 | main() |
程序入口,显示主菜单,调用其他功能函数 |
| 文件操作 | saveBooksToFile() |
将链表中的所有图书数据保存到文件 |
loadBooksFromFile() |
从文件中读取数据并加载到链表 | |
| 核心功能 | addBook() |
添加一本新图书到链表 |
deleteBook() |
从链表中删除指定ISBN的图书 | |
modifyBook() |
修改链表中指定ISBN的图书信息 | |
findBook() |
查询并显示图书信息 | |
displayAllBooks() |
显示链表中所有图书的信息 | |
| 辅助功能 | showMenu() |
显示系统主菜单 |
getInput() |
获取用户输入的选项 | |
freeBookList() |
释放链表占用的全部内存 |
核心代码实现
下面是关键部分的C语言代码实现。
头文件与结构体定义 (library.h)
// library.h
#ifndef LIBRARY_H
#define LIBRARY_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// 图书信息结构体
typedef struct {
char title[100];
char author[50];
char isbn[20];
int stock;
} Book;
// 图书链表节点
typedef struct BookNode {
Book book;
struct BookNode *next;
} BookNode;
// 函数声明
void showMenu();
void addBook(BookNode **head);
void deleteBook(BookNode **head);
void modifyBook(BookNode *head);
void findBook(BookNode *head);
void displayAllBooks(BookNode *head);
void saveBooksToFile(BookNode *head, const char *filename);
void loadBooksFromFile(BookNode **head, const char *filename);
void freeBookList(BookNode *head);
#endif // LIBRARY_H
主函数与菜单 (main.c)
// main.c
#include "library.h"
int main() {
BookNode *bookList = NULL;
loadBooksFromFile(&bookList, "books.dat"); // 启动时加载数据
int choice;
do {
showMenu();
printf("请输入您的选择: ");
scanf("%d", &choice);
getchar(); // 清除输入缓冲区中的换行符
switch (choice) {
case 1:
addBook(&bookList);
break;
case 2:
deleteBook(&bookList);
break;
case 3:
modifyBook(bookList);
break;
case 4:
findBook(bookList);
break;
case 5:
displayAllBooks(bookList);
break;
case 0:
saveBooksToFile(bookList, "books.dat"); // 退出前保存数据
freeBookList(bookList); // 释放内存
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");
}
核心功能函数实现 (functions.c)
// functions.c
#include "library.h"
// 添加图书
void addBook(BookNode **head) {
Book newBook;
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("请输入ISBN: ");
fgets(newBook.isbn, sizeof(newBook.isbn), stdin);
newBook.isbn[strcspn(newBook.isbn, "\n")] = 0;
printf("请输入库存数量: ");
scanf("%d", &newBook.stock);
getchar();
// 创建新节点
BookNode *newNode = (BookNode *)malloc(sizeof(BookNode));
if (newNode == NULL) {
printf("内存分配失败!\n");
return;
}
newNode->book = newBook;
newNode->next = NULL;
// 插入到链表头部
newNode->next = *head;
*head = newNode;
printf("图书添加成功!\n");
}
// 删除图书
void deleteBook(BookNode **head) {
char isbn[20];
printf("请输入要删除的图书ISBN: ");
fgets(isbn, sizeof(isbn), stdin);
isbn[strcspn(isbn, "\n")] = 0;
BookNode *current = *head;
BookNode *prev = NULL;
while (current != NULL && strcmp(current->book.isbn, isbn) != 0) {
prev = current;
current = current->next;
}
if (current == NULL) {
printf("未找到ISBN为 %s 的图书,\n", isbn);
return;
}
if (prev == NULL) {
// 删除的是头节点
*head = current->next;
} else {
// 删除的是中间或尾部节点
prev->next = current->next;
}
free(current);
printf("图书删除成功!\n");
}
// 查询图书 (示例:按ISBN查询)
void findBook(BookNode *head) {
char isbn[20];
printf("请输入要查询的图书ISBN: ");
fgets(isbn, sizeof(isbn), stdin);
isbn[strcspn(isbn, "\n")] = 0;
BookNode *current = head;
while (current != NULL) {
if (strcmp(current->book.isbn, isbn) == 0) {
printf("\n--- 找到图书 ---\n");
printf("书名: %s\n", current->book.title);
printf("作者: %s\n", current->book.author);
printf("ISBN: %s\n", current->book.isbn);
printf("库存: %d\n", current->book.stock);
printf("-----------------\n");
return;
}
current = current->next;
}
printf("未找到ISBN为 %s 的图书,\n", isbn);
}
// 显示所有图书
void displayAllBooks(BookNode *head) {
if (head == NULL) {
printf("当前系统中没有图书,\n");
return;
}
printf("\n--- 所有图书列表 ---\n");
BookNode *current = head;
int i = 1;
while (current != NULL) {
printf("图书 #%d\n", i++);
printf(" 书名: %s\n", current->book.title);
printf(" 作者: %s\n", current->book.author);
printf(" ISBN: %s\n", current->book.isbn);
printf(" 库存: %d\n", current->book.stock);
printf("--------------------\n");
current = current->next;
}
}
// 保存图书到文件
void saveBooksToFile(BookNode *head, const char *filename) {
FILE *file = fopen(filename, "wb"); // "wb" 表示二进制写入
if (file == NULL) {
printf("无法打开文件 %s 进行写入,\n", filename);
return;
}
BookNode *current = head;
while (current != NULL) {
fwrite(&(current->book), sizeof(Book), 1, file);
current = current->next;
}
fclose(file);
printf("数据已成功保存到 %s,\n", filename);
}
// 从文件加载图书
void loadBooksFromFile(BookNode **head, const char *filename) {
FILE *file = fopen(filename, "rb"); // "rb" 表示二进制读取
if (file == NULL) {
printf("文件 %s 不存在或无法打开,将创建新数据库,\n", filename);
return;
}
Book tempBook;
while (fread(&tempBook, sizeof(Book), 1, file) == 1) {
BookNode *newNode = (BookNode *)malloc(sizeof(BookNode));
if (newNode == NULL) {
printf("内存分配失败,加载中断,\n");
break;
}
newNode->book = tempBook;
newNode->next = *head;
*head = newNode;
}
fclose(file);
printf("数据已从 %s 成功加载,\n", filename);
}
// 释放链表内存
void freeBookList(BookNode *head) {
BookNode *current = head;
while (current != NULL) {
BookNode *temp = current;
current = current->next;
free(temp);
}
}
编译与运行
- 保存文件:将上述代码分别保存为
library.h,main.c,functions.c。 - 编译:使用GCC编译器将所有源文件链接成一个可执行文件。
gcc main.c functions.c -o library_system
- 运行:
./library_system
扩展与优化建议
如果你想让这个项目更加完善,可以考虑以下扩展方向:

(图片来源网络,侵删)
-
改进查询功能:
- 实现按书名或作者的模糊查询(使用
strstr函数)。 - 创建一个二级菜单,让用户选择查询方式(按ISBN、按书名、按作者)。
- 实现按书名或作者的模糊查询(使用
-
增加排序功能:
- 实现按书名或ISBN对图书列表进行排序(可以使用冒泡排序或插入排序等算法)。
-
增强用户输入验证:
- 检查ISBN是否已存在(添加时)。
- 确保库存数量为正数。
- 防止输入过长导致缓冲区溢出。
-
使用更高级的数据结构:
- 对于大量数据,可以使用哈希表来存储图书,以ISBN为键,可以实现O(1)时间复杂度的查找。
- 使用平衡二叉搜索树(如AVL树)可以同时实现高效的查找、插入和排序。
-
图形用户界面:
如果想挑战更高难度,可以使用GTK+、Qt或EasyX等库为系统添加图形界面。
这个设计方案为你提供了一个坚实的基础,你可以根据这个框架进行修改和扩展,打造一个功能更强大的图书管理系统,祝你项目顺利!
