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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:32:53  来源:igfitidea点击:

Safely prompt for yes/no with cin

c++user-input

提问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::getlineto 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<10but 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!

这没有不良后遗症!