C语言项目实战教程:11.3 项目实现
在本节中,我们将深入探讨如何在C语言中实现一个小型项目。我们将通过一个简单的命令行图书管理系统来展示项目的结构、设计和实现过程。该项目将涵盖文件操作、数据结构、动态内存管理等多个方面,适合希望提升C语言技能的开发者。
项目概述
我们的图书管理系统将具备以下功能:
- 添加新书籍
- 显示所有书籍
- 查找书籍
- 删除书籍
- 保存和加载书籍数据
项目结构
在开始编码之前,我们需要设计项目的结构。以下是推荐的文件结构:
book_manager/
├── main.c
├── book.h
├── book.c
└── Makefile
main.c
:主程序文件,负责用户交互。book.h
:书籍数据结构和函数声明。book.c
:书籍相关的函数实现。Makefile
:构建项目的文件。
数据结构设计
在book.h
中,我们定义书籍的数据结构和相关函数的声明。
// book.h
#ifndef BOOK_H
#define BOOK_H
#define MAX_TITLE_LENGTH 100
#define MAX_AUTHOR_LENGTH 100
#define MAX_BOOKS 100
typedef struct {
char title[MAX_TITLE_LENGTH];
char author[MAX_AUTHOR_LENGTH];
int year;
} Book;
void addBook(Book books[], int *count);
void displayBooks(const Book books[], int count);
int findBook(const Book books[], int count, const char *title);
void deleteBook(Book books[], int *count, const char *title);
void saveBooks(const Book books[], int count);
void loadBooks(Book books[], int *count);
#endif // BOOK_H
函数实现
接下来,在book.c
中实现这些函数。
// book.c
#include <stdio.h>
#include <string.h>
#include "book.h"
void addBook(Book books[], int *count) {
if (*count >= MAX_BOOKS) {
printf("书籍数量已达上限。\n");
return;
}
printf("输入书名: ");
scanf("%s", books[*count].title);
printf("输入作者: ");
scanf("%s", books[*count].author);
printf("输入出版年份: ");
scanf("%d", &books[*count].year);
(*count)++;
printf("书籍添加成功!\n");
}
void displayBooks(const Book books[], int count) {
if (count == 0) {
printf("没有书籍可显示。\n");
return;
}
for (int i = 0; i < count; i++) {
printf("书名: %s, 作者: %s, 年份: %d\n", books[i].title, books[i].author, books[i].year);
}
}
int findBook(const Book books[], int count, const char *title) {
for (int i = 0; i < count; i++) {
if (strcmp(books[i].title, title) == 0) {
return i;
}
}
return -1; // 未找到
}
void deleteBook(Book books[], int *count, const char *title) {
int index = findBook(books, *count, title);
if (index == -1) {
printf("未找到书籍。\n");
return;
}
for (int i = index; i < *count - 1; i++) {
books[i] = books[i + 1];
}
(*count)--;
printf("书籍删除成功!\n");
}
void saveBooks(const Book books[], int count) {
FILE *file = fopen("books.dat", "wb");
if (!file) {
printf("无法打开文件进行写入。\n");
return;
}
fwrite(books, sizeof(Book), count, file);
fclose(file);
printf("书籍数据已保存。\n");
}
void loadBooks(Book books[], int *count) {
FILE *file = fopen("books.dat", "rb");
if (!file) {
printf("无法打开文件进行读取。\n");
return;
}
*count = fread(books, sizeof(Book), MAX_BOOKS, file);
fclose(file);
printf("书籍数据已加载。\n");
}
主程序
在main.c
中实现用户交互逻辑。
// main.c
#include <stdio.h>
#include "book.h"
int main() {
Book books[MAX_BOOKS];
int count = 0;
int choice;
loadBooks(books, &count);
do {
printf("\n图书管理系统\n");
printf("1. 添加书籍\n");
printf("2. 显示所有书籍\n");
printf("3. 查找书籍\n");
printf("4. 删除书籍\n");
printf("5. 保存书籍\n");
printf("6. 退出\n");
printf("选择操作: ");
scanf("%d", &choice);
switch (choice) {
case 1:
addBook(books, &count);
break;
case 2:
displayBooks(books, count);
break;
case 3: {
char title[MAX_TITLE_LENGTH];
printf("输入书名: ");
scanf("%s", title);
int index = findBook(books, count, title);
if (index != -1) {
printf("找到书籍: %s, 作者: %s, 年份: %d\n", books[index].title, books[index].author, books[index].year);
} else {
printf("未找到书籍。\n");
}
break;
}
case 4: {
char title[MAX_TITLE_LENGTH];
printf("输入书名: ");
scanf("%s", title);
deleteBook(books, &count, title);
break;
}
case 5:
saveBooks(books, count);
break;
case 6:
printf("退出系统。\n");
break;
default:
printf("无效选择,请重试。\n");
}
} while (choice != 6);
return 0;
}
Makefile
为了方便编译,我们可以使用Makefile。
# Makefile
CC = gcc
CFLAGS = -Wall -g
OBJ = main.o book.o
TARGET = book_manager
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ)
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f $(OBJ) $(TARGET)
优点与缺点
优点
- 模块化设计:将书籍相关的功能分离到
book.c
和book.h
中,增强了代码的可读性和可维护性。 - 数据持久化:通过文件操作实现数据的保存和加载,确保数据不会丢失。
- 用户友好:提供简单的命令行界面,用户可以方便地进行操作。
缺点
- 内存限制:使用静态数组存储书籍,限制了书籍数量,无法动态扩展。
- 错误处理不足:在文件操作和用户输入方面的错误处理较为简单,可能导致程序崩溃或数据损坏。
- 缺乏多线程支持:该系统是单线程的,无法处理并发请求。
注意事项
- 输入验证:在实际应用中,用户输入需要进行严格验证,以防止缓冲区溢出等安全问题。
- 内存管理:在使用动态内存分配时,务必确保在不再使用时释放内存,以防内存泄漏。
- 文件操作:在进行文件读写时,始终检查文件是否成功打开,并处理可能的错误。
总结
通过本节的学习,我们实现了一个简单的图书管理系统,涵盖了C语言中的多个重要概念。希望通过这个项目,读者能够更深入地理解C语言的应用,并在此基础上进行更复杂的项目开发。