C++ 使用 cin 安全提示是/否
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2209135/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Safely prompt for yes/no with cin
提问by Levi
I'm in an intro to C++ class and I was wondering of a better method of checking if input was the desired type.
我正在介绍 C++ 类,我想知道检查输入是否为所需类型的更好方法。
Is this a good way of doing this? I come from a PHP/PERL background which makes me rather apprehensive of using while loops.
这是这样做的好方法吗?我来自 PHP/PERL 背景,这让我很担心使用 while 循环。
char type;
while (true) {
cout << "Were you admitted? [y/n]" << endl;
cin >> type;
if ((type == 'y') || (type == 'n')) {
break;
}
}
Is this a safeway of doing this or am I opening myself up to a world of hurt, which I suspect? What would be a better way of making sure I get the input I want before continuing?
这是一种安全的方式吗,还是我向一个我怀疑的伤害世界敞开心扉?确保在继续之前获得所需输入的更好方法是什么?
回答by McAden
Personally I'd go with:
我个人会选择:
do
{
cout << "Were you admitted? [y/n]" << endl;
cin >> type;
}
while( !cin.fail() && type!='y' && type!='n' );
回答by CB Bailey
Personally I'd make the prompt a separate function, this makes it putting the prompt output and reading a response a logical expression to put in a while loop.
就我个人而言,我会将提示作为一个单独的函数,这使得它可以将提示输出和读取响应作为逻辑表达式放入 while 循环中。
Testing whether the read was successful is critical to the correct functioning of the code.
测试读取是否成功对于代码的正确运行至关重要。
I'd also prefer to use std::getline
to get a line at a time as it helps reduce errors caused by reading the rest of a half read line that was the result of a partial read to earlier user responses.
我也更喜欢std::getline
一次获取一行,因为它有助于减少由于读取一半读取行的其余部分而导致的错误,这是部分读取早期用户响应的结果。
bool PromptForChar( const char* prompt, char& readch )
{
std::string tmp;
std::cout << prompt << std::endl;
if (std::getline(std::cin, tmp))
{
// Only accept single character input
if (tmp.length() == 1)
{
readch = tmp[0];
}
else
{
// For most input, char zero is an appropriate sentinel
readch = 'do {
program;
} while (condition_to_repeat);
';
}
return true;
}
return false;
}
void f()
{
char type = 'do
{
cout << "Were you admitted? [y/n]" << endl;
cin >> type;
}while( type !='y' && type !='n');
';
while( PromptForChar( "Were you admitted? [y/n]", type ) )
{
if (type == 'y' || type == 'n')
{
// Process response
break;
}
}
}
回答by Notinlist
Use can use
使用可以使用
#include <iostream>
#define MAX_USER_INPUT_ATTEMPTS 3
int _tmain(int argc, _TCHAR* argv[])
{
char input_value = ' ';
int current_attempt = 1;
while(true)
{
std::cout << "Please confirm your choice (press y[es] or n[o] and Enter): ";
std::cin >> input_value;
input_value = tolower( input_value );
if(input_value=='y' || input_value=='n')
{
break;
}
else
{
std::cout << "You have used " << current_attempt << " of " << MAX_USER_INPUT_ATTEMPTS << " attempts" << std::endl;
++current_attempt;
}
if( current_attempt > MAX_USER_INPUT_ATTEMPTS )
{
std::cout << "Warning: Maximum number of attempts reached." << std::endl;
break;
}
}
return 0;
}
if the algorithm is similar to your example. Otherwise the example is "safe", but I am not sure about the readablity.
如果算法与您的示例相似。否则这个例子是“安全的”,但我不确定可读性。
回答by Erich
Why not do it this way?
为什么不这样做呢?
char type;
while (type != 'y')
{
cout << "Were you admitted? [y/n]" << endl;
cin >> type;
}
回答by Daniel A. White
That's fine. If you want it to time out after a number of failures, you could use the i<10
but its not worth it.
没关系。如果您希望它在多次失败后超时,您可以使用 ,i<10
但它不值得。
回答by opal
And don't forget to make your potential user's life easier explaining each step and even provide the case insensitive input.
并且不要忘记让您的潜在用户的生活更容易解释每个步骤,甚至提供不区分大小写的输入。
bool yesno_repeat(char const* prompt) {
using namespace std;
while (true) {
cout << prompt << " [yn] ";
string line;
if (!getline(cin, line)) {
throw std::runtime_error("unexpected input error");
}
else if (line.size() == 1 and line.find_first_of("YyNn") != line.npos) {
return line == "Y" || line == "y";
}
}
}
int main() try {
if (yesno_repeat("Blow up?")) {
take_off_every<Zig>(); // in the future, a zig is a nuclear missile...
}
return 0;
}
catch (std::exception& e) {
std::cerr << e.what() << '\n';
return 1;
}
回答by Noyin
Here is a shorter way
这是一个更短的方法
char type;
char buffer[128];
do
{
cout << "Were you admitted? [y/n]" << endl;
cin >> buffer;
type = buffer[0];
cout << type << "\n";
}while( !cin.fail() && type!='y' && type!='n' );
回答by Noyin
Line-based input does not have to be verbose, you can make it succinct, with a single function you write once, that still handles corner cases:
基于行的输入不必冗长,您可以使其简洁,使用您编写一次的单个函数,仍然可以处理极端情况:
#include "stdafx.h"
#include <iostream>
int main()
{
bool play = true; // Initialize play to true.
char choice;
while (play) // While play is true, do the following:
{
std::cout << "Play again? [y/n] -> ";
std::cin >> choice;
switch (choice)
{
case 'n': // We can fall through here because we
play = false; // don't do anything with 'y' anyway.
case 'y': // Remember; play is already true unless
break; // we changed it to false with 'n'.
default: // We'll simply assume anything else is a fail!
std::cin.clear();
std::cin.ignore(1024, '\n');
break;
}
// Break out here and check the "while" condition again...
}
// When play becomes false, we exit the while statement.
}
回答by MichaelScaria
Modifying what @McAden said, try this fix the bug where if you enter multiple characters, the test only checks the first letter.
修改@McAden 所说的,试试这个修复错误,如果你输入多个字符,测试只检查第一个字母。
##代码##回答by Fixer
Here's another way to prompt for y/n. "While" you don't get what you want, "switch" on your input. Do whatever else you like with it; it just works.
这是提示输入 y/n 的另一种方法。“虽然”你没有得到你想要的,“切换”你的输入。用它做任何你喜欢的事情;它只是有效。
##代码##This comes with no adverse after effects!
这没有不良后遗症!