1

问题描述

例如有下面段代码

int main()
{
    int test;                        // 定义一个整型变量test
    cin >> test;                     // 输入test
    cout << endl;                    
    cout << "test=" << test << endl; // 输出test 
    return 0;    
}

当我输入字母'a'时,输出的test=0,说明当输入的数据类型与test类型不符时,会将test置为0
clipboard.png

于是,我可以通过这一点设计一个程序,当我输入的数据类型不合法时,则重新输入,否则输出test,如下图:

clipboard.png

代码实现:

int main()
{
    int test = 1;
    do
    {
        cout << "请输入数字" << endl;
        cin >> test;
    } while (!test);
    cout << "test=" << test << endl;
    return 0;
}

但是当我开始调试时,却发现了如下情况:
图片描述
在第一次循环输入不合法的数据类型后,之后的每次循环都跳过了cin语句,结果就进入了死循环

解决问题

在看了《C++ Primer》的17章第1节的内容后,我终于明白了为什么循环会跳过cin。



在此之前,需要一些准备知识:

一、cin是一个对象

cin是C++编程语言中的标准输入流对象,即istream类的对象

所以cin的本质是一个对象,是对象就要有它的属性方法,下图是在vs2017中查看到的cin的属性和方法

clipboard.png

二、输入流

首先通过一个例子简单了解一下cin输入流的工作原理

int test1;
char test2;

cin>>test1;  
{
     if(!cin.fail())
     test1 = cin.get();
}
cin>>test2;
{
     if(!cin.fail())
     test2 = cin.get();
}

首先从键盘输入“12E”,回车结束,流就会接收到一串字符"12E/n",/n为回车
图片描述
接着它就会检查流中的数据类型是否合格,然后将第一个到最后一个合格的数字字符串转成数字,赋给当前变量
图片描述
之后将流中剩下的字符交给下一个cin去处理,将字符'E'赋给了test2,到/n时则停止。

图片描述

所以,在这段代码中,当我输入字符'Q'时,由于没有合适的cin去接收流中的数据,那么将一直进行循环

int main()
{
    int test = 1;
    do
    {
        cout << "请输入数字" << endl;
        cin >> test;
    } while (!test);
    cout << "test=" << test << endl;
    return 0;
}

所以正确的做法是:当我在循环末尾依然无法接收流中的数据,那么我需要将流的状态重置,并且重新从键盘输入数据。cin对象为我们提供了三个函数来完善上述代码
cin.clear():重置流
cin.get()读取流中的数据
cin.fail():当没有读取到预期字符,则返回true
以下是完善后的代码实现:

int main()
{
    int test = 1;
    while (true)
    {
        cout << "请输入数字" << endl;
        cin >> test;
        if (cin.fail())
        {
            cin.clear();
            cin.get();
            continue;
        }
        else
        {
            break;
        }
    }
    return 0;
}


陈杰
167 声望332 粉丝

为API生,为框架死;