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

C++固定数组长度计算异常:子串匹配函数中length_two值不符问题

问题原因与解决方案

这个问题是C++里一个非常经典的陷阱——数组作为函数参数传递时会自动退化为指针,这直接导致了你看到的sizeof计算结果异常。

具体原因拆解

  • 在main函数里直接计算sizeof(two)时,two是一个实实在在的char数组(存储字符串"every"时,实际长度是6:5个字符加末尾的\0终止符),所以sizeof(two)/sizeof(*two)得到6,减1后得到5,这和你单独测试的结果一致。
  • 但当你把two传入func函数时,函数参数里的char two[]写法只是语法糖,本质上等价于char* two。这时候sizeof(two)计算的是指针的大小(在64位系统里指针大小是8字节),而sizeof(*two)是char的大小(1字节),所以8/1 -1 =7,正好是你看到的函数内的结果。

C++设计成这样是为了避免传递整个数组带来的性能开销,所以函数内部无法通过sizeof获取原数组的真实长度。

额外问题:原代码的越界风险

另外你的原代码还有一个隐藏问题:循环条件i<length_one会导致数组越界。比如当i接近length_one时,i+j会超出one数组的范围,可能引发未定义行为。正确的循环边界应该是i <= len_one - len_two。

修正方案

这里给你几种可靠的解决思路:

方案1:手动传递数组长度

修改函数参数,把两个数组的长度作为额外参数传入,同时用strlen(专门用于计算C风格字符串长度)代替sizeof,避免终止符的干扰:

#include <iostream>
#include <cstring>
using namespace std;

int func(char one[], char two[], int len_one, int len_two) { 
    int result = 0;
    // 限制循环边界,防止越界
    for(int i = 0; i <= len_one - len_two; ++i){ 
        bool isMatch = true;
        for(int j = 0; j < len_two; ++j){ 
            if(two[j] != one[i + j]){
                isMatch = false;
                break;
            }
        }
        if(isMatch){ 
            result++; 
        }
    }
    return result;
}

int main(){ 
    char one[] = "Hello everybody";
    char two[]= "every";
    int len_one = strlen(one);
    int len_two = strlen(two);
    cout << func(one, two, len_one, len_two);
}

方案2:使用std::string更简洁安全

如果可以改用C++的std::string,代码会更简洁,还能直接利用标准库的find方法:

#include <iostream>
#include <string>
using namespace std;

int countSubstring(const string& mainStr, const string& subStr) {
    int count = 0;
    size_t currentPos = 0;
    // 循环查找子串,直到找不到为止
    while ((currentPos = mainStr.find(subStr, currentPos)) != string::npos) {
        count++;
        currentPos += subStr.length(); // 移动位置,避免重复匹配同一处
    }
    return count;
}

int main() {
    string one = "Hello everybody";
    string two = "every";
    cout << countSubstring(one, two) << endl;
    return 0;
}

方案3:用模板推导数组大小(仅适用于固定大小数组)

如果你必须使用原生数组且不想手动传长度,可以用模板函数让编译器推导数组的大小:

#include <iostream>
#include <cstring>
using namespace std;

template <size_t Len1, size_t Len2>
int func(char (&one)[Len1], char (&two)[Len2]) { 
    int len_one = Len1 - 1; // 减去终止符的长度
    int len_two = Len2 - 1;
    int result = 0;
    for(int i = 0; i <= len_one - len_two; ++i){ 
        bool isMatch = true;
        for(int j = 0; j < len_two; ++j){ 
            if(two[j] != one[i + j]){
                isMatch = false;
                break;
            }
        }
        if(isMatch){ 
            result++; 
        }
    }
    return result;
}

int main(){ 
    char one[] = "Hello everybody";
    char two[]= "every";
    cout << func(one, two);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:48:09