C语言递归实现字符串转全大写函数测试失败问题排查
C语言递归实现字符串转大写函数测试失败问题修复
问题背景
- 开发需求:使用C语言编写递归函数,将包含任意字符的字符串转换为全大写形式,实现过程禁止使用
toupper()及其他同类内置大小写转换函数 - 初始实现代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> char* allCapStringRec(char str[]) { if (str[0] == '\0' ) return 0; if (str[0] >= 'a' && str[0] <= 'z') str[0] = str[0] - 32; return allCapStringRec(str+1); }
- 测试代码:
void Test3(char str[], char expected[], int dec) { char *result = allCapStringRec(str); if (strcmp(result, expected) != 0) printf("allCapStringRec => Your Output is %s, Expected: %s\n", result, expected); } int main() { Test3("123321", "123321", 4); Test3("abBba", "ABBBA", 4); Test3("ab$cd", "AB$CD", 4); printf("done"); return 0; }
- 实际运行报错:
allCapStringRec => Your Output is , Expected: 123321
错误原因定位
代码存在1个核心逻辑错误,另有1个潜在隐患:
- 递归返回值逻辑完全错误
每一层递归都直接返回下一层递归的调用结果,最终整个函数返回的是递归到最深处(字符串末尾\0位置)的返回值。终止条件中写的return 0;会返回空指针NULL,测试代码把空指针传入strcmp会直接读取异常;就算把终止条件改成返回当前指针,最终返回的也是指向字符串末尾结束符的指针,strcmp从结束符位置开始比较,得到的结果就是空字符串,和当前看到的输出完全一致。 - 潜在隐患:字符串字面量不可修改
测试代码中直接传入了"123321"这类字符串字面量作为入参,字符串字面量存储在内存只读区域,直接修改会触发段错误,属于测试代码的编写问题,实际调用时应该先将字面量复制到可写的字符数组中再传入函数。
修复后代码
只需要调整递归的返回逻辑,递归处理后续字符串后,返回当前层的字符串起始地址即可,这样最外层调用最终会返回原字符串的首地址:
char* allCapStringRec(char str[]) { // 递归终止:到达字符串末尾,返回当前指针 if (str[0] == '\0') { return str; } // 小写字母转大写(ASCII码中小写比对应大写大32) if (str[0] >= 'a' && str[0] <= 'z') { str[0] -= 32; } // 递归处理后续字符,不需要接收递归返回值 allCapStringRec(str + 1); // 返回当前层的字符串起始地址,最外层会返回原字符串首地址 return str; }
修复后函数会原地修改传入的可写字符串,并且返回字符串首地址,完全符合测试代码的调用要求。
补充:如果要适配测试代码中直接传入字符串字面量的场景,需要在函数内部先申请足够的内存复制原字符串,再对复制后的字符串做递归转换,最后返回复制后字符串的首地址即可,注意使用后需要手动释放内存避免泄漏。
内容的提问来源于stack exchange,提问作者Peace and Love
相关产品推荐
相关产品推荐

