C语言实现file.txt文件内图书名称搜索的代码技术咨询
图书名称搜索代码的问题分析与优化方案
首先,你的代码功能逻辑是不正确的,核心的交互和遍历流程完全搞反了,而且还有不少细节问题。我来一步步拆解:
一、原代码的核心问题
- 交互逻辑完全颠倒:原代码是每读取文件的一行,就弹出提示让用户输入搜索书名。这意味着用户要跟着文件行数重复输入关键词,完全不符合“输入一次关键词,搜索整个文件”的正常需求。
- 无法处理带空格的书名:
scanf("%s", tmp2)只能读取到空格为止,如果图书名称包含空格(比如《The Great Gatsby》),只会读取到第一个空格,导致搜索匹配失败。 - 文件操作不规范:
- 使用
"r+"模式打开文件,但你只需要读取内容,不需要写入权限,应该用更安全的"r"模式。 - 没有调用
fclose(myFile)关闭文件,会造成系统资源泄漏。
- 使用
- 错误提示滥用:每一行不匹配就打印“未找到”,会导致只要有一行不匹配就输出一次错误信息,用户会看到大量重复的提示,体验极差。正确的逻辑应该是遍历完全部文件后,没有找到任何匹配项再提示未找到。
- 缓冲区溢出风险:
scanf("%s", tmp2)没有限制输入长度,如果用户输入的字符超过tmp2的512字节,会导致缓冲区溢出,触发未定义行为。fgets读取的行如果超过512字节会被截断,可能导致部分内容丢失,影响匹配结果。
- 子串匹配可能不符合预期:
strstr(tmp1, tmp2)是子串匹配,比如用户搜索“Java”,会匹配到包含“JavaScript”的行,如果你的需求是精确匹配图书名称,这个逻辑就有问题。
二、完善后的代码实现
假设你的file.txt每行格式是类似图书名称 作者 价格(或者用其他分隔符,比如|),以下是修复所有问题后的代码:
#include <stdio.h> #include <string.h> #define MAX_LINE_LEN 512 #define MAX_BOOK_NAME_LEN 256 int searchBookname() { // 1. 先让用户输入要搜索的图书名称 char targetName[MAX_BOOK_NAME_LEN]; printf("Insert the Book Name: "); // 使用fgets读取带空格的输入,避免scanf的限制 if (fgets(targetName, MAX_BOOK_NAME_LEN, stdin) == NULL) { puts("Error reading input!"); return 1; } // 去掉fgets读取到的换行符(如果存在) size_t len = strlen(targetName); if (len > 0 && targetName[len-1] == '\n') { targetName[len-1] = '\0'; } // 2. 打开文件(只读模式) FILE *myFile = fopen("file.txt", "r"); if (myFile == NULL) { puts("\nDatabase file does not exist!"); return 1; } char line[MAX_LINE_LEN]; int foundCount = 0; // 3. 遍历文件每一行,查找匹配项 while (fgets(line, MAX_LINE_LEN, myFile) != NULL) { // 检查行是否被截断(可选:如果行末尾没有换行符且不是文件末尾,说明行太长) if (!strchr(line, '\n') && !feof(myFile)) { puts("Warning: A line in the file is too long and was truncated!"); // 跳过剩余的长行 while (fgetc(myFile) != '\n' && !feof(myFile)); continue; } // 子串匹配(如果需要精确匹配,这里可以根据文件格式分割出书名字段再比较) if (strstr(line, targetName) != NULL) { printf("Found matching book:\n%s", line); foundCount++; } } // 4. 遍历完成后统一提示结果 if (foundCount == 0) { puts("\nSorry, no matching books found. Maybe the book is not recorded yet :("); } else { printf("\nTotal %d matching books found.\n", foundCount); } // 5. 关闭文件,释放资源 fclose(myFile); return 0; } // 测试主函数 int main() { searchBookname(); return 0; }
三、额外优化建议
如果需要精确匹配图书名称(而不是子串匹配),假设你的file.txt每行的第一个字段是图书名称(比如用空格或竖线分隔),可以修改匹配逻辑:
// 示例:假设每行格式是 "书名|作者|价格",分割出书名部分 char bookName[MAX_BOOK_NAME_LEN]; if (sscanf(line, "%[^|]", bookName) == 1) { if (strcmp(bookName, targetName) == 0) { printf("Found exact match:\n%s", line); foundCount++; } }
这样就能确保只匹配完全一致的图书名称,避免子串匹配的误判。
内容的提问来源于stack exchange,提问作者Klayd Pro
相关产品推荐
相关产品推荐

