为什么这项工作? 使用CIN读取到一个字符数组比给定的输入小(Why does this wor

2019-07-23 13:58发布

我在读C ++的Primer Plus(第6版)和我已经遇到了一些示例代码在第4章,我有一个问题关于:

清单4.2 strings.cpp

// strings.cpp -- storing strings in an array
#include <iostream>
#include <cstring> // for the strlen() function
int main()
{
    using namespace std;
    const int Size = 15;
    char name1[Size]; // empty array
    char name2[Size] = "C++owboy"; // initialized array
    // NOTE: some implementations may require the static keyword
    // to initialize the array name2
    cout << "Howdy! I'm " << name2;
    cout << "! What's your name?\n";
    cin >> name1;
    cout << "Well, " << name1 << ", your name has ";
    cout << strlen(name1) << " letters and is stored\n";
    cout << "in an array of " << sizeof(name1) << " bytes.\n";
    cout << "Your initial is " << name1[0] << ".\n";
    name2[3] = '\0'; // set to null character
    cout << "Here are the first 3 characters of my name: ";
    cout << name2 << endl;
    return 0;
}

该代码本身不会造成任何混乱,但我一直在通过运行它,我受到了一定的场景迷惑。

名1初始化为字符数组的15个元素的长度 - 我是正确的思维本应持有的字符串长度为14个字符? 最终焦应预留一个字符串结束,对不对?

如果我输入我的名字作为HowCanIPossiblyFitThisEntireStringIn? ,我得到下面的输出:

你好! 我是C ++ owboy! 你叫什么名字?

HowCanIPossiblyFitThisEntireStringIn?

那么,HowCanIPossiblyFitThisEntireStringIn?你的名字有37个字母和存储

在15个字节的阵列。

您最初是H.

这里有我的名字的前3个字符:C ++

如何我进入全名被存储在哪里? 如果我通过代码,CIN读入后NAME1,Visual Studio中告诉我,它包含的元素0 - 14日,随着最后一个是字符“Y”(“HowCanIPossibly ...)我想从这个假设任何额外费用。输入的数据已经被截断而失败,但这显然并非如此,因为下面COUT成功写全名到控制台。

为了好奇,任何人都可以赐教,以这里发生了什么? 为了记录在案,我使用的Visual Studio 2012快。

Answer 1:

你写越过数组的边界。 C ++标准不说,这应该是一个错误; 它说,这是不确定的行为。 这意味着,任何事情都有可能发生,包括看似正常工作。 简单地说,你的代码没有良好定义的行为,所以你不应该相信它的工作。

我们可以想像,为什么它可能工作虽然。 前15个字符将很好地配合到数组:

|H|o|w|C|a|n|I|P|o|s|s|i|b|l|y|F|i|t|T|h|i|s|E|n|t|i|r|e|S|t|r|i|n|g|I|n|?|...
^                             ^
|    These characters fit     |
         in the array

字符的其余部分被写入以下存储位置。 现在,请记住,空字符,这是用来终止C风格的字符串,被定义为具有表示这是所有0位。 现在,如果下面的位置包含位置? 在所有0位,字符串将显示为空值终止。

但事实是,这是不确定的。 这恰好工作。 不幸的是,这是最可怕的类型错误的,因为它可以看似很长一段时间,直到有一天,你从你非常非常愤怒的客户开始越来越调用工作。



Answer 2:

你可以使用istream::get与缓冲区和缓冲区的大小:

cin.get(name1, Size);

正如其他人指出,这是更容易使用std::string

std::string name1;
cin >> name;


文章来源: Why does this work? Using cin to read to a char array smaller than given input