为何squeeze函数中变量k位置未变却出现值差异?
关于squeeze函数中字符串终止符位置导致输出差异的分析
问题场景
实现squeeze函数以删除字符串s1中所有与s2匹配的字符时,输入hello\nhell\n出现两种不同结果:
- 当
s1a[k] = '\0'放在两层for循环外时,k值为5,输出ooooo - 将该语句移至外层
for循环内、内层for循环外后,k值为1,输出o - 未添加终止符时,
s1a末尾会残留5个'o'
代码分析
错误的终止符位置(两层循环外)
// 错误写法 for (i = 0; s2a[i] != '\0'; i++) { for (k = j = 0; s1a[j] != '\0'; j++) { if (s1a[j] != s2a[i]) s1a[k++] = s1a[j]; } } s1a[k] = '\0'; // 终止符放在所有循环结束后
这种写法的问题在于:每次处理s2的一个字符后,没有及时截断s1a,导致内存中残留之前的旧字符。例如:
- 处理
s2的'h'后,s1a变为ello,但未加终止符,原字符串末尾的'o'依然保留 - 后续处理
'e'、'l'时,内层循环会遍历到原字符串的终止符位置(而非当前有效字符的末尾),不断将非匹配字符复制到s1a中,最终导致s1a被填充多个'o' - 所有循环结束后才设置终止符,此时
k是最后一次内层循环遍历到原字符串末尾的计数,因此输出5个'o'
正确的终止符位置(外层循环内)
// 正确写法 for (i = 0; s2a[i] != '\0'; i++) { for (k = j = 0; s1a[j] != '\0'; j++) { if (s1a[j] != s2a[i]) s1a[k++] = s1a[j]; } s1a[k] = '\0'; // 每次处理完一个s2字符后截断s1a }
这种写法的核心是每次过滤完s2的一个字符后,立即用终止符截断s1a,确保下一次内层循环仅遍历当前已过滤的有效字符串:
- 处理
'h'后,s1a被截断为ello(长度4) - 处理
'e'后,截断为llo(长度3) - 处理第一个
'l'后,截断为o(长度1) - 处理第二个
'l'后,s1a仍为o(长度1),最终输出正确结果o
关键结论
C语言中的字符串依赖'\0'作为终止标记,必须在每次修改字符串长度后及时设置终止符,否则后续字符串操作会读取到内存中残留的无效数据,导致输出异常。当前将终止符放在外层循环内的版本,才是符合需求的正确实现。
内容的提问来源于stack exchange,提问作者Haru Hoshizora
相关产品推荐
相关产品推荐

