2010-02-05 43 views
9

我正在介绍C++类,并且想知道更好的方法来检查输入是否是所需的类型。安全地提示是/否使用cin

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

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

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

这是这样做的安全方式还是我打开自己了伤的世界,我怀疑?在继续之前,确保获得我想要的输入信息会更好吗?

+2

什么是在这种情况下,10号的意义是什么? – froadie

+0

没有什么实际意义,我的意思是说循环会运行多长时间是有限制的。但即使存在风险,如果我从不增加。 – Levi

+2

我猜标题确实应该是while(condition)vs while(true){if(condition)break。 –

回答

25

我个人会一起去?

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

这不好。如果'cin'被关闭,它会永远循环喷射“你承认了吗?[y/n]”到'cout'。在测试应该读取的内容之前,始终测试输入操作的成功非常重要。 –

+1

比我的代码更具可读性和简洁性!是不是通常用于确保输入是正确的,如果不是再问一次? – Levi

+2

Do-Whiles主要用于在检查条件之前要采取某些操作的情况,如果您的条件属实,则会重复此操作。在用户输入的情况下,在检查你想要输入的条件之前,Do-Whiles很方便。 – Alex

1

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

4

使用可以使用

do { 
    program; 
} while (condition_to_repeat); 

如果算法类似,你的榜样。否则,这个例子是“安全的”,但我不确定可读性。

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

为什么不能做这种方式:

+0

你怎么知道'cin >> type'工作? –

+0

我认为目标...这是C++类的介绍。在这些早期的类中假定cin连接到命令行/操作系统,并且它不会失败。 – Erich

+0

^Windows中的Z或Unix中的^ D将导致命令行cin第一次返回EOF,第二次失败。 – jmucchiello

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',这个简单的程序将退出。

+0

这是什么解决?你是否决定假设示例代码片段是整个'main()'? – Potatoswatter

+1

所以,你只是把Levi的代码片段(这是个问题)移除到'n'条件(?!?!?!??!?!)的等式并将其作为解决方案发布?!?!?!? – Alex

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

+1。使用for循环来确定变量的范围。返回流是更多功能,仍然允许测试,如果它是一个布尔。 – 2010-02-07 02:36:19

+0

哪个变量应该被作用域? '类型'? –

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

长码是looong –

0

的做... while结构为这种做,但你也可以做循环条件的所有工作:

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

:)

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

不是完全认真的,尽管methinks把提示条件有时可以增强此类循环的逻辑(避免中断)。

0

我在这里看到两个“问题”。第一个是使用while(true)。我认为这不是一个好的做法(尽管这可能是许多人的口味问题)。一个循环内打破然而有趣的搜索:

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

这是不言自明:你运行,直到向量的末尾,但如果该元素被发现,你在到达之前打破。这是合理的。

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

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

这是另一种提示y/n的方法。 “虽然”你没有得到你想要的,“切换”你的输入。做任何你喜欢的事情;它只是工作。

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

这是没有不良后效应!

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

这也没有不良后效应!

1

这里是一个较短的方式

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