C语言mx_count_substr函数计数异常:预期3实际返回1求助
子串统计函数mx_count_substr输出异常排查
我写了一个统计字符串str中子串sub出现次数的函数mx_count_substr,预期对于字符串"yo, yo, yo Neo"和子串"yo"应该返回3,但实际运行后始终得到1。相关代码如下:
#include "mx_strstr.c" #include "mx_strchr.c" #include "mx_strlen.c" #include "mx_strncmp.c" #include <stdio.h> int mx_strncmp(const char *s1, const char *s2, int n); int mx_strlen(const char *s); char *mx_strchr(const char *s, int c); char *mx_strstr(const char *s1, const char *s2); int mx_count_substr(const char *str, const char *sub); int main(void) { const char str[] = "yo, yo, yo Neo"; const char sub[] = "yo"; mx_count_substr(str, sub); } int mx_count_substr(const char *str, const char *sub) { int coincidence; const char *temp = str; while(temp = mx_strstr(temp, sub)) { coincidence++; temp++; } printf("Coincidence: %i \n", coincidence); return coincidence; }
注:以下用到的标准库替代函数均为手动实现,且单独测试全部通过。
辅助函数实现
mx_strstr.c
int mx_strncmp(const char *s1, const char *s2, int n); int mx_strlen(const char *s); char *mx_strchr(const char *s, int c); char *mx_strstr(const char*s1, const char*s2); char *mx_strstr(const char*s1, const char*s2) { int i = 0; if(mx_strlen(s1) < mx_strlen(s2)) { return 0; } while(s1[i] != '\0') { if(mx_strncmp(s1, s2, mx_strlen(s2)) == 0) { return mx_strchr(s1, *s2); } i++; } return 0; }
mx_strncmp.c
int mx_strncmp(const char *s1, const char *s2, int n); int mx_strncmp(const char *s1, const char *s2, int n) { for(int i = 0; i < n; i++) { if(s1[i] != s2[i]) { return (int)(s1[i] - s2[i]); } } return 0; }
mx_strlen.c
#include <stdio.h> int mx_strlen(const char *s) { int number = 0; while(s[number] != '\0') { number++; } return number; }
mx_strchr.c
char *mx_strchr(const char *s, int c); char *mx_strchr(const char *s, int c) { for(int i = 0; s[i] != '\0'; i++) { if(s[i] == c) { return (char *)&s[i]; } } return 0; }
问题根源分析
1. mx_strstr函数逻辑错误
你的mx_strstr实现存在致命问题:循环中始终用原始的s1指针调用mx_strncmp,而非移动后的s1+i位置。也就是说,无论i怎么递增,每次都是从字符串开头开始比较,找到第一个匹配后直接返回,永远不会往后查找其他匹配项。
2. coincidence变量未初始化
mx_count_substr中的int coincidence;未初始化为0,会触发未定义行为,可能导致统计值异常。
修复方案
修复mx_strstr函数
修改循环逻辑,每次从s1+i的位置开始匹配,同时简化返回逻辑:
char *mx_strstr(const char*s1, const char*s2) { int sub_len = mx_strlen(s2); int s1_len = mx_strlen(s1); if(sub_len == 0 || s1_len < sub_len) { return 0; } for(int i = 0; i <= s1_len - sub_len; i++) { if(mx_strncmp(&s1[i], s2, sub_len) == 0) { return (char*)&s1[i]; // 直接返回匹配起始位置,无需调用mx_strchr } } return 0; }
修复mx_count_substr函数
初始化统计变量,并优化匹配后的指针移动逻辑(避免重叠统计,若需要重叠可改为temp++):
int mx_count_substr(const char *str, const char *sub) { int coincidence = 0; const char *temp = str; int sub_len = mx_strlen(sub); // 处理子串为空的边界情况 if(sub_len == 0) { return 0; } while((temp = mx_strstr(temp, sub)) != NULL) { coincidence++; temp += sub_len; // 跳过整个子串,避免重叠统计 } printf("Coincidence: %i \n", coincidence); return coincidence; }
修改后,函数即可正确统计到3次匹配。
内容的提问来源于stack exchange,提问作者ehorAKAstudent
相关产品推荐
相关产品推荐

