【C语言】图书管理系统(文件存储版)丨源码+详解

发布于:2025-06-16 ⋅ 阅读:(20) ⋅ 点赞:(0)

一、系统介绍

这是一个基于C语言开发的终端图书管理系统,采用链表数据结构​+​二进制文件存储技术实现。系统具有以下特点:

  1. 双角色系统​:管理员(管理图书)和读者(借阅/归还)
  2. 完整功能​:图书添加、搜索、借阅、归还、显示等功能
  3. 数据持久化​:所有图书信息保存在文件中,重启不丢失
  4. 健壮性设计​:完善的输入验证和错误处理

二、系统完整代码

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

/* 宏定义 */
#define MAX_NAME 50   // 名称最大长度
#define MAX_ID 20     // ID最大长度
#if defined(_WIN32)
    #define CLEAR_SCREEN system("cls")  // Windows清屏
#else
    #define CLEAR_SCREEN system("clear") // Linux/Mac清屏
#endif

/* 数据结构 */
// 图书结构
typedef struct Book {
    char isbn[MAX_ID];           // ISBN号
    char title[MAX_NAME];        // 书名
    char author[MAX_NAME];       // 作者
    int total_count;             // 总数量
    int available_count;         // 可借数量
    struct Book *next;           // 链表指针
} Book;

// 借阅记录
typedef struct BorrowRecord {
    char user_id[MAX_ID];        // 借阅者ID
    char book_isbn[MAX_ID];      // 图书ISBN
    time_t borrow_date;          // 借书日期(时间戳)
    time_t return_date;          // 还书日期
    struct BorrowRecord *next;   // 链表指针
} BorrowRecord;

/* 全局变量 */
Book *book_list = NULL;             // 图书链表头指针
BorrowRecord *borrow_list = NULL;   // 借阅记录链表头指针

/************************************
 * 工具函数:清空输入缓冲区
 ************************************/
void clear_input_buffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

/************************************
 * 数据加载:从文件读取图书数据
 ************************************/
void load_books() {
    FILE *fp = fopen("books.dat", "rb");
    if (fp == NULL) return;

    Book book_temp;
    while (fread(&book_temp, sizeof(Book), 1, fp) == 1) {
        Book *new_book = (Book*)malloc(sizeof(Book));
        *new_book = book_temp;
        new_book->next = book_list;
        book_list = new_book;
    }
    fclose(fp);
}

/************************************
 * 数据保存:将当前图书数据写入文件
 ************************************/
void save_books() {
    FILE *fp = fopen("books.dat", "wb");
    if (fp == NULL) {
        printf("错误:无法保存数据!\n");
        return;
    }

    Book *current = book_list;
    while (current != NULL) {
        fwrite(current, sizeof(Book), 1, fp);
        current = current->next;
    }
    fclose(fp);
}

/************************************
 * 功能:添加新书(管理员权限)
 ************************************/
void add_book() {
    CLEAR_SCREEN;
    printf("\n======== 添加新书 ========\n");
    Book *new_book = (Book*)malloc(sizeof(Book));

    // 输入ISBN并查重
    printf("ISBN: ");
    scanf("%19s", new_book->isbn);
    clear_input_buffer();

    Book *current = book_list;
    while (current != NULL) {
        if (strcmp(current->isbn, new_book->isbn) == 0) {
            printf("错误:ISBN已存在!\n");
            free(new_book);
            return;
        }
        current = current->next;
    }

    // 输入其他信息
    printf("书名: ");
    fgets(new_book->title, MAX_NAME, stdin);
    new_book->title[strcspn(new_book->title, "\n")] = '\0'; // 去掉换行符

    printf("作者: ");
    fgets(new_book->author, MAX_NAME, stdin);
    new_book->author[strcspn(new_book->author, "\n")] = '\0';

    printf("总数量: ");
    scanf("%d", &new_book->total_count);
    new_book->available_count = new_book->total_count;
    clear_input_buffer();

    // 插入链表
    new_book->next = book_list;
    book_list = new_book;
    printf("\n图书《%s》添加成功!\n", new_book->title);
    save_books();  // 保存到文件
}

/************************************
 * 功能:按关键字搜索图书(支持模糊搜索)
 ************************************/
void search_book() {
    CLEAR_SCREEN;
    printf("\n======== 图书搜索 ========\n");
    char keyword[MAX_NAME];
    printf("输入ISBN/书名/作者关键字: ");
    fgets(keyword, MAX_NAME, stdin);
    keyword[strcspn(keyword, "\n")] = '\0';  // 去掉换行符

    if (strlen(keyword) == 0) {
        printf("搜索内容不能为空!\n");
        return;
    }

    Book *current = book_list;
    int found = 0;
    while (current != NULL) {
        // 检查ISBN、书名、作者是否匹配
        if (strstr(current->isbn, keyword) != NULL || 
            strstr(current->title, keyword) != NULL || 
            strstr(current->author, keyword) != NULL) {
            
            printf("\n--------------------");
            printf("\nISBN: %s\n书名: %s\n作者: %s\n数量: %d/%d\n",
                  current->isbn, current->title, current->author,
                  current->available_count, current->total_count);
            found = 1;
        }
        current = current->next;
    }

    if (!found) {
        printf("未找到匹配的图书!\n");
    }
}

