我有一个简单的程序,提示用户输入一个单词,然后将该单词输入到char数组中,如下所示:
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int a;
char s[1024],r[1024];
cout<<"Enter a string:";
cin>>s;
for(int i = 0; s[i] != '\0'; i++) {
a = i + 1;
}
for(int i = 0; i < a; i++) {
r[i] = s[a-i-1];
}
cout << r;
return 0;
}
正如您将很快看到的那样,输入一个2个字母的单词会产生意外行为,任何其他长度的单词都可以。
例如,我尝试输入“Hi”。而不是预期的输出“iH”,它产生“iH?”哪里?是任何随机的符号。
为什么会这样?
答案 0 :(得分:4)
您忘记在r
中终止字符串。这意味着r
的输出将在您从s
复制的字符之后继续,直到它找到终结符'\0'
,可能超出数组的范围。
这很糟糕,因为本地非静态变量(包括数组及其内容)将具有 indeterminate 值,并且读取此数据会导致未定义的行为(因为它将超出数组的范围)。
有两个简单的解决方案:第一个是将r
数组初始化为全零:
char r[1024] = { '\0' };
另一种是在复制循环后添加终结符:
r[a] = '\0';
答案 1 :(得分:2)
由于您刚刚声明r
而未初始化,r
包含垃圾。替换r
的某些值后,您不会使用空字符'\0'
来终止它。因此,打印r
将发生未定义的行为。
所以将'\0'
放入
r[a] = '\0';
这将终止字符串r
。
输入:
输入字符串:ab
输出:
BA
答案 2 :(得分:1)
您没有复制\0
字节,因为当到达0字节(字符串结尾)时,循环退出,但不包括它。由于r
未初始化,因此它包含一个用于定义未定义行为的随机字符,因为可能不存在0字节。
所以要么
memset(r, 0, sizeof(r));
在复制完成后,在复制完成后,在适当的位置使用0字节完成字符串。
r[a] = 0;
或另一种选择是:
for(int i = 0; s[i] != '\0'; i++)
a = i + 1;
a++; // One additional char to account for the 0-byte.
答案 3 :(得分:1)
为什么不首先使用STL
,尤其是std::reverse
:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int main(int argc, char* argv[]) {
char s[1024];
cout << "Enter a string:";
cin >> s;
std::reverse(s, s + strlen(s));
cout << s;
return 0;
}
因此,您可以反转任意大小的字符串。