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
相关产品推荐
相关产品推荐

