使用递归函数检测回文字符串:C代码异常排查求助
问题排查与修正
1. 全局变量size的误用与长度跟踪错误
全局size固定为100000,完全没反映实际字符串的有效长度。预处理和递归过程中,你需要跟踪过滤后的真实字符串长度,而非这个固定值。另外delete函数里的size--仅修改了局部变量,外部的长度完全没更新,导致后续所有基于size的操作全错。
2. 预处理阶段的逻辑错误
- 大写字母处理错误:你用
continue跳过了大写字母,没有转成小写,违反了“不区分大小写”的要求,应该将大写转小写后保留。 - 删除字符后循环变量未回退:删除
i位置的字符后,后续字符会前移一位,此时i应保持不变,否则会跳过下一个待处理的字符。 - 使用废弃的
gets函数:gets无缓冲区长度检查,容易引发溢出,应替换为fgets。
3. 递归函数的致命问题
- 缺少递归终止条件:当字符串长度≤1时,本身就是回文,需直接返回1,否则会无限递归导致栈溢出。
- 不必要的字符串修改:判断回文不需要删除字符,仅通过左右索引对比即可,修改字符串不仅效率低,还容易引入长度跟踪错误。
- 递归参数错误:每次递归传递的
size未正确反映当前字符串的实际长度,因为原delete函数无法更新外部长度。
修正后的代码
#include <stdio.h> #include <ctype.h> #include <string.h> // 递归判断回文,用左右索引,不修改原字符串 int isPalindrome(const char word[], int left, int right) { // 终止条件:左右指针相遇或交叉,说明是回文 if (left >= right) { return 1; } // 双重保险:跳过非字母(预处理已过滤,此处做冗余校验) while (left < right && !isalpha(word[left])) { left++; } while (left < right && !isalpha(word[right])) { right--; } // 不区分大小写对比 if (tolower(word[left]) != tolower(word[right])) { return 0; } // 递归检查内部子串 return isPalindrome(word, left + 1, right - 1); } int main() { char word[100001]; // 预留一个位置存字符串结束符 // 用fgets读取输入,避免缓冲区溢出 if (fgets(word, sizeof(word), stdin) == NULL) { printf("NO\n"); return 1; } // 去掉fgets可能读取的换行符 size_t len = strlen(word); if (len > 0 && word[len - 1] == '\n') { word[len - 1] = '\0'; len--; } // 预处理:过滤非字母,统一转小写 char filtered[100001]; int idx = 0; for (size_t i = 0; i < len; i++) { if (isalpha(word[i])) { filtered[idx++] = tolower(word[i]); } } filtered[idx] = '\0'; // 添加字符串结束符 // 判断回文并输出结果 if (isPalindrome(filtered, 0, idx - 1)) { printf("YES\n"); } else { printf("NO\n"); } return 0; }
修正说明
- 用单独的
filtered数组存储预处理后的字符串,避免修改原字符串,同时准确跟踪有效长度。 - 递归函数改用左右索引实现,无需修改字符串,逻辑清晰且终止条件明确。
- 替换
gets为fgets并处理换行符,保证输入安全。 - 预处理阶段直接过滤非字母并转小写,逻辑简洁,避免了删除字符带来的索引混乱问题。
内容的提问来源于stack exchange,提问作者Fateme
相关产品推荐
相关产品推荐

