当输入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";
}
答案 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
,其中ct
为use_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
。
如果没有一个新值取代原始价值,原始价值不受干扰。