There is a little progamka, everything is nothing, but faced with a strange difficulty. Attached is a simple menu code that is wrapped in a do while loop and sends the user to other submenus via switch. Accepts the entered values ​​from 0 to 7. When entering "0" the program is closed. Here's the problem: cin.clear () and cin.ignore () reset the flags and clear the buffer after each input, which eliminates the difficulty of incorrect input (select has type int), forcing it to repeat until it is entered Something intelligible, what the program expects. But there is one small "but." When entering numbers in cin, no errors are written, the cycle is simply restarted if the number does not fit. But if you enter any character, an error will appear in the stream, and after working with cin.clear () cin.ignore (), the select variable will magically (?) Be equal to "0" and the program will close. You can of course rearrange this function for 9, for example, but you want to understand the topic and do it more or less without crutches.

do { // Starting <do while> cycle for selection. Wro cout << "Input: "; cin >> select; // This var lives only in private sector in current class cin.clear(); //сбрасываем ошибку cin.ignore(numeric_limits<streamsize>::max(), '\n'); //удаляем все из буфера до перевода строки switch (select) { case 0: exit (0); case 1: menuVariables(); break; case 2: menuCycles(); break; case 3: menuArrays(); break; case 4: menuFunctions(); break; case 5: menuOperators(); break; case 6: menuPointers(); break; case 7: menuLibraries(); break; case 666: cout << "\nBingo, you're little satan's follower. But try something in 1-7 range, please.\n\n"; break; default: cout << "\nWrong input. Try again!\n" << endl; } } while (select < 1 || select > 7); } 

I can not find intelligible documentation on cin and its methods. Rather, that is - I can not overpower. Either I am stupid, or it is written in such a language, not for a beginner. I would be grateful if you tell me the solution and even briefly chew for the tankers. Thank!

    2 answers 2

    Just change the logic inside the loop by adding an if statement.

     do { // Starting <do while> cycle for selection. Wro cout << "Input: "; if ( not ( cin >> select ) ) { cin.clear(); //сбрасываем ошибку cin.ignore(numeric_limits<streamsize>::max(), '\n'); //удаляем все из буфера до перевода строки } else { switch (select) { case 0: exit (0); case 1: menuVariables(); break; case 2: menuCycles(); break; case 3: menuArrays(); break; case 4: menuFunctions(); break; case 5: menuOperators(); break; case 6: menuPointers(); break; case 7: menuLibraries(); break; case 666: cout << "\nBingo, you're little satan's follower. But try something in 1-7 range, please.\n\n"; break; default: cout << "\nWrong input. Try again!\n" << endl; break; } } } while ( true ); } 
    • Wow Direction caught. That is, if cin falls into error, then the fork goes to "wash" and returns to cout on the grounds that nothing was taken into the stream? And if the error flag did not fall, flips to the switch? Thank! Can such an implementation be used to overflow a buffer, or is it quite an acceptable design? - deflore08
    • @ deflore08 This is a generally accepted approach. - Vlad from Moscow
    • Thanks I'll know. :) - deflore08

    I would do it this way:

     typedef void (*menuFunc)(); void exitFunc() { exit(0); } // Создаем массив функций; каждый `func[i]` представляет собой // вызываемую для значения i функцию. Например, для 1 - это // menuVariables. exitFunc() сделана специально, чтобы для // 0 вызывать exit(0). menuFunc func[] = { exitFunc, menuVariables, menuCycles, menuArrays, menuFunctions, menuOperators, menuPointers, menuLibraries }; ... for(unsigned int select;; сout << "OK, what is your choise now? ") { // Пока не прочитано значение select или прочитанное значение // больше 7 - сбрасываем cin и просим новый ввод. while(!((cin>>select) && (select <= 7))) { cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "Wrong input. Try again: "; } // Если все введено верно - т.е. именно число, и это // число от 1 до 7 - просто вызываем соответствующую функцию. func[select](); } 

    Not compiled, but the idea seems to be clear?

    • To be honest, it's very roughly, I'm completely green, and it looks like the "slang" of fluent in a foreign language :)). I will try to guess: the array is declared with all menu items, then the for loop is started, which starts the while inside itself, and if cin eats an unsigned integer not more than 7, the required string is called from the array via select. If cin choked with some kind of gibberish, go wash and everything is new .. I don’t understand how menuFunc works, well, it’s already necessary to repeat the arrays, I’m not sure. And the solution looks very concise, thanks for the idea! - deflore08
    • See the added comments to the code. - Harry
    • Exhaustive! Thanks for your time and effort! :) can we not mark 2 answers as a solution? :( - deflore08
    • No, you can only give a plus (upper triangle), but only one is taken as an exhaustive answer :) - Harry