[英]About c++ input behavior
#include <iostream>
using namespace std;
const int ArrSize = 400;
int main()
{
char arr1[ArrSize];
char arr2[ArrSize];
char arr3[ArrSize];
cout << "enter the first string ";
cin >> arr1;
cout << "enter the second string ";
cin.get(arr2, ArrSize);
cout << "enter the thrid string ";
cin>>arr3;
cout << endl << endl;
cout << "first string is: " << arr1 << "\n";
cout << "second string is: " << arr2 << "\n";
cout << "thrid string is: " << arr3 << "\n";
return 0;
}
execution result is执行结果是
input : "abc\\n"输入:“abc\\n”
output : first string is: abc second string is: thrid string is:(strange characters)输出:第一个字符串是:abc 第二个字符串是:第三个字符串是:(奇怪的字符)
Can you explain why the second cin didn't get input?你能解释为什么第二个cin没有得到输入吗?
I expected that cin would read leading white spaces form the stream buffer and ignore them and read new string.我预计 cin 会从流缓冲区中读取前导空格并忽略它们并读取新字符串。
Let's start by adjusting the program to check for errors.让我们从调整程序以检查错误开始。
#include <iostream>
using namespace std;
const int ArrSize = 400;
int main()
{
char arr1[ArrSize];
char arr2[ArrSize];
char arr3[ArrSize];
cout << "enter the first string ";
if (!(cin >> arr1))
{
cout << "Failed cin >> arr1\n";
}
cout << "enter the second string ";
if (!cin.get(arr2, ArrSize))
{
cout << "Failed cin.get(arr2, ArrSize)\n";
}
cout << "enter the third string ";
if (!(cin>>arr3))
{
cout << "Failed cin >> arr3\n";
}
cout << endl << endl;
cout << "first string is: " << arr1 << "\n";
cout << "second string is: " << arr2 << "\n";
cout << "third string is: " << arr3 << "\n";
return 0;
}
The results should be something like结果应该是这样的
enter the first string abc
enter the second string Failed cin.get(arr2, ArrSize)
enter the third string Failed cin >> arr3
first string is: abc
second string is:
third string is: <garbage here>
We can see that the second and third reads failed.我们可以看到第二次和第三次读取失败。 Why is that?
这是为什么? To find out, we need to do a little reading.
为了找出答案,我们需要做一点阅读。 Here's some high-quality documentation for
std::istream::get
这是
std::istream::get
的一些高质量文档
The relevant overload is number 3, but 3 just calls number 4 with the delimiter set to '\\n'
and 4 says two important things,相关的重载是数字 3,但 3 只是调用数字 4 并将分隔符设置为
'\\n'
并且 4 表示两件重要的事情,
Characters are extracted and stored until any of the following occurs:
字符将被提取并存储,直到发生以下任一情况:
count-1
characters have been stored已存储
count-1
字符- end of file condition occurs in the input sequence (
setstate(eofbit)
is called)文件结束条件出现在输入序列中(
setstate(eofbit)
)- the next available input character c equals
delim
, as determined byTraits::eq(c, delim)
.下一个可用的输入字符 c 等于
delim
,由Traits::eq(c, delim)
。 This character is not extracted (unlikebasic_istream::getline()
)不提取此字符(与
basic_istream::getline()
)
If no characters were extracted, calls
setstate(failbit)
.如果未提取字符,则调用
setstate(failbit)
。 In any case, if count>0, a null character (CharT() is stored in the next successive location of the array.在任何情况下,如果 count>0,空字符 (CharT() 将存储在数组的下一个连续位置。
So if you only get a newline, delim in this case, the output string arr2
is null terminated and the stream is placed into fail state because no characters were extracted from the stream, making the stream unreadable until the failure is acknowledged by clearing it.因此,如果您只得到一个换行符,在这种情况下 delim,则输出字符串
arr2
以 null 终止并且流被置于失败状态,因为没有从流中提取任何字符,这使得流无法读取,直到通过清除它来确认失败。 This is what we are seeing: an empty string and fail bit.这就是我们所看到的:空字符串和失败位。
Why is the string empty?为什么字符串是空的? Why didn't it prompt for input?
为什么不提示输入? Because
cin >> arr1
reads one whitespace-delimited token from the stream.因为
cin >> arr1
从流中读取一个以空格分隔的标记。 It will ignore all whitespace up to the start of the token, but it leaves the whitespace after the token in the stream.它将忽略直到令牌开头的所有空白,但它会在流中的令牌之后留下空白。
If you type abc and hit enter, "abc\\n" goes into the stream.如果您键入 abc 并按回车键,“abc\\n”将进入流。
cin >> arr1
reads "abc" into arr1
. cin >> arr1
将 "abc" 读入arr1
。 The "\\n" stays in the stream where cin.get(arr2, ArrSize)
finds it. "\\n" 保留在
cin.get(arr2, ArrSize)
找到它的流中。 The get
exit condition is immediately satisfied by the "\\n", so get
stops and leaves the "\\n" in the stream. "\\n" 立即满足
get
退出条件,因此get
停止并将 "\\n" 留在流中。 No characters were extracted.没有提取字符。 Fail bit is set and
arr2
is null terminated.设置失败位并且
arr2
为空终止。
cin>>arr3
subsequently fails because you can't read from a failed stream. cin>>arr3
随后失败,因为您无法从失败的流中读取。 Nothing is placed in arr3
, so when arr3
is printed, it is unterminated and <<
keeps printing until it finds a terminator.没有被放置在
arr3
,所以当arr3
被印刷,它是未终结和<<
保持打印,直到它找到一个终止子。 This is the garbage characters, though technically anything can happen .这是垃圾字符,尽管从技术上讲任何事情都可能发生。
The question does not specify what is to be done with data left over after cin >> arr1
.该问题没有具体说明如何处理
cin >> arr1
之后剩余的数据。 Common solutions are to remove everything up to and including the newline character from the stream with常见的解决方案是从流中删除包括换行符在内的所有内容
cin.ignore(numeric_limits<streamsize>::max(), '\n');
but if you want to use any characters left on the line for arr2
, you'll have to be trickier.但是,如果您想将行上剩余的任何字符用于
arr2
,则必须更加棘手。 For example, always read lines, build an istringstream
out of the line, and then parse the istringstream
as is done in option 2 of this answer .例如,始终读取行,从行中构建
istringstream
,然后按照本答案的选项 2 中的方法解析istringstream
。
Side note: Reading into character arrays with >>
is always risky because it will keep reading until whitespace is found.旁注:用
>>
读入字符数组总是有风险的,因为它会一直读到找到空格为止。 If the program reads the size of the array from the stream without finding whitepace, sucks to be you .如果程序从流中读取数组的大小而没有找到空白,那么你很糟糕。
get
knows to stop before its overflowed. get
知道其溢出之前停止。 >>
doesn't. >>
没有。 On the other hand, get
will read until it finds the end of the line, not just a single whitespace delimited token.另一方面,
get
将读取直到找到行尾,而不仅仅是单个空格分隔的标记。
>>
into a std::string
will do the right thing and resize the string
to fit the input. >>
进入std::string
会做正确的事情并调整string
大小以适应输入。 Generally prefer std::string
to char
arrays.通常更喜欢
std::string
到char
数组。 And if you are using std::string
prefer std::getline
to get
or istream
's getline
.如果你正在使用
std::string
喜欢std::getline
来get
或istream
的getline
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.