C语言歌曲名搜索如何实现关键词完整匹配,避免命中含该子串的长单词
歌曲关键词检索匹配问题修复方案
问题原因
当前代码使用strstr()做纯子串匹配,只要关键词出现在歌曲名任意位置就会命中,没有验证匹配到的内容是不是独立单词,才会出现搜索you命中含your的歌曲的问题。
修复思路
新增独立单词匹配校验规则,对strstr()找到的每一处匹配位置做边界校验:
- 若匹配起始位置不是字符串开头,那么前一个字符必须是非英文字母(空格、标点、数字等都可)
- 若匹配结束位置不是字符串结尾,那么后一个字符必须是非英文字母
只要存在一处满足上述规则的匹配,就判定歌曲名符合搜索条件。
修复后代码
// 需额外引入 ctype.h 头文件使用isalpha() #include <ctype.h> // 新增独立单词匹配辅助函数 int is_full_word_match(const char *src_str, const char *keyword) { int key_len = strlen(keyword); int src_len = strlen(src_str); char *match_pos = src_str; // 循环查找所有可能的匹配位置 while ((match_pos = strstr(match_pos, keyword)) != NULL) { int start_idx = match_pos - src_str; int end_idx = start_idx + key_len - 1; // 校验前边界:要么是开头,要么前一个字符不是字母 int left_valid = (start_idx == 0) || (!isalpha((unsigned char)match_pos[-1])); // 校验后边界:要么是结尾,要么后一个字符不是字母 int right_valid = (end_idx == src_len - 1) || (!isalpha((unsigned char)match_pos[key_len])); if (left_valid && right_valid) { return 1; // 找到符合要求的匹配 } match_pos++; // 跳过当前位置继续查找下一处匹配 } return 0; // 无符合要求的匹配 } int main() { // 原有变量声明等逻辑保持不变 printf("Enter the keyword: "); scanf("%s", keyWord); convert_to_lowercase(keyWord, keyWordLower); songCount = 0; for (i = 0; i < songNum; i++) { strcpy(listInfoLower, (listInfo + i)->name); convert_to_lowercase(listInfoLower, listInfoLower); // 替换原来的strstr判断 if (is_full_word_match(listInfoLower, keyWordLower)) { songCount++; } } if (songCount == 0) { printf("No songs with %s in database\n", keyWord); } else { printf("%d songs with %s\n", songCount, keyWord); for (i = 0; i < songNum; i++) { strcpy(listInfoLower, listInfo[i].name); convert_to_lowercase(listInfoLower, listInfoLower); // 同样替换判断逻辑 if (is_full_word_match(listInfoLower, keyWordLower)) { printf("%s(%d) by %s, US(%d)\n", (listInfo + i)->name, (listInfo + i)->year, (listInfo + i)->artist, (listInfo + i)-> us_rank); } } } // 原有后续逻辑保持不变 return 0; }
补充说明
如果需要支持带特殊字符的关键词匹配,或者自定义单词分隔规则,可以修改边界校验的判断逻辑,把isalpha()替换成自定义的分隔符判断即可。
内容的提问来源于stack exchange,提问作者clamp
相关产品推荐
相关产品推荐

