[英]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;
}
执行结果是
输入:“abc\\n”
输出:第一个字符串是:abc 第二个字符串是:第三个字符串是:(奇怪的字符)
你能解释为什么第二个cin没有得到输入吗?
我预计 cin 会从流缓冲区中读取前导空格并忽略它们并读取新字符串。
让我们从调整程序以检查错误开始。
#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;
}
结果应该是这样的
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>
我们可以看到第二次和第三次读取失败。 这是为什么? 为了找出答案,我们需要做一点阅读。 这是std::istream::get
的一些高质量文档
相关的重载是数字 3,但 3 只是调用数字 4 并将分隔符设置为'\\n'
并且 4 表示两件重要的事情,
字符将被提取并存储,直到发生以下任一情况:
- 已存储
count-1
字符- 文件结束条件出现在输入序列中(
setstate(eofbit)
)- 下一个可用的输入字符 c 等于
delim
,由Traits::eq(c, delim)
。 不提取此字符(与basic_istream::getline()
)
如果未提取字符,则调用
setstate(failbit)
。 在任何情况下,如果 count>0,空字符 (CharT() 将存储在数组的下一个连续位置。
因此,如果您只得到一个换行符,在这种情况下 delim,则输出字符串arr2
以 null 终止并且流被置于失败状态,因为没有从流中提取任何字符,这使得流无法读取,直到通过清除它来确认失败。 这就是我们所看到的:空字符串和失败位。
为什么字符串是空的? 为什么不提示输入? 因为cin >> arr1
从流中读取一个以空格分隔的标记。 它将忽略直到令牌开头的所有空白,但它会在流中的令牌之后留下空白。
如果您键入 abc 并按回车键,“abc\\n”将进入流。 cin >> arr1
将 "abc" 读入arr1
。 "\\n" 保留在cin.get(arr2, ArrSize)
找到它的流中。 "\\n" 立即满足get
退出条件,因此get
停止并将 "\\n" 留在流中。 没有提取字符。 设置失败位并且arr2
为空终止。
cin>>arr3
随后失败,因为您无法从失败的流中读取。 没有被放置在arr3
,所以当arr3
被印刷,它是未终结和<<
保持打印,直到它找到一个终止子。 这是垃圾字符,尽管从技术上讲任何事情都可能发生。
该问题没有具体说明如何处理cin >> arr1
之后剩余的数据。 常见的解决方案是从流中删除包括换行符在内的所有内容
cin.ignore(numeric_limits<streamsize>::max(), '\n');
但是,如果您想将行上剩余的任何字符用于arr2
,则必须更加棘手。 例如,始终读取行,从行中构建istringstream
,然后按照本答案的选项 2 中的方法解析istringstream
。
旁注:用>>
读入字符数组总是有风险的,因为它会一直读到找到空格为止。 如果程序从流中读取数组的大小而没有找到空白,那么你很糟糕。 get
知道其溢出之前停止。 >>
没有。 另一方面, get
将读取直到找到行尾,而不仅仅是单个空格分隔的标记。
>>
进入std::string
会做正确的事情并调整string
大小以适应输入。 通常更喜欢std::string
到char
数组。 如果你正在使用std::string
喜欢std::getline
来get
或istream
的getline
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.