自定义C++ String类substring函数字符数组初始化异常排查
问题分析与解决
嘿,这个问题我太熟悉啦!你遇到的乱码问题根源在于C风格字符数组必须以空终止符'\0'结尾,而你的代码里漏掉了这关键一步。
为什么会出现垃圾字符?
你当前的代码中:
char* r = new char[rlength]; for (int i = 0; i < rlength; i++) { r[i] = chars[i + startIndex]; } string s2(r);
- 你只分配了
rlength大小的内存来存储子串的字符,但没有预留额外空间存放'\0' - 当用这个字符数组构造
string对象时,它会从r的起始位置开始读取,直到找到一个'\0'才停止 - 因为你没手动添加
'\0',程序就会读取数组后面的随机内存数据,这就是你看到的"a�;�"这类垃圾字符的来源
修复方案
有两种简洁的修复方式,推荐第二种更安全的写法:
方式1:手动添加空终止符(修复原有逻辑)
修改数组分配和添加终止符:
string string::substring(unsigned int startIndex, unsigned int endIndex) const { if (startIndex >= endIndex) { return string(); } if (endIndex > length) endIndex = length; int rlength = endIndex - startIndex; // 多分配1个字节存'\0' char* r = new char[rlength + 1]; for (int i = 0; i < rlength; i++) { r[i] = chars[i + startIndex]; } // 添加空终止符 r[rlength] = '\0'; string s2(r); // 记得释放内存,避免泄漏! delete[] r; return s2; }
这里一定要记得delete[] r,不然会造成内存泄漏。
方式2:直接利用string的范围构造(更安全,无需手动管理内存)
如果你的自定义string类支持接受字符指针+长度的构造函数(类似标准std::string的string(const char* s, size_t n)),可以直接简化代码:
string string::substring(unsigned int startIndex, unsigned int endIndex) const { if (startIndex >= endIndex) { return string(); } if (endIndex > length) endIndex = length; int rlength = endIndex - startIndex; // 直接从chars的起始偏移位置,取rlength个字符构造string return string(chars + startIndex, rlength); }
这种写法完全避免了手动内存管理,也不需要依赖空终止符,更不容易出错。
验证修复效果
修复后,你的测试用例都会得到预期结果:
"This is a test".substring(9, 10)会正确返回"a",不再带有垃圾字符
额外提醒
如果你的自定义string类还没有实现带长度的构造函数,建议补上它——这会让很多字符串操作更安全,避免因为空终止符问题踩坑。
内容的提问来源于stack exchange,提问作者user9625223
相关产品推荐
相关产品推荐

