澄清 C++ 中 cin 的基本行为

Clarification on a basic behavior of cin in C++

我很好奇为什么 cin 会有以下行为。我想我可能有 对其行为的一些误解。

考虑这个简单的代码。此代码要求输入一些输入,所有这些都在最后一个语句中打印出来。

#include <iostream>
#include <string>
using namespace std;

int main(int argc, char** argv) {
  cout << "Please enter your input: " ;
  int a=3, b=87; // initialized to some random integers
  string s = "Mary" ; // initialized to a random string
  cin >> a ;
  cin >> b ;
  getline(cin,s);
  cout << "You entered the following " << a << "  " << b << "  " << s << endl;
  return 0;  
}

现在如果输入是 12 34 cat 输出是 12 34 cat 这是意料之中的。

但是,如果输入为 cat 23 dog,则输出为 0 87 Mary

这就是我认为这是出乎意料的原因:

cin >> a 应该会失败,因为 cat 无法转换为整数。但是,a 被替换为我认为是垃圾值的值。

现在输入的第二个数是整数23,cin >> b一定成功。然而这个操作似乎失败了,并且 b 继续保留其原始值,这与 a 发生的情况不同。

类似地getline无法将字符串<space>dog放入字符串s 它继续保留其原始值 Mary

我的问题如下。

  1. 某些cin操作的失败是否强制所有的失败 使用 >> 运算符或 getline 函数的后续 cin 操作。

  2. 为什么第一个cin操作失败改变了a的值 而 bs 的初始值没有改变?

Does the failure of some cin operation mandate the failure of all subsequent cin operations using the >> operator or the getline function.

是的。直到您使用 cin.clear() 清除错误。此外,当提取失败时,字符会留在缓冲区中,因此如果您尝试再次读取相同类型,它将再次失败。

Why did the failure of the first cin operation change the value of a whereas the initial values of b and s were unchanged?

因为(自 C++11 起),它被定义为在从(先前)有效流提取失败的情况下将值更改为 0。在 C++11 之前,它会保持不变。对于处于错误状态的流,该操作不执行任何操作,这就是 bs 未更改的原因。

您应该使用cin.good() 函数或shorthand 表示法if(cin),如@AndyG 所述,以检查cin 对象的状态。变量 a 的类型是 int 那么你怎么输入字符串?因此,它为变量 a.

提供了意外的输出
  1. Does the failure of some cin operation mandate the failure of all subsequent cin operations using the >> operator or the getline function.

是的。您的代码希望以完全相同的顺序读取输入值

cin >> a ; // 1st integer value
cin >> b ; // 2nd integer value
getline(cin,s); // string value

给它一个像

这样的输入
cat 23 dog

导致在尝试读取第一个 int 值时在 cin 上设置 fail() 状态,并且以下 operator>>() 调用中的 none 将成功.


cin >> a should fail since catcannot be converted into an integer. However, a gets replaced with what I presume is a garbage value.

这不是垃圾值,但定义明确,请参阅下面的参考引文。

Now since the second number of the input is an integer 23, cin >> b must succeed. Yet this operation seems to fail, and b continues to retain its original value unlike what happened to a.

不,这个假设是错误的,如前所述,cin 此时处于 fail() 状态,并且完全跳过进一步输入的解析。

您必须在每次 operator>>() 调用后调用 clear(),以确保输入将被解析:

cin >> a ; // 1st integer value
cin.clear();
cin >> b ; // 2nd integer value
cin.clear();
getline(cin,s); // string value

  1. Why did the failure of the first cin operation change the value of a whereas the initial values of b and s were unchanged?

因为 std::basic_istream::operator>>() 的引用说

"If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set. (since C++11)"