std::getline(std::cin, string) 可能因键盘输入而失败的方式
Ways std::getline(std::cin, string) can fail from keyboard input
我正在编写此函数来请求特定的输入类型。 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) 在用户的键盘输入下失败的问题?
此外,为什么
我必须按回车键 2 次
output = get_type<std::string>(prompt) ;
行到 运行 在 if.
内
std::getline
如果您之前使用过 stdin
而未清除故障位并且输入超过 std::string::max_size
则可能会失败(请参阅 Davis Herring 的评论)。
否则,我知道除了 EOF (^Z/^D
).
没有办法让 std::getline
失败
但是,您的代码有一些小的改进:
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";
}
}
如评论中所述,在某些系统上需要在stdin
上使用clearerr
。如果您的系统需要,只需取消注释 std::clearerr(stdin);
.
因为你的 2x <Enter>
问题:忽略语句是不必要的。您只需忽略下一个输入(这就是为什么您必须点击 <Enter>
两次)。
我正在编写此函数来请求特定的输入类型。 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) 在用户的键盘输入下失败的问题?
此外,为什么
我必须按回车键 2 次output = get_type<std::string>(prompt) ;
行到 运行 在 if.
内std::getline
如果您之前使用过 stdin
而未清除故障位并且输入超过 std::string::max_size
则可能会失败(请参阅 Davis Herring 的评论)。
否则,我知道除了 EOF (^Z/^D
).
std::getline
失败
但是,您的代码有一些小的改进:
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";
}
}
如评论中所述,在某些系统上需要在stdin
上使用clearerr
。如果您的系统需要,只需取消注释 std::clearerr(stdin);
.
因为你的 2x <Enter>
问题:忽略语句是不必要的。您只需忽略下一个输入(这就是为什么您必须点击 <Enter>
两次)。