c++中cin的一个基本行为说明

Clarification on a basic behavior of cin in C++

本文关键字:一个 说明 cin c++      更新时间:2023-10-16

我很好奇为什么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必须成功。然而,这个操作似乎失败了,与a不同,b继续保留其原始值。

同样,getline无法将字符串<space>dog放入字符串s中它继续保持其原始值Mary

我的问题如下。
  1. 某些cin操作失败是否意味着所有操作失败?使用>>操作符或getline函数执行cin的后续操作。

  2. 为什么第一次cin操作失败会改变a的值而bs的初始值不变。

某个cin操作的失败是否意味着所有cin操作的失败使用>>操作符或getline的后续cin操作函数。

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

为什么第一个cin操作失败会改变a的值而b和s的初始值是不变的?

因为(从c++ 11开始),它被定义为在从(先前)有效的流中提取失败时将值更改为0。在c++ 11之前,它将保持不变。对于处于错误状态的流,该操作不做任何操作,这就是bs保持不变的原因。

  1. 使用>>操作符或getline函数时,某些cin操作失败是否会导致后续所有cin操作失败?

是的。您的代码期望按照以下顺序读取输入值

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

输入像

cat 23 dog

导致在读取第一个int值时将fail()的状态设置为cin,并且随后的operator>>()调用都不会成功。


cin >> a应该失败,因为cat不能转换为整数。然而,a被我认为是一个垃圾值所取代。

它不是垃圾值,但定义良好,参见下面的参考引用。

现在,由于输入的第二个数字是一个整数23,cin >> b必须成功。然而,这个操作似乎失败了,b继续保持其原始值,而a则不同。

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

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

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

  • 为什么第一个cin操作失败改变了a的值,而b和s的初始值不变?
  • 因为std::basic_istream::operator>>()的引用说

    "如果提取失败,将0写入value并设置failbit。如果抽取结果值太大或太小而无法匹配值,则写入std::numeric_limits<T>::max()std::numeric_limits<T>::min()并设置failbit标志。<一口>(因为c++ 11) "

    您应该使用cin.good()函数或@AndyG所说的简写符号if(cin)来检查cin对象的状态。变量a的类型是int,那么你怎么能&为什么要输入字符串?因此,它为变量a提供了意外输出。