C ++ - 反转两个字母的字符数组会产生未知行为吗?

时间:2015-10-21 09:21:38

标签: c++ arrays char

我有一个简单的程序,提示用户输入一个单词,然后将该单词输入到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?”哪里?是任何随机的符号。

为什么会这样?

4 个答案:

答案 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

Run live here.

输入:

  

输入字符串:ab

输出:

  

BA

了解Null Terminated String

答案 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;
}

因此,您可以反转任意大小的字符串。