为什么 if(!(cin >> int)) 在第一次迭代中接受十进制数而不是其他的?

Why does if(!(cin >> int)) accept a decimal number in the first iteration but not the other ones?

下面的程序来自 google 教程,它非常简单,除了我输入十进制数的时候。

#include <iostream>
using namespace std;

int main() {
  int input_var = 0;
  do {
    cout << "Enter a number (-1 = quit): ";

    if (!(cin >> input_var)) {
      cout << "You entered a non-numeric. Exiting..." << endl;
      break;
    }

    if (input_var != -1) {
      cout << "You entered " << input_var << endl;
    }

  } while (input_var != -1);

  cout << "All done." << endl;
  return 0;
}

如果输入是一个整数(不是-1)它输出:

Enter a number (-1 = quit): 5
You entered 5
Enter a number (-1 = quit):

如果是非数字:

Enter a number (-1 = quit): p
You entered a non-numeric. Exiting...
All done.

这正是它应该如何工作的,但如果它是十进制数:

Enter a number (-1 = quit): 5.9
You entered 5
Enter a number (-1 = quit): You entered a non-numeric. Exiting...
All done.

我知道如果将 doublefloat 分配给 int 时 c++ 的行为,在这种情况下,它第一次输出截断的十进制数, cin 不会变成 false 但第二次迭代它甚至不接受输入。

我会理解它是否从一开始就不接受它,或者如果它只是截断了小数点并且表现得就像它有一个 int 作为输入一样,但为什么它的表现不同第一个循环和第二个循环不同?

I know how C++ behaves if you assign a double or a float to an int and in this case it outputs the truncated decimal number.

这实际上不是这里发生的事情。没有将 floatdouble 值分配给您的 int。当您尝试 输入 一个整数 5.9 时,它会成功获取 5 位并停在那里,在输入流中留下 .9 。您在任何阶段都没有从输入流中提取完整的 5.9 并将其截断为整数以放入 input_var.

然后,在 next 迭代中,它发现 .9,发现它不是一个有效的整数,并采取相应的行动,就像您输入 p.

这在 C++14 的第 22.4.2.1 num_get() 节中有极其详细的介绍,但最重要的是在该描述的第 3 阶段:

The sequence of chars accumulated in stage 2 (the field) is converted to a numeric value by the rules of one of the functions declared in the header <cstdlib>:

For a signed integer value, the function strtoll.

我不会详细介绍strtoll的工作方式,因为它也需要逐步完成 ISO C99 的相当多的部分。可以说它在 6.4.4 Constants 部分结束,该部分规定整数中允许的字符,并且字符 . 根本没有出现。

cin >> input_var;

这是算子>>和这个算子returncin的一个运算。然而,当这个 cin 被传递给条件语句,如 ifwhile 时,调用 istreat 的特殊函数来评估 truefalse来自 cin 的值。此函数检查 cin 是否遇到和 EOR 或它接收到它应该接收的值。请记住 >> 是一个重载运算符,在您的情况下,该运算符被调用以获得整数值。但是,当您输入一个非整数值(在您的情况下为 double)时,它会检测到结果为假。

虽然,结果不能以相反的方式产生,即当你的 input_var 是 double 类型并且你输入一个整数时, cin 评估它是 double,但是,cin 不要截断 int 变量的小数点后的数字。