在将用户输入验证为int时,陷入无限循环

时间:2014-12-17 15:10:22

标签: c++ while-loop switch-statement cin

所以我使用do while循环显示菜单,如下所示,我希望用户通过菜单提示,直到他们进行有效选择 - 输入数字1,2,3或4然后,我想使用switch case语句来识别用户选择并执行相关的代码块。但是,当涉及输入验证时,我如何考虑用户输入字母而不是数字?下面的代码成功地继续下一次迭代,以便在用户输入字母时重新启动用户,除非它进入连续循环。

int selection;

do{
    cout << "Which option would you like to select? (select 1, 2, or 3)";
    cout << "1: Option 1" << endl;
    cout << "2: Option 2" << endl;
    cout << "3: Option 2" << endl;

    if(!(cin >> selection)){
        cout << "Please select an integer from 1-4." << endl;
        cin.clear()
    }

}while(selection != (1) or (2) or (3) or (4));

我尝试使用istringstream插入下面的代码,将用户响应从字符串流式传输到while循环内的int,作为尝试解决问题的替代方法,但无济于事。

string temp;
cin >> temp;
clearInputBuffer();
istringstream is(temp);
is >> selection;

更新代码 - 仍然无限循环(仅当用户输入字母时)                                                        字符;整数行为预期)

int selection;

do{
    cout << "Which option would you like to select? (select 1, 2, or 3)";
    cout << "1: Option 1" << endl;
    cout << "2: Option 2" << endl;
    cout << "3: Option 2" << endl;

    if(std::cin >> selection){
       cout << "Enter the new price: ";
    }

    else if(!std::cin.eof()){
       cout << "Please select an integer from 1-4." << endl;
       cin.clear();
    }


    }while(selection != 1 && selection != 2 && selection != 3 && selection != 4);

7 个答案:

答案 0 :(得分:5)

while(selection != (1) or (2) or (3) or (4));

虽然你很可能想要

,但在语法上是有效的
while(selection != 1 && selection != 2 && selection != 3 && selection != 4);

您的原始表达相当于

while((selection != 1) || (2) || (3) || (4)) 

(2)(3)(4)被评估为true,这会使您的循环无限,因为anything || truetrue

如果有人想知道,是的,C ++允许写and代替&&or代替||,而not代替{{ 1}}等等你必须“禁用语言扩展”才能在MSVC上看到这一点。

[更新]

另一个问题是,在非整数输入的情况下,变量选择保持未初始化。在else子句中,例如,给它一个值-1。

答案 1 :(得分:1)

显而易见的方法是实际检查输入是否成功,如果不是这种情况处理错误,例如,写入错误消息,清除流,忽略字符或行,然后再试一次:

if (std::cin >> selection) {
    // do something with the good selection
}
else if (!std::cin.eof()) {
    std::cin.clear();
    std::cout << "invalid character ('" << char(std::cin.get()) << "') ignored\n";
}

您的代码会检查流并清除它,但它不会提取有问题的字符。当你检查选择是否在范围内时,事情已经很糟糕并且会保持这种状态。

你继续检查范围。当逻辑或运算符评估每个单独的元素时,您的方法不能很好地工作。一种方法是检查输入的值是否是特定rnage的成员,例如,使用

int const valid[] = { 1, 2, 3, 4 };
if (std::end() == std::find(std::begin(valid), std::end(valid), selection)) {
    std::cout << "chosen invalid selection (" << selection << ")\n";
}

单独检查每个选择的替代方案对于少量选择可能是可行的,但是当选项范围变得更大时,这是不可行的。不可否认,一旦你有更多的选择,你实际上就把钥匙和操作放在了一起:

std::unordered_map<int, std::function<void()>> actions;
bool done = false;

// set up different operations for the respective actions, e.g.:
actions.insert(std::make_pair(1, [](){ std::cout << "hello, world\n"; }));
actions.insert(std::make_pair(2, [&](){ done = true; std::cout << "goodbye\n"; }))

int selection;
if (std::cin >> selection) {
    auto it = actions.find(selection);
    if (it != actions.end()) {
        (it->second)();
    }
    else {
        std::cout << "unknown action selection " << selection << '\n';
    }
}

答案 2 :(得分:0)

试试这个

while(selection != (1) and selection != (2) and selection != (3) and selection != (4));

答案 3 :(得分:0)

selection != (1) or (2) or (3) or (4)

非零整数将评估为true,因此这相当于:

(selection != (1)) or true or true or true

始终评估为true

解决这个问题的方法是逐个比较

while(selection != 1 && selection != 2 && selection != 3 && selection != 4)

答案 4 :(得分:0)

(2),(3,(4)总是如此,这就是为什么你被困在一个无限的角色里。试试:

while(selection != 1 && selection != 2 && selection != 3 and selection != 4);

答案 5 :(得分:0)

更短的版本:

while (selection <= 4 && selection >= 1)

答案 6 :(得分:0)

我得到它的工作,原始帖子中提供的更新缺少一个额外的代码行,我通过筛选有关在while循环中验证输入的其他问题来确定。我认为@DietmarKühl试图在他的建议中说明类似的东西,但是我的编译器不喜欢代码,我不太明白它所以我不知道如何让它工作。我会玩你关于通过Dietmar验证范围的建议,所以感谢您的意见。

还要感谢所有为这个主题做出贡献的人,特别是99%的人这样做而没有听起来居高临下:-)但总有一个。我可以在here找到我找到我遗失的语句的线程,并且添加到代码中的行在下面的代码中用注释标识。再次感谢!

int selection;

do{
    cout << "Which option would you like to select? (select 1, 2, or 3)";
    cout << "1: Option 1" << endl;
    cout << "2: Option 2" << endl;
    cout << "3: Option 2" << endl;

    if(std::cin >> selection){
        cout << "Enter the new price: ";
    }

    else if(!std::cin.eof()){
        cout << "Please select an integer from 1-4." << endl;
        cin.clear();
        cin.ignore(10000,'\n'); // this line eliminated the infinite loop issue
    }


}while(selection != 1 && selection != 2 && selection != 3 && selection != 4);