繁体   English   中英

关于 C++ 输入行为

[英]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::stringchar数组。 如果你正在使用std::string喜欢std::getlinegetistreamgetline

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM