You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:11:54