Skip to content
C++ Better Explained
Go back
Menu Driven Program in C++: Build a Clean Interactive Menu

Menu Driven Program in C++: Build a Clean Interactive Menu

Almost every beginner assignment eventually asks for one: show a list of options, let the user pick, do the thing, ask again. It sounds trivial, and the happy path is — but the version most tutorials show breaks the moment someone types a letter instead of a number.

Here is how to build one properly.


The Structure: do-while Plus switch

Every menu program has the same skeleton:

do {
    print the menu
    read the choice
    switch on the choice
} while the user has not chosen to exit

The do-while loop is the right choice here, not a plain while. A do-while runs its body before testing the condition, which matches what a menu needs: you always want to display the options at least once. With a while loop you would have to either print the menu twice or invent a fake starting value just to get in.

Inside, a switch statement reads better than a chain of if / else if because every branch tests the same variable against a constant.


A Basic Working Menu

#include <iostream>

int main() {
    int choice;

    do {
        std::cout << "\n===== Calculator Menu =====\n";
        std::cout << "1. Add\n";
        std::cout << "2. Subtract\n";
        std::cout << "3. Multiply\n";
        std::cout << "4. Exit\n";
        std::cout << "Enter your choice: ";
        std::cin >> choice;

        double a, b;

        switch (choice) {
            case 1:
                std::cout << "Enter two numbers: ";
                std::cin >> a >> b;
                std::cout << "Result: " << a + b << "\n";
                break;
            case 2:
                std::cout << "Enter two numbers: ";
                std::cin >> a >> b;
                std::cout << "Result: " << a - b << "\n";
                break;
            case 3:
                std::cout << "Enter two numbers: ";
                std::cin >> a >> b;
                std::cout << "Result: " << a * b << "\n";
                break;
            case 4:
                std::cout << "Goodbye!\n";
                break;
            default:
                std::cout << "Invalid choice, try again.\n";
        }
    } while (choice != 4);

    return 0;
}

This works, and it is a fine first version. Two things about it are worth noticing before we improve it.

The break at the end of each case is not optional. Leave it out and C++ falls through into the next case, so choosing “Add” would also run subtract and multiply. That is the single most common bug in menu code.

The default case catches every number that is not on the menu. Without it, typing 9 would silently do nothing and just redraw the menu, which looks broken to the user.

If you're looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you're a complete beginner or looking to solidify your understanding. Just $19.

The Infinite Loop Bug (and the Fix)

Run the program above and type abc at the menu prompt. It will spew “Invalid choice” forever and you will have to kill it.

Here is why. std::cin >> choice expects digits. When it finds a, it fails, sets an internal fail flag, and — critically — leaves abc sitting in the input buffer. On the next loop iteration cin is still in its failed state, so it refuses to read anything at all, choice keeps its old value, and the same bad characters are still waiting. Nothing ever changes.

The fix is two calls:

if (std::cin.fail()) {
    std::cin.clear();                                            // reset the error flag
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // discard the bad input
    std::cout << "Please enter a number.\n";
    continue;
}

clear() resets the flag so cin will read again. ignore() throws away everything up to and including the next newline, removing the offending characters. You need #include <limits> for numeric_limits. There is a fuller treatment of this in cin.ignore and clearing the buffer.


The Complete, Robust Version

Real menu code also pulls each action into its own function. Once the menu has six options, a switch with six inline bodies becomes unreadable — and functions let you test each action separately.

#include <iostream>
#include <limits>
#include <vector>
#include <string>

std::vector<std::string> tasks;

void showMenu() {
    std::cout << "\n===== Task Manager =====\n";
    std::cout << "1. Add a task\n";
    std::cout << "2. List all tasks\n";
    std::cout << "3. Remove a task\n";
    std::cout << "4. Exit\n";
    std::cout << "Enter your choice: ";
}

void addTask() {
    std::cout << "Task description: ";
    std::cin.ignore();                 // drop the newline left by >>
    std::string task;
    std::getline(std::cin, task);
    tasks.push_back(task);
    std::cout << "Added.\n";
}

void listTasks() {
    if (tasks.empty()) {
        std::cout << "No tasks yet.\n";
        return;
    }
    for (size_t i = 0; i < tasks.size(); i++)
        std::cout << i + 1 << ". " << tasks[i] << "\n";
}

void removeTask() {
    if (tasks.empty()) {
        std::cout << "Nothing to remove.\n";
        return;
    }
    listTasks();
    std::cout << "Which number? ";
    size_t n;
    std::cin >> n;

    if (n >= 1 && n <= tasks.size()) {
        tasks.erase(tasks.begin() + (n - 1));
        std::cout << "Removed.\n";
    } else {
        std::cout << "No task with that number.\n";
    }
}

int main() {
    int choice = 0;

    do {
        showMenu();

        if (!(std::cin >> choice)) {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "Please enter a number between 1 and 4.\n";
            continue;
        }

        switch (choice) {
            case 1: addTask();    break;
            case 2: listTasks();  break;
            case 3: removeTask(); break;
            case 4: std::cout << "Goodbye!\n"; break;
            default: std::cout << "Invalid choice, try again.\n";
        }
    } while (choice != 4);

    return 0;
}

Sample run:

===== Task Manager =====
1. Add a task
2. List all tasks
3. Remove a task
4. Exit
Enter your choice: 1
Task description: Buy milk
Added.

A few deliberate choices in this version:


Where to Take It Next

The switch-plus-functions pattern scales well up to about eight options. Beyond that, look at storing the actions in a std::map<int, void(*)()> of function pointers, which lets you add an option by adding one map entry instead of editing the switch. That is also how you would let the menu be built at runtime rather than hard-coded.



Take Your C++ Further

If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.

👉 Get the C++ Better Explained Ebook — $19

📋

Free Download: The 10 Mistakes Every C++ Beginner Makes

A free 1-page checklist that shows the exact traps that slow down every C++ beginner — so you can avoid them from day one.

🔒 No spam. Unsubscribe anytime.


Share this post on:

Written by

Sahil Bora

Software Engineer. Author and creator of C++ Better Explained.


Previous Post
Heap Sort in C++: How It Works, With Full Code and Complexity
Next Post
Transpose of a Matrix in C++: Full Program Explained Step by Step

Keep Learning