首页 > 解决方案 > std::getline(std::cin, string) 可能因键盘输入而失败的方式

问题描述

我正在编写这个函数来询问特定的输入类型。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 2 次

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

在 if 内运行的行。

标签: c++cingetline

解决方案


std::getline如果您之前使用stdin过而没有清除故障位并且输入超出,则可能会失败std::string::max_size(请参阅 Davis Herring 的评论)。std::getline否则,我知道除了 EOF ( ^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";
    }
}

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

由于您的 2x<Enter>问题:忽略语句是不必要的。您只需忽略下一个输入(这就是您必须点击<Enter>两次的原因)。


推荐阅读