当我输入Ctrl + Z完成下面的循环时,我在变量z中得到空字符串.为什么?

Bel*_*loc 1 c++ visual-studio-2013

z[]当输入EOF(Windows中为Ctrl + Z)完成循环时,缓冲区在其第一个字节中获取空字符.为什么是这样?

#include <iostream>
using namespace std;

int main()
{
    char z[10];
    while( cin >> z ) cout << z << '\n';

    if( cin.eof() ) cout << z << "End of input\n";
}
Run Code Online (Sandbox Code Playgroud)

这不会发生在下面,即z保持从键盘读取最后一个字符.

#include <iostream>
using namespace std;

int main()
{
    char z;
    while( cin >> z ) cout << z << '\n';

    if( cin.eof() ) cout << z << "End of input\n";
}
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 5

因为标准是这样说的!

你给流看起来像C字符串缓冲区.即使提取导致设置了失败位,它也希望终止它放在该缓冲区中的内容(在这种情况下,为空字符串).

这是从以下定义的证明template<class charT, class traits> basic_istream<charT,traits>& operator>>(basic_istream<charT,traits>& in, charT* s):

[C++11: 27.7.2.2.3/8]:提取并存储字符,直到出现以下任何一种情况:

  • n-1 字符存储;
  • 文件末尾出现在输入序列上;
  • ct.is(ct.space,c)对于下一个可用的输入字符是真的c,其中ctuse_facet<ctype<charT> >(in.getloc()).

[C++11: 27.7.2.2.3/9]: operator>>然后charT()在下一个位置存储一个空字节(),如果没有提取字符,它可能是第一个位置.

值得一提的是,这也是提取到a的情况std::string:

[C++11: 21.4.8.9/1]: 效果:表现为格式化输入函数(27.7.2.2.1).在构造一个岗哨对象之后,如果哨兵转换为真,则调用str.erase()然后从中提取角色is并将其附加到str就像通过调用一样str.append(1,c).如果is.width()大于零,则追加的最大字符数为n is.width(); 否则n是str.max_size().提取并附加字符,直到出现以下任何一种情况:

  • n 字符存储;
  • 文件结束发生在输入序列上;
  • isspace(c,is.getloc())true下一个可用的输入字符c

也就是说,对于char缓冲区和a std::string,如果流在提取之前处于有效状态,即使提取在到达EOF之前拉出零字符,您的输入对象也将被"清除".

单一的规则不存在这样的规则char:

[C++11: 27.7.2.2.3/12]: 效果:表现为格式化的输入成员(如27.7.2.2.1中所述)in.在构造了一个岗哨对象之后in,如果一个角色可用,则从中提取一个角色并将其存储c.否则,函数调用in.setstate(failbit).

如果没有新的值取代它,原始值不会受到干扰.