C语言字符串处理问题:原数组被意外修改,求助排查原因
问题原因分析
1. 数组传参的本质是指针传递
C语言中,栈上数组传递给函数时不会生成副本——函数接收到的是数组首元素的指针。也就是说,stripSpaces里的noSpace指针直接指向usrStr的内存空间,函数内对noSpace的修改(覆盖字符、添加终止符'\0')都会直接作用于原数组,导致后续printf输出的原字符串被改变。
2. const无效的原因
你尝试给usrStr加const但没效果,核心问题在于:
- 若
main中声明const char usrStr[250];,但isPalindrome和stripSpaces的参数是char*(非const指针),把const数组传给非const指针会触发编译警告,且强制编译通过后修改const内存属于未定义行为,根本没解决原问题; - 你需要的是保护原数组不被修改,而非简单加
const修饰。
解决办法
有两种可行方案,可根据需求选择:
方案一:动态分配新内存存储去空格后的字符串(推荐)
在stripSpaces中为去空格后的字符串分配堆内存,不修改原数组,用完后释放内存避免泄漏。
修改后的完整代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> bool isPalindrome(const char string[]); char* stripSpaces(const char *noSpace); int main(void) { char usrStr[250]; printf("Please enter a string and I will check if it is a palindrome..."); scanf("%250[^\n]", usrStr); printf("\n"); isPalindrome(usrStr) ? printf("\"%s\" is a palindrome", usrStr) : printf("\"%s\" is not a palindrome", usrStr); printf("\n"); return 0; } bool isPalindrome(const char* string) { char* newStr = stripSpaces(string); if (newStr == NULL) { return false; } int middle = strlen(newStr) / 2; int len = strlen(newStr); bool isPalin = true; for(int x = 0; x < middle; x++) { if(newStr[x] != newStr[len - x - 1]) { isPalin = false; break; } } free(newStr); // 释放动态分配的内存 return isPalin; } char* stripSpaces(const char *noSpace) { int length = strlen(noSpace); int count = 0; // 先统计非空格字符数量,按需分配内存 for(int idx = 0; idx < length; idx++) { if(noSpace[idx] != ' ') { count++; } } // 分配内存(+1用于存储字符串终止符'\0') char *newStr = (char*)malloc(count + 1); if(newStr == NULL) { perror("Failed to allocate memory"); return NULL; } count = 0; for(int idx = 0; idx < length; idx++) { if(noSpace[idx] != ' ') { newStr[count] = noSpace[idx]; count++; } } newStr[count] = '\0'; return newStr; }
方案二:使用临时数组存储原字符串副本
如果不想用动态内存,可在isPalindrome中创建临时数组,复制原字符串后对副本执行去空格操作,原数组不受影响。
修改后的核心代码:
bool isPalindrome(const char* string) { char tempStr[250]; // 临时数组长度与原数组一致 strcpy(tempStr, string); // 复制原字符串到临时数组 char* newStr = stripSpaces(tempStr); // 对临时数组去空格 int middle = strlen(newStr) / 2; int len = strlen(newStr); for(int x = 0; x < middle; x++) { if(newStr[x] != newStr[len - x - 1]) { return false; } } return true; } // stripSpaces函数可保持原实现,建议参数改为char*明确操作临时数组 char* stripSpaces(char *noSpace) { int length = strlen(noSpace); int count = 0; for(int idx = 0; idx < length; idx++) { if(noSpace[idx] != ' ') { noSpace[count] = noSpace[idx]; count++; } } noSpace[count] = '\0'; return noSpace; }
内容的提问来源于stack exchange,提问作者Charles H
相关产品推荐
相关产品推荐

