You need to enable JavaScript to run this app. C语言如何在文本文件中搜索排除子串的独立精确关键词
优惠活动
大模型
产品
解决方案
定价
更多

C语言如何在文本文件中搜索排除子串的独立精确关键词

独立整词关键词匹配的实现方案

现有代码的问题定位

  • 原代码使用strstr做无边界的子串匹配,只要行内任意位置出现关键词字符序列就判定为命中,无法过滤掉关键词作为子串嵌入其他单词的场景,实现不了独立整词匹配的目标,比如关键词为a时,cap、macaroni单词里内嵌的a都会被误判为匹配项
  • 缺少fopen操作的返回值校验,当目标文件不存在或无读取权限时,后续的文件读取操作会触发未定义行为
  • 读取行的方式用fscanf的%[^\n]格式,没有可靠的边界保护,超长行可能造成缓冲区溢出

整词匹配的判断规则

要满足题目要求的“关键词为独立单词形式,前后边界为空白字符”的匹配逻辑,当检索到关键词在当前行的出现位置时,必须同时校验两个方向的边界:

  • 左边界:关键词的起始位置要么是整行的首个字符,要么紧邻左侧的字符为空白字符(空格、制表符、换行符等)
  • 右边界:关键词的结束位置要么是整行的最后一个有效字符,要么紧邻右侧的字符为空白字符

改进后的可运行代码

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXLINESIZE 1024
#define MAXKEYWORD 256

// 校验匹配位置是否符合独立整词的边界要求
int is_valid_word_boundary(const char *line, const char *match_pos, const char *keyword) {
    size_t keyword_len = strlen(keyword);
    // 校验左边界
    if (match_pos != line) {
        // 非行首位置时,左侧必须是空白字符才算合法边界
        if (!isspace(*(match_pos - 1))) {
            return 0;
        }
    }
    // 校验右边界
    const char *right_pos = match_pos + keyword_len;
    if (*right_pos != '\0') {
        // 非行尾位置时,右侧必须是空白字符才算合法边界
        if (!isspace(*right_pos)) {
            return 0;
        }
    }
    return 1;
}

int main()
{
    FILE* file = fopen("yankee.txt", "r");
    // 增加文件打开失败的异常处理
    if (file == NULL) {
        perror("打开文件失败");
        return 1;
    }
    int linenumber = 0;
    const char *keyword = "a";
    char keywordline[MAXLINESIZE];

    // 用fgets替代原有的fscanf读取行,避免缓冲区溢出
    while (fgets(keywordline, MAXLINESIZE, file) != NULL)
    {
        linenumber++;
        // 移除读入行末尾自带的换行符,避免干扰边界判断
        keywordline[strcspn(keywordline, "\n")] = '\0';
        
        int matched = 0;
        const char *search_pos = keywordline;
        // 遍历整行检索所有可能的关键词出现位置
        while ((search_pos = strstr(search_pos, keyword)) != NULL) {
            // 校验当前匹配位置的边界是否合法
            if (is_valid_word_boundary(keywordline, search_pos, keyword)) {
                matched = 1;
                break;
            }
            // 跳过当前位置,避免循环死锁
            search_pos++;
        }
        if (matched) {
            printf("linenumber = %d\n'%s'\n\n", linenumber, keywordline);
        }
    }
    fclose(file);
    return 0;
}

运行效果

针对题目给出的测试文本,上述代码的输出和预期完全一致:

linenumber = 2 
'riding on a pony'

linenumber = 3
'Stuck a feather in his cap'

代码会自动过滤掉第4行And called it macaroni.中内嵌在macaroni单词里的字母a,也不会把第1行没有独立a出现的内容纳入匹配结果。

内容的提问来源于stack exchange,提问作者YeetCode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 13:06:03