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

时间:2015-05-25 19:12:17

标签: c++ visual-studio-2013

当输入EOF(Windows中为Ctrl + Z)以完成循环时,缓冲区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";
}

这不会发生在下面,即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";
}

1 个答案:

答案 0 :(得分: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()),如果没有提取字符,则可能是第一个位置。 < / p>

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

  

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

     
      存储
  • str.max_size()个字符;
  •   
  • 输入序列上出现文件结尾;
  •   
  • n对于下一个可用输入字符isspace(c,is.getloc())
  • true   

也就是说,对于c缓冲区和char,如果流在提取之前处于有效状态,即使提取在到达EOF之前拉出零字符,您的输入对象将被清除&#34;。

单个std::string

不存在此类规则
  

char 效果:表现得像[C++11: 27.7.2.2.3/12]:中的格式化输入成员(如27.7.2.2.1所述)。构建sentry对象后,将从in中提取一个字符(如果有的话),并将其存储在in中。否则,该函数调用c

如果没有一个新值取代原始价值,原始价值不受干扰。