键盘输入可能导致std :: getline(std :: cin,string)失败

时间:2019-02-09 04:35:38

标签: c++ cin getline

我正在编写此函数以询问特定的输入类型。 is_type只是验证可以使用stringstream将接收到的字符串强制转换为所需的类型。

template<typename T>
T get_type(std::string prompt)
{
    T output;
    std::cout << prompt;
    std::string Input;
    while (std::getline(std::cin, Input) && !is_type<T>(Input))
    {
            std::cout << "Invalid input type. Please try again:\n"
              << prompt;
    }

    std::stringstream(Input) >> output;
       return output;
}

除了我输入ctrl + Z以外,这些功能似乎都可以正常工作。 处理此问题的合适方法是什么?

我添加了:

template<typename T>
    T get_type(std::string prompt)
    {
        T output;
        std::cout << prompt;
        std::string Input;
        while (std::getline(std::cin, Input) && !is_type<T>(Input))
        {
                std::cout << "Invalid input type. Please try again:\n"
              << prompt;
        }
        if (!std::cin)
        {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        output = get_type<std::string>(prompt) ;
        return output;
        }
        std::stringstream(Input) >> output;
           return output;
    }

例如在ctrl + Z之后再次询问输入 这能解决我的std :: getline(std :: cin,std :: string)在用户输入的kewyboard下失败的问题吗?

此外,为什么我必须按Enter键两次

output = get_type<std::string>(prompt) ; 

行在if中运行。

1 个答案:

答案 0 :(得分:0)

如果您以前使用过std::getline而没有清除故障位,并且输入超过了stdin,则

std::string::max_size可能会失败(请参阅Davis Herring的评论)。 否则,除非通过EOF(std::getline),否则我无法让^Z/^D失败。

但是,这是您的代码,做了一些小的改进:

template<typename T>
T get_type(std::string prompt)
{
    T output;
    std::string input;
    while(true)
    {
        std::cout << prompt;
        std::getline(std::cin, input);
        std::istringstream iss(input);
        if(!std::cin)
        {
            std::cin.clear();
        //  std::clearerr(stdin);
        }
        else if(iss >> output && iss.eof())
            return output;

        std::cout << "Invalid input type. Please try again:\n";
    }
}

如评论中所述,在某些系统上必须在clearerr上使用stdin。如果您的系统需要这样做,只需取消注释std::clearerr(stdin);

由于您有2个<Enter>问题,因此:无需使用ignore语句。您只需忽略下一个输入(这就是为什么您必须打两次<Enter>的原因。)