C语言图书管理系统设计与实现
需求分析
一个基本的图书管理系统应该具备以下核心功能:

(图片来源网络,侵删)
- 图书信息的录入:能够将新图书的信息(如ID、书名、作者、出版社、库存数量)添加到系统中。
- 图书信息的查询:能够根据不同的条件(如书名、作者、ID)查找图书。
- 图书信息的修改:能够修改已有图书的信息(如更新库存、修改作者等)。
- 图书信息的删除:能够从系统中删除某本图书。
- 图书信息的显示:能够以列表形式显示所有图书的信息。
- 数据持久化:系统能够将图书数据保存到文件中,并在程序启动时从文件中加载,确保数据不丢失。
系统设计
数据结构设计
为了存储图书信息,我们使用结构体,为了管理所有图书,我们使用结构体数组。
// 定义图书结构体
typedef struct {
int id; // 图书ID (唯一标识)
char title[100]; // 书名
char author[50]; // 作者
char publisher[50]; // 出版社
int stock; // 库存数量
} Book;
// 定义图书管理系统结构体
// 使用一个结构体来封装所有数据和功能,使程序更模块化
typedef struct {
Book books[MAX_BOOKS]; // 存储所有图书的数组
int count; // 当前系统中图书的数量
} LibrarySystem;
MAX_BOOKS是一个宏,定义了系统能容纳的最大图书数量,#define MAX_BOOKS 1000。LibrarySystem结构体封装了数据和图书总数,方便函数间传递。
功能模块设计
我们将系统功能分解为独立的函数,每个函数负责一个特定的任务。
| 函数名 | 功能描述 |
|---|---|
initSystem(LibrarySystem *sys) |
初始化系统,清空图书列表,计数器归零。 |
saveToFile(LibrarySystem *sys) |
将系统中的所有图书数据保存到文件(如 library.dat)。 |
loadFromFile(LibrarySystem *sys) |
从文件中加载图书数据到系统。 |
addBook(LibrarySystem *sys) |
添加一本新书。 |
findBook(LibrarySystem *sys) |
查找并显示图书。 |
modifyBook(LibrarySystem *sys) |
修改图书信息。 |
deleteBook(LibrarySystem *sys) |
删除图书。 |
displayAllBooks(LibrarySystem *sys) |
显示所有图书信息。 |
showMenu() |
显示用户操作菜单。 |
main() |
程序入口,负责调用其他函数,控制程序流程。 |
核心代码实现
下面是完整的C语言代码实现,代码包含了详细的注释,以帮助你理解每一部分的作用。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BOOKS 1000 // 最大图书数量
#define FILENAME "library.dat" // 数据文件名
// 定义图书结构体
typedef struct {
int id;
char title[100];
char author[50];
char publisher[50];
int stock;
} Book;
// 定义图书管理系统结构体
typedef struct {
Book books[MAX_BOOKS];
int count;
} LibrarySystem;
// 函数声明
void initSystem(LibrarySystem *sys);
void saveToFile(LibrarySystem *sys);
void loadFromFile(LibrarySystem *sys);
void addBook(LibrarySystem *sys);
void findBook(LibrarySystem *sys);
void modifyBook(LibrarySystem *sys);
void deleteBook(LibrarySystem *sys);
void displayAllBooks(LibrarySystem *sys);
void showMenu();
int main() {
LibrarySystem sys;
initSystem(&sys);
// 程序启动时尝试从文件加载数据
loadFromFile(&sys);
int choice;
do {
showMenu();
printf("请输入您的选择: ");
scanf("%d", &choice);
getchar(); // 消耗掉输入缓冲区中的换行符,避免影响后续的gets或fgets
switch (choice) {
case 1:
addBook(&sys);
break;
case 2:
findBook(&sys);
break;
case 3:
modifyBook(&sys);
break;
case 4:
deleteBook(&sys);
break;
case 5:
displayAllBooks(&sys);
break;
case 0:
printf("感谢使用,系统将自动保存数据并退出,\n");
saveToFile(&sys);
break;
default:
printf("无效的选择,请重新输入!\n");
break;
}
} while (choice != 0);
return 0;
}
// 初始化系统
void initSystem(LibrarySystem *sys) {
sys->count = 0;
printf("图书管理系统已初始化,\n");
}
// 显示菜单
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(LibrarySystem *sys) {
if (sys->count >= MAX_BOOKS) {
printf("错误:系统已满,无法添加更多图书!\n");
return;
}
Book newBook;
printf("请输入图书ID: ");
scanf("%d", &newBook.id);
getchar(); // 消耗换行符
printf("请输入书名: ");
fgets(newBook.title, sizeof(newBook.title), stdin);
newBook.title[strcspn(newBook.title, "\n")] = 0; // 去掉fgets读取的换行符
printf("请输入作者: ");
fgets(newBook.author, sizeof(newBook.author), stdin);
newBook.author[strcspn(newBook.author, "\n")] = 0;
printf("请输入出版社: ");
fgets(newBook.publisher, sizeof(newBook.publisher), stdin);
newBook.publisher[strcspn(newBook.publisher, "\n")] = 0;
printf("请输入库存数量: ");
scanf("%d", &newBook.stock);
// 检查ID是否已存在
for (int i = 0; i < sys->count; i++) {
if (sys->books[i].id == newBook.id) {
printf("错误:ID为 %d 的图书已存在!\n", newBook.id);
return;
}
}
sys->books[sys->count] = newBook;
sys->count++;
printf("图书添加成功!\n");
}
// 查询图书
void findBook(LibrarySystem *sys) {
if (sys->count == 0) {
printf("系统中没有图书!\n");
return;
}
int choice;
printf("请选择查询方式:\n");
printf("1. 按ID查询\n");
printf("2. 按书名查询\n");
printf("请输入选择: ");
scanf("%d", &choice);
if (choice == 1) {
int id;
printf("请输入要查询的图书ID: ");
scanf("%d", &id);
int found = 0;
for (int i = 0; i < sys->count; i++) {
if (sys->books[i].id == id) {
printf("\n--- 找到图书 ---\n");
printf("ID: %d\n", sys->books[i].id);
printf("书名: %s\n", sys->books[i].title);
printf("作者: %s\n", sys->books[i].author);
printf("出版社: %s\n", sys->books[i].publisher);
printf("库存: %d\n", sys->books[i].stock);
found = 1;
break;
}
}
if (!found) {
printf("未找到ID为 %d 的图书,\n", id);
}
} else if (choice == 2) {
char title[100];
printf("请输入要查询的书名: ");
getchar(); // 消耗换行符
fgets(title, sizeof(title), stdin);
title[strcspn(title, "\n")] = 0;
int found = 0;
for (int i = 0; i < sys->count; i++) {
if (strstr(sys->books[i].title, title) != NULL) { // 使用strstr进行模糊查询
printf("\n--- 找到图书 ---\n");
printf("ID: %d\n", sys->books[i].id);
printf("书名: %s\n", sys->books[i].title);
printf("作者: %s\n", sys->books[i].author);
printf("出版社: %s\n", sys->books[i].publisher);
printf("库存: %d\n", sys->books[i].stock);
printf("-----------------\n");
found = 1;
}
}
if (!found) {
printf("未找到包含 \"%s\" 的图书,\n", title);
}
} else {
printf("无效的选择!\n");
}
}
// 修改图书
void modifyBook(LibrarySystem *sys) {
if (sys->count == 0) {
printf("系统中没有图书!\n");
return;
}
int id;
printf("请输入要修改的图书ID: ");
scanf("%d", &id);
for (int i = 0; i < sys->count; i++) {
if (sys->books[i].id == id) {
printf("找到图书,请输入新的信息 (直接回车则保持不变):\n");
printf("书名 (%s): ", sys->books[i].title);
getchar();
char newTitle[100];
fgets(newTitle, sizeof(newTitle), stdin);
if (strlen(newTitle) > 1) { // 如果用户输入了内容
newTitle[strcspn(newTitle, "\n")] = 0;
strcpy(sys->books[i].title, newTitle);
}
printf("作者 (%s): ", sys->books[i].author);
char newAuthor[50];
fgets(newAuthor, sizeof(newAuthor), stdin);
if (strlen(newAuthor) > 1) {
newAuthor[strcspn(newAuthor, "\n")] = 0;
strcpy(sys->books[i].author, newAuthor);
}
printf("出版社 (%s): ", sys->books[i].publisher);
char newPublisher[50];
fgets(newPublisher, sizeof(newPublisher), stdin);
if (strlen(newPublisher) > 1) {
newPublisher[strcspn(newPublisher, "\n")] = 0;
strcpy(sys->books[i].publisher, newPublisher);
}
printf("库存数量 (%d): ", sys->books[i].stock);
char newStockStr[10];
fgets(newStockStr, sizeof(newStockStr), stdin);
if (strlen(newStockStr) > 1) {
int newStock = atoi(newStockStr);
sys->books[i].stock = newStock;
}
printf("图书信息修改成功!\n");
return;
}
}
printf("未找到ID为 %d 的图书,\n", id);
}
// 删除图书
void deleteBook(LibrarySystem *sys) {
if (sys->count == 0) {
printf("系统中没有图书!\n");
return;
}
int id;
printf("请输入要删除的图书ID: ");
scanf("%d", &id);
int foundIndex = -1;
for (int i = 0; i < sys->count; i++) {
if (sys->books[i].id == id) {
foundIndex = i;
break;
}
}
if (foundIndex != -1) {
// 将后面的所有图书向前移动一位,覆盖掉要删除的图书
for (int i = foundIndex; i < sys->count - 1; i++) {
sys->books[i] = sys->books[i + 1];
}
sys->count--;
printf("ID为 %d 的图书已删除,\n", id);
} else {
printf("未找到ID为 %d 的图书,\n", id);
}
}
// 显示所有图书
void displayAllBooks(LibrarySystem *sys) {
if (sys->count == 0) {
printf("系统中没有图书!\n");
return;
}
printf("\n========== 所有图书列表 (共 %d 本) ==========\n", sys->count);
printf("-----------------------------------------------------------------\n");
printf("%-5s %-30s %-20s %-20s %-10s\n", "ID", "书名", "作者", "出版社", "库存");
printf("-----------------------------------------------------------------\n");
for (int i = 0; i < sys->count; i++) {
printf("%-5d %-30s %-20s %-20s %-10d\n",
sys->books[i].id,
sys->books[i].title,
sys->books[i].author,
sys->books[i].publisher,
sys->books[i].stock);
}
printf("-----------------------------------------------------------------\n");
}
// 保存数据到文件
void saveToFile(LibrarySystem *sys) {
FILE *fp = fopen(FILENAME, "wb"); // "wb" 表示二进制写入,会覆盖文件
if (fp == NULL) {
printf("警告:无法打开文件 %s 进行保存!\n", FILENAME);
return;
}
// 一次性写入整个结构体数组
fwrite(sys->books, sizeof(Book), sys->count, fp);
fclose(fp);
printf("数据已成功保存到 %s\n", FILENAME);
}
// 从文件加载数据
void loadFromFile(LibrarySystem *sys) {
FILE *fp = fopen(FILENAME, "rb"); // "rb" 表示二进制读取
if (fp == NULL) {
printf("提示:数据文件 %s 不存在,将创建新文件,\n", FILENAME);
return;
}
// 一次性读取整个结构体数组
sys->count = fread(sys->books, sizeof(Book), MAX_BOOKS, fp);
fclose(fp);
printf("数据已成功从 %s 加载,共 %d 本图书,\n", FILENAME, sys->count);
}
如何编译和运行
- 将以上代码保存为一个文件,
library_system.c。 - 打开终端或命令提示符。
- 使用GCC编译器进行编译:
gcc library_system.c -o library_system
- 运行生成的可执行文件:
- 在Windows上:
library_system.exe - 在Linux或macOS上:
./library_system
- 在Windows上:
系统扩展建议
如果你想让这个系统更完善,可以考虑以下扩展:

(图片来源网络,侵删)
-
更强大的查询功能:
- 增加按作者、出版社查询。
- 实现组合查询(查找“某位作者”写的“某本书”)。
-
借阅和归还功能:
- 添加一个
borrowBook函数,当用户借书时,减少对应图书的库存。 - 添加一个
returnBook函数,当用户还书时,增加对应图书的库存。 - 可以增加一个
isAvailable函数来检查图书是否可借。
- 添加一个
-
用户管理系统:
- 创建一个
User结构体,包含用户ID、姓名、密码等。 - 实现用户注册、登录功能,不同权限的用户(如管理员、普通用户)可以操作的功能不同。
- 创建一个
-
改进数据存储:
(图片来源网络,侵删)- 使用文本文件(如CSV格式)存储数据,方便用Excel等工具查看和编辑。
- 对于更复杂的系统,可以考虑使用简单的数据库(如SQLite)。
-
优化用户界面:
- 使用
system("cls")(Windows) 或system("clear")(Linux/macOS) 来清屏,使界面更整洁。 - 添加更多的输入验证,防止非法输入导致程序崩溃。
- 使用
这个项目是学习C语言结构体、文件操作、函数模块化设计的一个绝佳实践,希望这个详细的实现能对你有所帮助!