/************************************
 * 功能:借阅图书(读者权限)
 ************************************/
void borrow_book(char *user_id) {
    CLEAR_SCREEN;
    printf("\n======== 借阅图书 ========\n");
    char isbn[MAX_ID];
    printf("输入要借阅的图书ISBN: ");
    scanf("%19s", isbn);
    clear_input_buffer();

    // 查找图书
    Book *book = book_list;
    while (book != NULL) {
        if (strcmp(book->isbn, isbn) == 0) break;
        book = book->next;
    }

    // 检查图书状态
    if (book == NULL) {
        printf("错误:找不到该图书!\n");
        return;
    } else if (book->available_count <= 0) {
        printf("错误:该书已全部借出!\n");
        return;
    }

    // 创建借阅记录
    BorrowRecord *record = (BorrowRecord*)malloc(sizeof(BorrowRecord));
    strcpy(record->user_id, user_id);
    strcpy(record->book_isbn, isbn);
    record->borrow_date = time(NULL);  // 当前时间
    record->return_date = 0;           // 0表示未归还

    // 更新图书库存
    book->available_count--;

    // 添加记录到链表
    record->next = borrow_list;
    borrow_list = record;

    printf("\n借阅成功!\n");
    printf("归还期限: 30天内\n");
    printf("借阅时间: %s", ctime(&record->borrow_date));
    save_books();  // 保存库存变更
}

/************************************
 * 功能:归还图书(读者权限)
 ************************************/
void return_book(char *user_id) {
    CLEAR_SCREEN;
    printf("\n======== 归还图书 ========\n");
    char isbn[MAX_ID];
    printf("输入要归还的图书ISBN: ");
    scanf("%19s", isbn);
    clear_input_buffer();

    // 查找借阅记录(未归还状态)
    BorrowRecord *prev = NULL;
    BorrowRecord *current = borrow_list;
    int found = 0;

    while (current != NULL) {
        if (strcmp(current->user_id, user_id) == 0 && 
            strcmp(current->book_isbn, isbn) == 0 && 
            current->return_date == 0) {
            
            found = 1;
            // 更新图书库存
            Book *book = book_list;
            while (book != NULL) {
                if (strcmp(book->isbn, isbn) == 0) {
                    book->available_count++;
                    break;
                }
                book = book->next;
            }

            // 更新归还日期
            current->return_date = time(NULL);
            printf("\n归还成功!\n");
            printf("归还时间: %s", ctime(&current->return_date));
            save_books();
            return;
        }
        prev = current;
        current = current->next;
    }

    if (!found) {
        printf("错误:未找到借阅记录或已归还!\n");
    }
}

/************************************
 * 功能:显示所有图书信息
 ************************************/
void display_all_books() {
    CLEAR_SCREEN;
    printf("\n======== 所有图书 ========\n");
    printf("%-15s %-25s %-20s %-10s\n", "ISBN", "书名", "作者", "库存(可借/总数)");
    
    Book *current = book_list;
    while (current != NULL) {
        printf("%-15s %-25s %-20s %d/%d\n", 
              current->isbn, 
              current->title, 
              current->author, 
              current->available_count, 
              current->total_count);
        current = current->next;
    }
}

/************************************
 * 管理员菜单
 ************************************/
void admin_menu() {
    int choice;
    while (1) {
        CLEAR_SCREEN;
        printf("\n======= 管理员菜单 =======\n");
        printf("1. 添加图书\n");
        printf("2. 搜索图书\n");
        printf("3. 查看所有图书\n");
        printf("0. 退出\n");
        printf("请选择操作: ");
        scanf("%d", &choice);
        clear_input_buffer();

        switch (choice) {
            case 1: add_book(); break;
            case 2: search_book(); break;
            case 3: display_all_books(); break;
            case 0: return;
            default: printf("无效选择!\n");
        }

        printf("\n按回车键继续...");
        getchar();
    }
}

/************************************
 * 读者菜单
 ************************************/
void reader_menu(char *user_id) {
    int choice;
    while (1) {
        CLEAR_SCREEN;
        printf("\n======= 读者菜单 =======\n");
        printf("读者ID: %s\n", user_id);
        printf("1. 借阅图书\n");
        printf("2. 归还图书\n");
        printf("3. 搜索图书\n");
        printf("4. 查看所有图书\n");
        printf("0. 退出\n");
        printf("请选择操作: ");
        scanf("%d", &choice);
        clear_input_buffer();

        switch (choice) {
            case 1: borrow_book(user_id); break;
            case 2: return_book(user_id); break;
            case 3: search_book(); break;
            case 4: display_all_books(); break;
            case 0: return;
            default: printf("无效选择!\n");
        }

        printf("\n按回车键继续...");
        getchar();
    }
}

