Results 1 to 5 of 5

Thread: [RESOLVED] Integer based console menu problem

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Aug 2012
    Posts
    75

    Resolved [RESOLVED] Integer based console menu problem

    Hi!

    I have a problem with a integer based menu that I use in my console program.

    Code:
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    
    
    int menu()
    {
    	int choice = 0;
    
    
    	do {
    		cout << "\nMenu\n" << endl;
    		cout << "[1] Do something." << endl;
    		cout << "[2] Do something else." << endl;
    		cout << "[3] Do something entirely different." << endl;
    		cout << "[4] Quit." << endl;
    		cout << "Your choice: ";
    
    		choice = 0;
    		
    		if (!(cin >> choice) || (choice < 1) || (choice > 4)) {
    			cout << "Invalid choice! \nChoice needs to be in range 1 to 4" << endl;
    			cin.clear();
    			cin.ignore(1000, '\n');
    		}
    	} while (choice < 1 || choice > 4);
    	
    	return choice;
    }
    
    
    int main()
    {
    	int choice = 0;
    
    	do {
    
    		switch (choice = menu()) {
    		case 1:
    			cout << "You chose 1!" << endl;
    			//Do something
    			break;
    		case 2:
    			cout << "You chose 2!" << endl;
    			//Do something
    			break;
    
    		case 3:
    			cout << "You chose 3!" << endl;
    			//Do something
    			break;
    
    
    		case 4:
    			/* Quit program */
    			break;
    
    		default:
    			/* Just for testing. This is not supposed to happen in runtime. */
    			cout << "Oops! Something went wrong!" << endl;
    
    		}
    	} while (choice != 4);
    
    	return 0;
    }
    Now when I input single integer it works fine. But when I insert something like "1 2 3 4" it loops all the numbers and the result is:
    Code:
    Menu
    
    [1] Do something.
    [2] Do something else.
    [3] Do something entirely different.
    [4] Quit.
    Your choice: 1 2 3 4
    You chose 1!
    
    Menu
    
    [1] Do something.
    [2] Do something else.
    [3] Do something entirely different.
    [4] Quit.
    Your choice: You chose 2!
    
    Menu
    
    [1] Do something.
    [2] Do something else.
    [3] Do something entirely different.
    [4] Quit.
    Your choice: You chose 3!
    
    Menu
    
    [1] Do something.
    [2] Do something else.
    [3] Do something entirely different.
    [4] Quit.
    Your choice:
    --------------------------------
    Process exited after 3.484 seconds with return value 0
    Press any key to continue . . .
    "1 2 3 4" is invalid input and needs to be handled. Any idea how to handle this situation?

  2. #2
    Fanatic Member 2kaud's Avatar
    Join Date
    May 2014
    Location
    England
    Posts
    1,000

    Re: Integer based console menu problem

    For the input 1 2 3 4, the stream extraction operator >> will first get the 1 leaving 2 3 4 in the stream. As this is a valid input menu() returns. The next time menu() is called the input stream still contains 2 3 4 so >> extracts 2 and continues. This repeats until either the stream is empty in which case >> will wiat until further input has been entered or an invalid number is found. Try changing
    Code:
    	return choice;
    to
    Code:
    	cin.ignore(1000, '\n');
    	return choice;
    This should remove any remaining chars from the buffer once the first valid entry has been used.
    All advice is offered in good faith only. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Aug 2012
    Posts
    75

    Re: Integer based console menu problem

    Thank you 2kaud, good explanation!

    Code:
    cin.ignore(1000, '\n');
    return choice;
    Does the trick!
    But I am wondering if this cin.ignore(1000, '\n'); "hack" is a good way in terms of integer validation. Still "1 2 3 4" is invalid input.

    I was thinking something like converting input to string, check the length of the string for example" if (string.length == 1)", check if string[0] is integer and then return true or false.
    Is this idea any good? Maybe there is some better practice to achieve what I'm after?

  4. #4
    Fanatic Member 2kaud's Avatar
    Join Date
    May 2014
    Location
    England
    Posts
    1,000

    Re: Integer based console menu problem

    If you want to count 1 2 3 4 as invalid input rather than 4 inputs of 1 then 2 then 3 then 4 then you need to read the whole line and validate. Something like this
    Code:
    string trim(const string& st)
    {
    size_t f = st.find_first_not_of(' ');
    size_t l = st.find_last_not_of(' ');
    
    	return (f != string::npos && l != string::npos) ? st.substr(f, l - f + 1) : "";
    }
    
    int menu()
    {
    const int max = 4;
    
    int choice = 0;
    
    	do {
    		cout << "\nMenu\n" << endl;
    		cout << "[1] Do something." << endl;
    		cout << "[2] Do something else." << endl;
    		cout << "[3] Do something entirely different." << endl;
    		cout << "[4] Quit." << endl;
    		cout << "Your choice: ";
    
    		string line, tlin;
    
    		if (!getline(cin, line))
    			cin.clear();
    		else
    			tlin = trim(line);
    
    		const char* last = tlin.c_str() + tlin.length();
    		char *end;
    
    		choice = strtol(tlin.c_str(), &end, 10);
    		if (end != last || choice < 1 || choice > max) {
    			cout << "Invalid choice\n";
    			choice = 0;
    		}
    
    	} while (choice == 0);
    
    	return choice;
    }
    All advice is offered in good faith only. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Aug 2012
    Posts
    75

    Re: Integer based console menu problem

    And you've made my day again, 2kaud!

    The code you've provided is exactly what I was looking for!

    Thread resolved!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width