用cin安全地提示是/否

时间:2010-02-05 17:41:09

标签: c++ user-input

我正在介绍C ++类,我想知道一种更好的检查输入是否是所需类型的方法。

这是一个很好的方法吗?我来自PHP / PERL背景,这使我非常担心使用while循环。

char type;
while (true) {
    cout << "Were you admitted? [y/n]" << endl;
    cin >> type;

    if ((type == 'y') || (type == 'n')) {
        break;
    }
}

这是安全这样做的方式还是我打开了一个受伤的世界,我怀疑?什么是更好的方法,以确保我在继续之前得到我想要的输入?

15 个答案:

答案 0 :(得分:25)

就我个人而言:

do
{
    cout << "Were you admitted? [y/n]" << endl;
    cin >> type;
}
while( !cin.fail() && type!='y' && type!='n' );

答案 1 :(得分:9)

就个人而言,我会将提示作为一个单独的函数,这使得它将提示输出和读取响应作为逻辑表达式放入while循环中。

测试读取是否成功对于代码的正确运行至关重要。

我还希望一次使用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 = '\0';
        }
        return true;
    }
    return false;
}

void f()
{
    char type = '\0';

    while( PromptForChar( "Were you admitted? [y/n]", type ) )
    {
        if (type == 'y' || type == 'n')
        {
            // Process response
            break;
        }
    }
}

答案 2 :(得分:4)

使用可以使用

do {
    program;
} while (condition_to_repeat);

如果算法类似于您的示例。否则该示例是“安全的”,但我不确定可读性。

答案 3 :(得分:2)

为什么不这样做?

do
{
    cout << "Were you admitted? [y/n]" << endl;
    cin >> type;
}while(  type !='y' && type !='n');

答案 4 :(得分:1)

没关系。如果您希望在发生多次失败后超时,可以使用i<10但不值得。

答案 5 :(得分:1)

不要忘记让潜在用户的生活更容易解释每一步,甚至提供不区分大小写的输入。

#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;
}

答案 6 :(得分:1)

基于行的输入不必冗长,您可以使用您编写一次的单个函数将其设为succinct,但仍处理极端情况:

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;
}

答案 7 :(得分:1)

这是一个更短的方式

char type;
while (type != 'y') 
{
    cout << "Were you admitted? [y/n]" << endl;
    cin >> type;   
}

答案 8 :(得分:0)

我以前从未在PERL / PHP中编码,而是基于您的问题,这里的示例是一个简单的解决方案。

    char c;
while(true){
    cout << "Were you admitted? [y/n]" << endl;
    cin >> c;
    if(c == 'y')
        break;
}
cin.get(c);
return 0;

在输入“y”后输入“y”将继续提示您,此简单程序将退出。

答案 9 :(得分:0)

do ... while构造是为此做的,但你也可以在循环条件下完成所有工作:

while (std::cout << "Were you admitted [y/n]\n" && std::cin >> answer && !(answer == 'y' || answer == 'n'));

:)

如果你不想测试std::cin >> answer的成功(例如想要用Ctrl + Z无限循环),你可以用逗号替换&&:)

并非完全严重,即使将提示置于条件中,有时可以增强此类循环的逻辑(避免中断)。

答案 10 :(得分:0)

我在这里看到两个“问题”。第一个是使用while(true)。我不认为这是一个很好的做法(虽然这可能是许多人的品味问题)。然而,在循环中打破对搜索很有意义:

for(i = 0; i < MAX; ++i) {
  if ( v[ i ] == searchedElement ) {
      break;
  }
}

这是不言自明的:你一直运行到向量的末尾,但是如果找到了元素,你就会在到达之前中断。这是合理的。

关于从控制台获取信息,直接从cin读取会遇到很多麻烦,例如,如果输入有内容,则只返回第一个空格。 getline()是一个实用程序函数,它读取一个字符串,它几乎总是安全的。 getline()在实用程序标头中定义。您还需要字符串标题。如果您想使用EOF,请使用cstdio。

int main()
{
    int ch;
    std::string type;

    do {
        getline( std::cin, type );

        if ( cin.fail() ) {
            ch = EOF;
            break;
        }

        ch = tolower( type[ 0 ] );
    } while( ch != 'y' && ch != 'n' );

    // interesting things here...

    return 0;
}

答案 11 :(得分:0)

修改@McAden所说的内容,尝试修复错误,如果输入多个字符,测试只检查第一个字母。

    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' );

答案 12 :(得分:0)

这是提示y / n的另一种方式。 &#34;虽然&#34;你没有得到你想要的东西,&#34;切换&#34;在你的输入。做任何你喜欢的事情;它只是有效。

#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.
}

这没有任何不利的后遗症!

答案 13 :(得分:0)

提示y / n的另一种方法。 “做”这个“而”你没有得到你想要的东西。做任何你喜欢的事情;它只是有效。

#include "stdafx.h"
#include <iostream>

int main()
{
    bool accepted;
    char answer;
    do
    { // Ask for 'y' or 'n' at least once
        std::cout << "Accepted? [y/n] -> ";
        std::cin >> answer;
        if (std::cin.fail())
        {                                // not a valid character?
            std::cin.clear();
            std::cin.ignore(1024, '\n');
        }
        if (answer == 'n')
        {                                // character is 'n'?
            accepted = false;
        }
        else
        {                                // character is 'y'?
            accepted = true;
        }
         //    not valid    |or|    not 'n'     |or|    not 'y'
    } while (std::cin.fail() || !(answer == 'n') || !(answer == 'y'));  
}

这也没有不良的后遗症!

答案 14 :(得分:0)

char yn;
bool choice;
do
    {
           
        cout<<"Would you like try again?\n";
        cout<<"Y for yes N for no: ";
        cin>>yn;
    
        while (yn != 'n'&& yn != 'N'&&yn != 'y'&&yn != 'Y')
        {
            cout<<"Y or N please: ";
            cin>>yn;
        }
        
        if (yn == 'n'||yn == 'N')
            choice = false;
        if(yn == 'y'||yn == 'Y')
            choice = true;
        
    } while (choice == true);