/************************************
 * 主函数
 ************************************/
int main() {
    load_books();  // 启动时加载图书数据
    
    while (1) {
        CLEAR_SCREEN;
        printf("======= 图书管理系统 =======\n");
        printf("1. 管理员登录\n");
        printf("2. 读者登录\n");
        printf("0. 退出系统\n");
        printf("请选择: ");
        
        int option;
        if (scanf("%d", &option) != 1) {
            clear_input_buffer();
            continue;
        }
        clear_input_buffer();

        switch (option) {
            case 1: admin_menu(); break;
            case 2: {
                char user_id[MAX_ID];
                printf("请输入读者ID: ");
                fgets(user_id, MAX_ID, stdin);
                user_id[strcspn(user_id, "\n")] = '\0';
                reader_menu(user_id);
                break;
            }
            case 0: {
                // 程序退出前保存数据
                save_books();
                printf("感谢使用,再见!\n");
                return 0;
            }
            default: printf("无效选择!\n");
        }
    }
}

三、系统功能详解

1. 主要功能模块

功能模块 描述 访问权限
图书添加 添加新书到系统,包含ISBN、书名、作者等信息 管理员
图书搜索 通过ISBN、书名或作者关键字查找图书 所有用户
借阅管理 借阅图书并自动记录借阅时间和读者ID 读者
归还管理 归还已借阅图书并更新库存 读者
图书显示 以表格形式展示所有图书信息 所有用户

2. 数据结构设计

 

3. 文件存储机制

系统使用二进制文件books.dat保存所有图书数据,采用以下技术:

  1. 序列化存储​:直接将内存中的结构体写入文件
  2. 链表遍历​:通过fwrite逐个节点写入文件
  3. 读取加载​:启动时重新构建链表结构
  4. 自动保存​:每次数据变更后自动更新文件

四、使用说明

1. 编译运行

Windows系统:​

gcc library.c -o library
library.exe

Linux/Mac系统:​

gcc library.c -o library
./library

2. 操作流程示例

管理员操作:​

  1. 选择"管理员登录"
  2. 添加图书:
  3. 搜索图书:输入"C程序"

读者操作:​

  1. 选择"读者登录",输入任意ID(如:2023001)
  2. 借阅图书:输入ISBN号
  3. 查看图书:选择"查看所有图书"
  4. 归还图书:选择归还并输入ISBN号

3. 系统界面示例

======= 图书管理系统 =======
1. 管理员登录
2. 读者登录
0. 退出系统
请选择: 1

======= 管理员菜单 =======
1. 添加图书
2. 搜索图书
3. 查看所有图书
0. 退出
请选择操作: 1

======== 添加新书 ========
ISBN: 1234567890
书名: C程序设计语言
作者: XXXX
总数量: 10

图书《C程序设计语言》添加成功!

五、扩展与优化建议

1. 可扩展功能

  1. 借阅记录持久化​:添加borrow.dat保存借阅记录
  2. 逾期计算​:根据借阅时间自动计算逾期费用
  3. 管理员密码​:增加管理员登录验证
  4. 批量导入​:支持从CSV文件批量导入图书

2. 性能优化

// 示例:优化查找函数(哈希表实现)
#define HASH_SIZE 100

typedef struct HashTable {
    Book *table[HASH_SIZE];
} HashTable;

// ISBN哈希函数
unsigned int hash_function(char *isbn) {
    unsigned int hash = 0;
    for (int i = 0; i < strlen(isbn); i++) {
        hash = 31 * hash + isbn[i];
    }
    return hash % HASH_SIZE;
}

// 添加图书到哈希表
void add_to_hash(Book *book, HashTable *hash_table) {
    unsigned int index = hash_function(book->isbn);
    book->next = hash_table->table[index];
    hash_table->table[index] = book;
}

3. 增强安全性

  1. 输入验证​:添加更严格的ISBN格式检查
  2. 密码加密​:管理员密码使用MD5/SHA加密存储
  3. 访问控制​:不同读者只能查看自己的借阅记录

六、总结

这个C语言图书管理系统具有完整的功能实现、清晰的代码结构和良好的扩展性,适合用作课程设计或学习项目。系统特点包括:

  1. 采用链表数据结构动态管理数据
  2. 文件存储实现数据持久化
  3. 模块化设计便于功能扩展
  4. 完整的输入验证和错误处理
  5. 跨平台兼容性(Windows/Linux/Mac)

将整个代码复制到library.c文件中即可编译运行,无需任何外部依赖库。

 资源推荐:

C/C++学习交流君羊

C/C++教程

C/C++学习路线,就业咨询,技术提升


网站公告

今日签到

点亮在社区的每一天
去签到