1. 项目概述
"PTA 习题9-4 查找书籍"是程序设计类课程常见的实践题目,主要考察学生对数据结构中查找算法的掌握程度。这道题通常会要求学生实现一个书籍信息管理系统,能够根据书名或其他关键字段快速检索目标书籍。
在实际教学场景中,这类题目往往作为《数据结构》或《C语言程序设计》课程的配套练习出现。通过完成这个项目,学生可以深入理解以下核心概念:
- 结构体数据类型的定义与使用
- 文件读写操作
- 基本查找算法(顺序查找、二分查找等)
- 字符串处理技巧
提示:虽然题目描述可能只要求实现基本功能,但在实际开发中应该考虑程序的健壮性,比如处理无效输入、优化查找效率等。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心需求解析
2.1 题目基本要求
典型的PTA习题要求可能包含以下功能点:
- 从文件读取书籍信息(通常包括书名、作者、价格等字段)
- 实现按书名查找功能
- 输出查找结果或"未找到"提示
- 可能需要支持多次查询直到用户选择退出
2.2 数据结构设计
对于书籍信息,最合理的存储方式是使用结构体:
c复制struct Book {
char title[100]; // 书名
char author[50]; // 作者
float price; // 价格
// 可根据需要添加其他字段
};
在内存中,通常使用数组或链表来存储多个书籍信息。考虑到查找效率,建议使用数组配合排序算法。
2.3 文件格式假设
虽然题目可能不明确指定,但实践中常见的输入文件格式是:
code复制编程珠玑 Jon Bentley 58.00
算法导论 Thomas Cormen 128.00
C程序设计语言 Brian Kernighan 45.00
每行代表一本书,字段间用空格或制表符分隔。
3. 实现方案详解
3.1 基础实现步骤
- 文件读取与解析:
c复制FILE *fp = fopen("books.txt", "r");
if (fp == NULL) {
printf("无法打开文件\n");
return 1;
}
struct Book books[100]; // 假设不超过100本书
int count = 0;
while (fscanf(fp, "%s %s %f", books[count].title,
books[count].author, &books[count].price) == 3) {
count++;
if (count >= 100) break; // 防止数组越界
}
fclose(fp);
- 顺序查找实现:
c复制int findBook(struct Book books[], int count, char *title) {
for (int i = 0; i < count; i++) {
if (strcmp(books[i].title, title) == 0) {
return i; // 返回找到的索引
}
}
return -1; // 未找到
}
3.2 性能优化方案
对于大量数据(如超过100本书),顺序查找效率低下。可以采用以下优化:
- 先排序后二分查找:
c复制// 比较函数用于qsort
int compareBooks(const void *a, const void *b) {
return strcmp(((struct Book*)a)->title, ((struct Book*)b)->title);
}
// 使用前先排序
qsort(books, count, sizeof(struct Book), compareBooks);
// 二分查找实现
int binarySearch(struct Book books[], int left, int right, char *title) {
while (left <= right) {
int mid = left + (right - left) / 2;
int cmp = strcmp(books[mid].title, title);
if (cmp == 0) return mid;
if (cmp < 0) left = mid + 1;
else right = mid - 1;
}
return -1;
}
- 建立索引:
对于更复杂的系统,可以建立书名哈希表或多字段索引。
4. 完整实现代码示例
c复制#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_BOOKS 100
#define MAX_TITLE_LEN 100
#define MAX_AUTHOR_LEN 50
struct Book {
char title[MAX_TITLE_LEN];
char author[MAX_AUTHOR_LEN];
float price;
};
int compareBooks(const void *a, const void *b) {
return strcmp(((struct Book*)a)->title, ((struct Book*)b)->title);
}
int binarySearch(struct Book books[], int count, char *title) {
int left = 0, right = count - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
int cmp = strcmp(books[mid].title, title);
if (cmp == 0) return mid;
if (cmp < 0) left = mid + 1;
else right = mid - 1;
}
return -1;
}
int main() {
struct Book books[MAX_BOOKS];
int count = 0;
// 读取文件
FILE *fp = fopen("books.txt", "r");
if (fp == NULL) {
printf("无法打开文件\n");
return 1;
}
while (fscanf(fp, "%99s %49s %f", books[count].title,
books[count].author, &books[count].price) == 3) {
count++;
if (count >= MAX_BOOKS) break;
}
fclose(fp);
// 排序书籍
qsort(books, count, sizeof(struct Book), compareBooks);
// 查询循环
char query[MAX_TITLE_LEN];
while (1) {
printf("请输入要查找的书名(输入exit退出): ");
scanf("%99s", query);
if (strcmp(query, "exit") == 0) break;
int index = binarySearch(books, count, query);
if (index != -1) {
printf("找到书籍: %s 作者: %s 价格: %.2f\n",
books[index].title, books[index].author, books[index].price);
} else {
printf("未找到书籍: %s\n", query);
}
}
return 0;
}
5. 常见问题与解决方案
5.1 文件读取问题
问题1:文件打开失败
- 检查文件路径是否正确
- 确认程序有文件读取权限
- 添加错误处理代码
问题2:字段包含空格
- 使用fgets代替fscanf逐行读取
- 实现自定义的字段解析逻辑
5.2 字符串比较问题
问题:查找时大小写敏感
解决方案:
c复制// 使用不区分大小写的比较
int cmp = strcasecmp(books[i].title, title);
5.3 内存管理问题
问题:书籍数量超过数组限制
解决方案:
- 使用动态内存分配
- 或者先统计文件行数再分配足够空间
6. 扩展思考
6.1 多字段查询
实际应用中,可能需要支持按作者或价格范围查询。可以:
- 维护多个排序后的数组副本
- 使用更复杂的数据结构如二叉搜索树
- 实现简单的数据库索引机制
6.2 交互界面改进
基础的命令行界面可以升级为:
- 简单的文本菜单系统
- 基于ncurses的TUI界面
- 支持模糊查询和自动补全
6.3 性能测试
对于不同规模的书籍数据,可以测试:
- 顺序查找与二分查找的时间对比
- 不同排序算法的效率
- 内存占用情况
注意:在实际PTA系统中提交时,务必严格按照题目要求的输入输出格式,避免因格式错误导致判题失败。
