std :: cin有时挂起,有时在无效输入后会永远重复

时间:2014-07-16 01:40:54

标签: c++

在这种情况下,当标记为hang point的行收到无效输入时,例如。 abc,它重复内部do-while循环,并在再次到达该行时挂起。

// figure 1
std::string s;
do {
    do {
        std::cout<<"s = ";
        std::getline(std::cin, s);
    } while (s == "");
    double d;
    std::cout<<"d = ";
    do {
        std::cin.clear();
        std::cin>>d; // hang point
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    } while (std::cin.fail());
} while (s != "exit");

在这种情况下,程序跳过该行并永远重复执行do-while循环。

// figure 2
double d;
do {
    std::cout<<"d = ";
    std::cin.clear();
    std::cin>>d; // skip point
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while (std::cin.fail());

为什么?

最初我会问为什么figure 1挂起,并且在尝试简化示例的过程中,我提出了figure 2,并发现它没有挂起,而是永远重复。我不明白为什么figure 1figure 2做他们做的事情。

编辑:我在我为自己写的提示中输入字母数据,导致cin失败。例如

s = something
d = 3
s = something
d = a

2 个答案:

答案 0 :(得分:2)

图2:你必须在cin.ignore()之前调用cin.clear()。否则,cin.ignore将不会执行任何操作,因为cin仍处于错误状态。

double d;
do {
    if (std::cin.fail()) {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    std::cout<<"d = ";
    std::cin>>d;
} while (std::cin.fail());

答案 1 :(得分:1)

我的印象是你正在重置标志,但是cin缓冲区仍然是满的。因此,当它重新进入循环时,'d'会自动重新分配字母值(例如,您在终端输入的'abc')。因此,失败标志将被重置,循环将重复。

这是固定版本(有一些风格上的变化,抱歉):

#include <string>
#include <iostream>

int main(){
    std::string s="";
    std::string dummy="";
    while ( s!="exit"){
        s="";
        while (s==""){
            std::cout<<"s = ";
            std::getline(std::cin, s);
        }
        double d;
        std::cout<<"d = ";
        do {
            if (std::cin.fail()){
                std::cin.clear();
                std::getline(std::cin, dummy);
                std::cout << "d = ";
            }
            std::cin>>d;
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        } while (std::cin.fail());
    }
}