C++中数组越界问题
运行环境
本次程序的运行环境是C-Free 5.0.
今天写程序,想要实现判断一个字符串是否是回文字符串的问题,代码如下:
void Reverse(char *str, int from, int to){
if(NULL == str)
return ;
while(from < to){
char temp = str[from];
str[from++] = str[to];
str[to--] = temp;
}
}
bool IsPalindrome(char *str){
char *p = str;
Reverse(str, 0, strlen(str)-1);
int begin = 0;
while(begin < strlen(str)){
if(p[begin] != str[begin])
return false;
++begin;
}
return true;
}
写这个代码的时候出现了问题,那就是无论输入的字符串为何值,结果都为true。这个问题其实是深拷贝与浅拷贝的问题,
char *p = str;
该代码属于浅拷贝,指针p和str都指向同一个地址,因此当翻转str过后,p指向的值也发生变化,和str相同。因此需要执行深拷贝。所以改代码如下:
bool IsPalindrome(char *str){
char *p = NULL;
strcpy(p, str);
cout << p << endl;
Reverse(str, 0, strlen(str)-1);
int begin = 0;
while(begin < strlen(str)){
if(p[begin] != str[begin])
return false;
++begin;
}
return true;
}
结果在运行的时候又出现问题,编译没有出错。这个结果很容易分析,因为strcpy()执行的是深拷贝,因此指针p需要申请空间,而不能为NULL,因此需要修改
char *p = new char[strlen(str)];
修改过后就可以很简单的判断该字符串是否为回文。但是自己想要亲手实现以下一下strcpy的过程,于是有代码:
bool IsPalindrome(char *str){
char *p = new char[strlen(str)];
int i=0;
while(i < strlen(str)){
p[i] = str[i];
i++;
}
Reverse(str, 0, strlen(str)-1);
int begin = 0;
while(begin < strlen(str)){
if(p[begin] != str[begin])
return false;
++begin;
}
return true;
}
这个代码的运行结果很诡异,因为添加了很多莫名其妙的数字,虽然到最后结果是正确的,但是对此我还是很有疑惑。因为我p数组的大小是给定了的,就为strlen(str),但是当打印出p过后发现其大小大于strlen(str),首先就感觉是数组越界了,但是我已经定义了数组的大小,为何在赋值完成过后还会越界呢?经过分析发现是因为我们将数组p赋值过后,没有在最后一步加上结束符’\0’,因此p就会一直往后寻找,直到发现’\0’才视为数组结束。修改代码如下
while(i < strlen(str)){
p[i] = str[i];
i++;
}
p[i] = '\0';
解决了该问题,通过该问题我们发现,在使用数组进行深拷贝的时候,我们规定的数组大小似乎是没用的,因为当赋值过后,数组只看结尾的符’\0’,找到结尾符,就表明数组的大小是多少,并且在C++中,也没有给与特定的处理,因此当忘记添加p[i] = '\0';
时,就很容易出现一些莫名其妙的错误。因此建议尽量使用函数库提供的函数strcpy()。
我还测试了当使用IO输入时的情况,发现IO输入会在字符结尾自动加上’\0’符号
int size;
cin >> size;
char *p = new char[size];
for(int i=0; i<size+1; i++)
cin >> p[i];
cout<<p<<endl;
cout<<strlen(p)<<endl;