初步分析


  在C++中实现连续输入时,我们会用到 while(cin >> x >> y) ,但是它的条件判断的原理可不那么好想,这里我分享一下我对于它的见解。

  首先来看 cin >> x >> y,它的返回值是什么?首先要明确的是 cin 是一个 istream 对象,一个对象并没有返回值这个概念,那可以产生返回值的东西就只有" >> "运算符符了。在《C++ primer(第五版)》中我们知道,"">>"运算符左边是一个 istream 对象,右边是需要被输入的对象,它返回其左侧运算对象作为计算结果。也就是说, 它每次进行一次运算后返回的都是 istream 对象,在这里就是标准输入 cin。

   ">>"运算符背后的机制是引用与运算元重载,这种选项可以更方便地返回左值(左值就是可以被取地址运算符 & 操作的变量),而 istream::opreator>>() 就需要返回左值,才能做到 (cin >> x) >> y。

  这就是为什么 std::cin >> x >> y; 可以等价于 (std::cin >> x) >> y; 和 std::cin >> x; std::cin >> y; 的原因。

  知道了返回值是什么后,问题还是没有解决,因为我们不知道如何判断一个对象的值是 TRUE 还是 FALSE ,看来得深究一下 cin 对象了。

cin 对象的深入理解


  

  通过查阅资料,我们知道 cin 是行缓冲。对于行缓冲的描述,man手册里有如下的一句话可以很好的说明什么是行缓冲:

深入理解 while(cin >> x >> y)-LMLPHP

  大概意思是:cin 是行缓冲,你从键盘上输入一串字符,这一串字符首先会被缓冲区保存下来。每当你按下回车键的时候,cin 就会检测输入缓冲区是否有可读的数据。在这里,cin 会检查键盘输入是否有流结束标志 CTRL + X (我用的是 Linux,Windows是 CTRL + Z) 和 CTRL + D(EOF)。在这里我翻阅了网上资料,发现检查的方法一共有两种,一种是阻塞式检查,一种是非阻塞式检查。

  阻塞式检查是这样:只有在你按下回车后才能检查之前是否输入了 CTRL + X。

  非阻塞式检查是这样:只要你按了 CTRL + D,就立即响应。如果你按下 CTRL + D 之前还有字符,此时 CTRL + D 相当于是回车的作用,会把你之前从键盘输入的字符输入缓冲区供读取使用。

  我们拿一个程序验证一下所讨论的两种检查方式:

//This program's name is 1.cpp
#include<iostream>

int main(void)
{
    int i;
    cout << (cin >> i) << endl;
    ;
}  

  Input:

    1、从键盘输入:“12345" + CTRL + D;

    2、从键盘输入:CTRL + D;

    3、从键盘输入:"12345" + CTRL + X;

    4、从键盘输入:CTRL + X。

  Output:

  深入理解 while(cin &gt;&gt; x &gt;&gt; y)-LMLPHP

  结果:

    1、立马响应,同时将12345读入输入缓冲区并输出括号里的值;

    2、立马响应,输出括号里值,此时 cin 对象值为0

    3、先不响应,再输入回车后立马响应,同时读入”12345“

    4、先不响应,再输入回车后立马响应,此时 cin 对象值为0

  

总结


  

  标题中的两个条件判断都可以这么想:由于 cin 是行缓冲且存在两种阻塞检查机制,当你按下 CTRL + D 或者 按下 CTRL + X + 回车,cin 接收到流结束标志,使得  cin 的值为0,导致条件判断为 FALSE。这是我个人的分析,可能有部分知识不严谨,欢迎指正。

05-11 17:51