#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
STATUS_RETURNED = 0, /* 已归还/在馆 */
STATUS_BORROWED = 1 /* 已借出 */
} BookStatus;
typedef struct Book {
char title[50];
char publisher[50];
char borrow_date[20];
char return_date[20];
BookStatus status;
struct Book *next;
} Book;
Book *head = NULL; /* 链表头指针 */
/* ---------- 输入辅助:读一整行,去掉换行 ---------- */
void read_line(char *buf, size_t size) {
if (fgets(buf, (int)size, stdin) == NULL) {
buf[0] = '\0';
return;
}
if (strchr(buf, '\n') == NULL) { /* 输入超长,清掉残留 */
int c;
while ((c = getchar()) != '\n' && c != EOF) { }
} else {
buf[strcspn(buf, "\n")] = '\0';
}
}
const char *status_text(BookStatus s) {
return s == STATUS_BORROWED ? "借出" : "归还";
}
/* ---------- 添加图书(尾插,保持录入顺序) ---------- */
void add_book(void) {
Book *b = (Book *)malloc(sizeof(Book));
if (b == NULL) { printf("内存分配失败!\n"); return; }
printf("书名: ");
read_line(b->title, sizeof(b->title));
if (b->title[0] == '\0') { printf("书名不能为空!\n"); free(b); return; }
printf("出版社: ");
read_line(b->publisher, sizeof(b->publisher));
printf("借出时间(如 2024-05-01,可为 -): ");
read_line(b->borrow_date, sizeof(b->borrow_date));
printf("归还时间(如 2024-06-01,可为 -): ");
read_line(b->return_date, sizeof(b->return_date));
char line[16];
printf("状态(0=归还/在馆, 1=借出): ");
read_line(line, sizeof(line));
b->status = (atoi(line) == 1) ? STATUS_BORROWED : STATUS_RETURNED;
b->next = NULL;
if (head == NULL) {
head = b;
} else {
Book *p = head;
while (p->next != NULL) p = p->next;
p->next = b;
}
printf("添加成功!\n");
}
/* ---------- 显示辅助 ---------- */
void print_header(void) {
printf("%-20s %-20s %-14s %-14s %-6s\n",
"书名", "出版社", "借出时间", "归还时间", "状态");
printf("--------------------------------------------------------------------------------\n");
}
void print_book(Book *b) {
printf("%-20s %-20s %-14s %-14s %-6s\n",
b->title, b->publisher,
b->borrow_date, b->return_date,
status_text(b->status));
}
/* ---------- 查找:按书名(模糊匹配) ---------- */
void search_by_title(void) {
char key[50];
printf("输入书名关键字: ");
read_line(key, sizeof(key));
int count = 0;
print_header();
for (Book *p = head; p != NULL; p = p->next) {
if (strstr(p->title, key) != NULL) {
print_book(p);
count++;
}
}
printf("共找到 %d 本图书\n", count);
}
/* ---------- 查找:按出版社(模糊匹配) ---------- */
void search_by_publisher(void) {
char key[50];
printf("输入出版社关键字: ");
read_line(key, sizeof(key));
int count = 0;
print_header();
for (Book *p = head; p != NULL; p = p->next) {
if (strstr(p->publisher, key) != NULL) {
print_book(p);
count++;
}
}
printf("共找到 %d 本图书\n", count);
}
/* ---------- 删除的匹配函数 ---------- */
int match_title(Book *b, const char *key) {
return strcmp(b->title, key) == 0;
}
int match_publisher(Book *b, const char *key) {
return strcmp(b->publisher, key) == 0;
}
/* 通用删除:删除所有匹配节点,返回删除数量 */
int delete_books(int (*match)(Book *, const char *), const char *key) {
Book *prev = NULL;
Book *cur = head;
int count = 0;
while (cur != NULL) {
if (match(cur, key)) {
Book *del = cur;
if (prev == NULL) head = cur->next; /* 删除头节点 */
else prev->next = cur->next; /* 删除中间/尾节点 */
cur = cur->next;
free(del);
count++;
} else {
prev = cur;
cur = cur->next;
}
}
return count;
}
void delete_by_title(void) {
char key[50];
printf("输入要删除的书名(完整): ");
read_line(key, sizeof(key));
int n = delete_books(match_title, key);
if (n > 0) printf("已删除 %d 本图书\n", n);
else printf("未找到该书\n");
}
void delete_by_publisher(void) {
char key[50];
printf("输入要删除的出版社(完整): ");
read_line(key, sizeof(key));
int n = delete_books(match_publisher, key);
if (n > 0) printf("已删除 %d 本图书\n", n);
else printf("未找到该出版社的图书\n");
}
/* ---------- 借出 / 归还登记(修改状态和时间) ---------- */
void change_status(void) {
char title[50];
printf("输入书名: ");
read_line(title, sizeof(title));
Book *p = head;
while (p != NULL && strcmp(p->title, title) != 0) p = p->next;
if (p == NULL) { printf("未找到该书\n"); return; }
char line[16];
printf("1=借出 0=归还: ");
read_line(line, sizeof(line));
if (atoi(line) == 1) {
p->status = STATUS_BORROWED;
printf("借出时间: ");
read_line(p->borrow_date, sizeof(p->borrow_date));
} else {
p->status = STATUS_RETURNED;
printf("归还时间: ");
read_line(p->return_date, sizeof(p->return_date));
}
printf("状态已更新\n");
}
/* ---------- 显示全部 ---------- */
void list_books(void) {
if (head == NULL) { printf("暂无图书\n"); return; }
print_header();
for (Book *p = head; p != NULL; p = p->next) print_book(p);
}
/* ---------- 释放整条链表 ---------- */
void free_all(void) {
Book *p = head;
while (p != NULL) {
Book *next = p->next;
free(p);
p = next;
}
head = NULL;
}
/* ---------- 主函数 ---------- */
int main(void) {
char line[32];
while (1) {
printf("\n========== 图书管理系统(链表版) ==========\n");
printf("1. 添加图书\n");
printf("2. 按书名查找\n");
printf("3. 按出版社查找\n");
printf("4. 按书名删除\n");
printf("5. 按出版社删除\n");
printf("6. 显示全部图书\n");
printf("7. 借出/归还登记\n");
printf("0. 退出\n");
printf("请选择: ");
read_line(line, sizeof(line));
int choice = atoi(line);
switch (choice) {
case 1: add_book(); break;
case 2: search_by_title(); break;
case 3: search_by_publisher(); break;
case 4: delete_by_title(); break;
case 5: delete_by_publisher(); break;
case 6: list_books(); break;
case 7: change_status(); break;
case 0:
free_all();
printf("再见!\n");
return 0;
default:
printf("无效选项,请重新输入\n");
}
}
return 0;
}