即使输入是另一种数据类型,C ++ cin.fail()也会执行并移至下一行

时间:2019-05-15 01:56:27

标签: c++ validation switch-statement cin

我正在使用get.fail()来检查输入中是否有任何字符,如果有,我想给用户一个重新输入的机会。但是,无论哪种情况,只要输入前面有一个整数,该程序似乎仍会接受用户输入。假设w11w,该程序将告诉用户,它仅接受整数,而后者接受输入并移至下一行,然后引起另一个问题。

    void userChoice(int input){

        switch(input)
        {
            case 1:
                insert();
                break;
            case 2:
                display();  
                break;
            case 3:
                update_data();
                break;
            case 4:
                delete_position();
                break;
            case 5:
                cout<<"Thank you for using the program\n";
                exit(0);
                break;
            case 6:
                tellSize();
                break;
            default:
                cout<<"Not an option\n";
                cin>>input;

                while(cin.fail())
                {
                    cin.clear();
                    cin.ignore(INT_MAX, '\n'); 
                    cin>>input;
                    break; 
                }
                userChoice(input);
        }

    }

参考上面的代码,说我输入了1w。程序仍然会执行情况1,就好像没有什么问题,然后w会以某种方式传递到insert()函数中,这不是我想要的。我希望该程序无论是1w还是w1都允许用户重新输入,总之,如果有字符,我不希望程序移至下一行。整数输入。

tl; dr: 为什么当cin为1w时,下面的代码仍然可以执行,为什么不打印“仅输入数字”,因为其中有一个字符?

编辑:这是我制作的一个快速程序,要重现我所遇到的错误,我首先输入1h,这是我所遇到的第一个错误,为什么在有字符{{ 1}}中输入?然后在第二个输入中,我输入h并打印出2w,由于输入中有一个字符2,该程序是否应该循环while循环?

w

1 个答案:

答案 0 :(得分:1)

从您的评论看来,您似乎只需要整数输入,并且即使1w可能是1也不想允许在诸如int这样的整数后面输入其他字符。转换为w的同时,.ignore(...)仍未读取,将在您调用.clear()之后由.clear()删除。 (如上所述,您现在对.ignore(...).peek()的使用是正确的。

如果这是您的意图,则需要一种方法来检查用户输入的整数后面是否还有其他内容。要在不存在任何障碍的情况下以非阻塞方式进行操作,则有两种选择。 (例如,您可以在下一个字符string处输入字符-但您只能得到一个字符,或者可以使用 line _ 输入法) line _ 该方法允许您将整个用户输入行读入getline(),然后提取整数值并检查输入行中是否还包含其他任何内容。

最直接的方法是从用void menu()读取的数据行中创建一个std::basic_stringstream。这种方法消耗了整个用户输入行,并为您提供了从行中提取任何所需信息所需的所有工具。这样做也不会影响您以后的任何用户输入。

虽然我建议您结合使用void options(int input)menu()函数,以便仅使用一个函数来处理菜单的输入处理-将它分成两部分并没有什么错,除了可能性重复的几行代码。以下只是有关如何处理#include <sstream> #include <string> 函数以仅允许整数输入的建议。您可以使其适应代码的其余部分。

您将需要几个附加条件:

#define

我也会#define MENUFIRST 1 /* first valid entry */ #define MENULAST 1 /* last valid entry */ 接受第一个和最后一个菜单项,因此您可以在代码中使用这些常量,并且可以在添加菜单时轻松更改这些常量,例如

1

注意:,仅允许输入menu()作为有效菜单项)

要使用上述方法来限制您void menu(){ int user_input = 0; string line, unwanted; for (;;) { /* loop continually until valid input received */ cout << "\nEnter 1 to print something: "; if (!getline (cin, line)) { /* read an entire line at a time */ cerr << "(user canceled or unrecoverable stream error)\n"; return; } stringstream ss (line); /* create a stringstream from line */ if (!(ss >> user_input)) { /* test if valid integer read */ /* test eof() or bad() */ if (ss.eof() || ss.bad()) /* if not, did user cancel or err */ cerr << "(empty-input or unreconverable error)\n"; else if (ss.fail()) /* if failbit - wasn't an int */ cerr << "error: invalid integer input.\n"; } else if (ss >> unwanted) { /* are there unwanted chars? */ cerr << "error: additional characters following user_input.\n"; user_input = 0; /* reset user_input zero */ } /* was int outside MENUFIRST-to-MENULAST? */ else if (user_input < MENUFIRST || MENULAST < user_input) cerr << "error: integer not a valid menu selection.\n"; else /* valid input!, break read loop */ break; } options(user_input); } 的功能,可以执行以下操作:

// bool fail;

鉴于以上讨论,这些评论应该是不言自明的,但是如果您有任何疑问,请告诉我。将该功能与其余代码一起使用(并注释未使用的$ ./bin/menu_int Enter 1 to print something: w1 error: invalid integer input. Enter 1 to print something: $#%&^#&$ (cat steps on keyboard) !#$%%^%*() error: invalid integer input. Enter 1 to print something: 1w error: additional characters following user_input. Enter 1 to print something: -1 error: integer not a valid menu selection. Enter 1 to print something: 24 error: integer not a valid menu selection. Enter 1 to print something: 1 Enter the amount of cake 3 3 ),您可以测试它是否满足您的要求,例如

使用/输出示例

menu()

还请注意,您的EOF函数现在将正确捕获用户按下 Ctrl + d (或 Ctrl + z 在Windows上)取消输入并正常退出。