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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:58:32