google-site-verification: google61fe8ba583a51912.html
Command Line Menu in C: Building Interactive User Interfaces

Command line menus are fundamental to many C applications, providing a simple yet effective way for users to interact with programs. From system utilities to configuration tools, text-based menus offer a portable, lightweight interface that works across all platforms. For C programmers, building robust command line menus involves handling user input, validating choices, managing state, and creating intuitive navigation systems.

What is a Command Line Menu?

A command line menu is a text-based user interface that presents options to users and processes their selections. It typically displays numbered or lettered choices, prompts for input, and executes corresponding actions. Command line menus range from simple single-level menus to complex hierarchical systems with submenus, configuration screens, and data entry forms.

Why Build Command Line Menus in C

  1. Portability: Works on any platform with a terminal
  2. Simplicity: Easy to implement and understand
  3. Scriptability: Can be automated and tested
  4. Resource Efficiency: Minimal system requirements
  5. Remote Access: Works over SSH and serial connections
  6. Rapid Development: Quick to prototype and iterate

Basic Single-Level Menu

#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> // ============================================================ // BASIC SINGLE-LEVEL MENU // ============================================================ void clearScreen() { // Cross-platform screen clearing #ifdef _WIN32 system("cls"); #else system("clear"); #endif } void printHeader(const char *title) { printf("\n========================================\n"); printf(" %s\n", title); printf("========================================\n"); } void waitForKey() { printf("\nPress Enter to continue..."); while (getchar() != '\n'); getchar(); // Wait for Enter } // Menu functions void option1() { printf("\n📁 You selected Option 1: File Operations\n"); printf(" This would handle file operations here.\n"); } void option2() { printf("\n🔧 You selected Option 2: Configuration\n"); printf(" This would handle configuration settings.\n"); } void option3() { printf("\n📊 You selected Option 3: View Statistics\n"); printf(" This would display statistics.\n"); } void option4() { printf("\n🔍 You selected Option 4: Search\n"); printf(" This would perform searches.\n"); } void option5() { printf("\n📝 You selected Option 5: Help\n"); printf(" This would show help information.\n"); } void exitProgram() { printf("\n👋 Goodbye!\n"); } int main() { int choice; do { clearScreen(); printHeader("MAIN MENU"); printf("\n"); printf(" 1. File Operations\n"); printf(" 2. Configuration\n"); printf(" 3. View Statistics\n"); printf(" 4. Search\n"); printf(" 5. Help\n"); printf(" 0. Exit\n"); printf("\n Enter your choice: "); scanf("%d", &choice); getchar(); // Clear newline switch (choice) { case 1: option1(); waitForKey(); break; case 2: option2(); waitForKey(); break; case 3: option3(); waitForKey(); break; case 4: option4(); waitForKey(); break; case 5: option5(); waitForKey(); break; case 0: exitProgram(); break; default: printf("\n❌ Invalid choice! Please try again.\n"); waitForKey(); } } while (choice != 0); return 0; }

Menu with Input Validation

#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <stdbool.h> // ============================================================ // MENU WITH INPUT VALIDATION // ============================================================ typedef struct { int id; char name[50]; float value; } Item; Item items[100]; int itemCount = 0; // Clear input buffer void clearInputBuffer() { int c; while ((c = getchar()) != '\n' && c != EOF); } // Get validated integer input int getValidInt(const char *prompt, int min, int max) { int value; int result; char buffer[100]; while (1) { printf("%s [%d-%d]: ", prompt, min, max); if (fgets(buffer, sizeof(buffer), stdin) != NULL) { // Check if input is a valid integer char *endptr; value = strtol(buffer, &endptr, 10); // Check if conversion succeeded and no extra characters if (endptr != buffer && (*endptr == '\n' || *endptr == '\0')) { if (value >= min && value <= max) { return value; } } } printf("❌ Invalid input. Please enter a number between %d and %d.\n", min, max); } } // Get validated float input float getValidFloat(const char *prompt, float min, float max) { float value; char buffer[100]; while (1) { printf("%s [%.2f-%.2f]: ", prompt, min, max); if (fgets(buffer, sizeof(buffer), stdin) != NULL) { char *endptr; value = strtof(buffer, &endptr); if (endptr != buffer && (*endptr == '\n' || *endptr == '\0')) { if (value >= min && value <= max) { return value; } } } printf("❌ Invalid input. Please enter a number between %.2f and %.2f.\n", min, max); } } // Get validated string input void getValidString(const char *prompt, char *buffer, int maxLen) { while (1) { printf("%s: ", prompt); if (fgets(buffer, maxLen, stdin) != NULL) { // Remove trailing newline buffer[strcspn(buffer, "\n")] = 0; // Check if not empty if (strlen(buffer) > 0) { return; } } printf("❌ Input cannot be empty. Please try again.\n"); } } // Get yes/no input bool getYesNo(const char *prompt) { char response[10]; while (1) { printf("%s (y/n): ", prompt); if (fgets(response, sizeof(response), stdin) != NULL) { response[strcspn(response, "\n")] = 0; if (strcasecmp(response, "y") == 0 || strcasecmp(response, "yes") == 0) { return true; } if (strcasecmp(response, "n") == 0 || strcasecmp(response, "no") == 0) { return false; } } printf("❌ Please enter 'y' or 'n'.\n"); } } // Menu options void addItem() { printf("\n--- Add New Item ---\n"); Item newItem; newItem.id = itemCount + 1; getValidString("Enter item name", newItem.name, sizeof(newItem.name)); newItem.value = getValidFloat("Enter value", 0, 10000); items[itemCount++] = newItem; printf("\n✅ Item added successfully! (ID: %d)\n", newItem.id); } void viewItems() { printf("\n--- Item List ---\n"); if (itemCount == 0) { printf("No items found.\n"); return; } printf("%-5s %-20s %-10s\n", "ID", "Name", "Value"); printf("----------------------------------------\n"); for (int i = 0; i < itemCount; i++) { printf("%-5d %-20s $%-9.2f\n", items[i].id, items[i].name, items[i].value); } printf("----------------------------------------\n"); printf("Total items: %d\n", itemCount); } void editItem() { if (itemCount == 0) { printf("\n❌ No items to edit.\n"); return; } viewItems(); int id = getValidInt("Enter item ID to edit", 1, itemCount); int index = id - 1; printf("\nEditing Item %d:\n", id); printf("Current name: %s\n", items[index].name); printf("Current value: $%.2f\n", items[index].value); char newName[50]; getValidString("Enter new name (or Enter to keep)", newName, sizeof(newName)); if (strlen(newName) > 0) { strcpy(items[index].name, newName); } float newValue = getValidFloat("Enter new value (or -1 to keep)", -1, 10000); if (newValue >= 0) { items[index].value = newValue; } printf("\n✅ Item updated successfully!\n"); } void deleteItem() { if (itemCount == 0) { printf("\n❌ No items to delete.\n"); return; } viewItems(); int id = getValidInt("Enter item ID to delete", 1, itemCount); if (getYesNo("Are you sure you want to delete this item?")) { // Shift remaining items for (int i = id - 1; i < itemCount - 1; i++) { items[i] = items[i + 1]; } itemCount--; printf("\n✅ Item deleted successfully!\n"); } else { printf("\nDeletion cancelled.\n"); } } void searchItems() { if (itemCount == 0) { printf("\n❌ No items to search.\n"); return; } char searchTerm[50]; getValidString("Enter search term", searchTerm, sizeof(searchTerm)); printf("\n--- Search Results ---\n"); int found = 0; for (int i = 0; i < itemCount; i++) { if (strstr(items[i].name, searchTerm) != NULL) { printf("ID %d: %s - $%.2f\n", items[i].id, items[i].name, items[i].value); found++; } } printf("Found %d matching item(s).\n", found); } int main() { int choice; do { clearScreen(); printHeader("ITEM MANAGEMENT SYSTEM"); printf("\n"); printf(" 📋 Main Menu\n"); printf(" ==========\n"); printf(" 1. Add Item\n"); printf(" 2. View All Items\n"); printf(" 3. Edit Item\n"); printf(" 4. Delete Item\n"); printf(" 5. Search Items\n"); printf(" 0. Exit\n"); printf("\n Current items: %d\n", itemCount); choice = getValidInt("\n Enter your choice", 0, 5); switch (choice) { case 1: addItem(); break; case 2: viewItems(); break; case 3: editItem(); break; case 4: deleteItem(); break; case 5: searchItems(); break; case 0: if (getYesNo("Exit program?")) { printf("\n👋 Goodbye!\n"); } else { choice = -1; // Continue loop } break; } if (choice != 0) { waitForKey(); } } while (choice != 0); return 0; }

Hierarchical Menu System

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> // ============================================================ // HIERARCHICAL MENU SYSTEM // ============================================================ // Menu item structure typedef struct MenuItem { int id; char title[50]; void (*function)(void); struct MenuItem *submenu; int submenuSize; } MenuItem; // Forward declarations void mainMenu(); void fileMenu(); void editMenu(); void viewMenu(); void toolsMenu(); void helpMenu(); void fileNew(); void fileOpen(); fileSave(); void fileSaveAs(); void fileExit(); void editCut(); void editCopy(); void editPaste(); void editFind(); void viewZoomIn(); void viewZoomOut(); void viewFullScreen(); void toolsOptions(); void toolsPlugins(); void helpAbout(); void helpHelp(); // ============================================================ // MENU DEFINITIONS // ============================================================ // File submenu MenuItem fileSubmenu[] = { {1, "New", fileNew, NULL, 0}, {2, "Open...", fileOpen, NULL, 0}, {3, "Save", fileSave, NULL, 0}, {4, "Save As...", fileSaveAs, NULL, 0}, {5, "Exit", fileExit, NULL, 0}, {0, "", NULL, NULL, 0} // Sentinel }; // Edit submenu MenuItem editSubmenu[] = { {1, "Cut", editCut, NULL, 0}, {2, "Copy", editCopy, NULL, 0}, {3, "Paste", editPaste, NULL, 0}, {4, "Find...", editFind, NULL, 0}, {0, "", NULL, NULL, 0} }; // View submenu MenuItem viewSubmenu[] = { {1, "Zoom In", viewZoomIn, NULL, 0}, {2, "Zoom Out", viewZoomOut, NULL, 0}, {3, "Full Screen", viewFullScreen, NULL, 0}, {0, "", NULL, NULL, 0} }; // Tools submenu MenuItem toolsSubmenu[] = { {1, "Options...", toolsOptions, NULL, 0}, {2, "Plugins...", toolsPlugins, NULL, 0}, {0, "", NULL, NULL, 0} }; // Help submenu MenuItem helpSubmenu[] = { {1, "Help Topics", helpHelp, NULL, 0}, {2, "About", helpAbout, NULL, 0}, {0, "", NULL, NULL, 0} }; // Main menu MenuItem mainMenuItems[] = { {1, "File", fileMenu, fileSubmenu, sizeof(fileSubmenu) / sizeof(MenuItem) - 1}, {2, "Edit", editMenu, editSubmenu, sizeof(editSubmenu) / sizeof(MenuItem) - 1}, {3, "View", viewMenu, viewSubmenu, sizeof(viewSubmenu) / sizeof(MenuItem) - 1}, {4, "Tools", toolsMenu, toolsSubmenu, sizeof(toolsSubmenu) / sizeof(MenuItem) - 1}, {5, "Help", helpMenu, helpSubmenu, sizeof(helpSubmenu) / sizeof(MenuItem) - 1}, {0, "Exit", NULL, NULL, 0} }; // ============================================================ // MENU DISPLAY FUNCTIONS // ============================================================ void displayMenu(MenuItem *items, const char *title) { clearScreen(); printHeader(title); printf("\n"); for (int i = 0; items[i].id != 0; i++) { if (items[i].submenu != NULL) { printf(" %d. %s >\n", items[i].id, items[i].title); } else { printf(" %d. %s\n", items[i].id, items[i].title); } } printf(" 0. Back/Exit\n"); } int getMenuChoice(MenuItem *items) { char input[10]; int choice; while (1) { printf("\n Enter choice: "); if (fgets(input, sizeof(input), stdin) != NULL) { char *endptr; choice = strtol(input, &endptr, 10); if (endptr != input && (*endptr == '\n' || *endptr == '\0')) { // Check if choice is valid int maxChoice = 0; for (int i = 0; items[i].id != 0; i++) { if (items[i].id > maxChoice) maxChoice = items[i].id; } if (choice == 0 || (choice >= 1 && choice <= maxChoice)) { return choice; } } } printf("❌ Invalid choice. Please try again.\n"); } } void runMenu(MenuItem *items, const char *title) { int choice; do { displayMenu(items, title); choice = getMenuChoice(items); if (choice > 0) { // Find selected menu item MenuItem *selected = NULL; for (int i = 0; items[i].id != 0; i++) { if (items[i].id == choice) { selected = &items[i]; break; } } if (selected) { if (selected->submenu != NULL) { // Run submenu runMenu(selected->submenu, selected->title); } else if (selected->function != NULL) { // Execute function clearScreen(); selected->function(); waitForKey(); } } } } while (choice != 0); } // ============================================================ // MENU FUNCTION IMPLEMENTATIONS // ============================================================ void fileMenu() { // This is just a placeholder - runMenu handles submenus directly } void editMenu() {} void viewMenu() {} void toolsMenu() {} void helpMenu() {} void fileNew() { printf("📄 File > New\n"); printf("Creating new file...\n"); // File creation logic } void fileOpen() { printf("📂 File > Open\n"); printf("Opening file dialog...\n"); // File open logic } void fileSave() { printf("💾 File > Save\n"); printf("Saving file...\n"); } void fileSaveAs() { printf("📁 File > Save As\n"); printf("Save as dialog...\n"); } void fileExit() { printf("👋 File > Exit\n"); printf("Exiting program...\n"); exit(0); } void editCut() { printf("✂️ Edit > Cut\n"); } void editCopy() { printf("📋 Edit > Copy\n"); } void editPaste() { printf("📌 Edit > Paste\n"); } void editFind() { printf("🔍 Edit > Find\n"); } void viewZoomIn() { printf("🔍 View > Zoom In\n"); } void viewZoomOut() { printf("🔍 View > Zoom Out\n"); } void viewFullScreen() { printf("🖥️ View > Full Screen\n"); } void toolsOptions() { printf("⚙️ Tools > Options\n"); printf("Configuration dialog...\n"); } void toolsPlugins() { printf("🔌 Tools > Plugins\n"); printf("Plugin manager...\n"); } void helpHelp() { printf("❓ Help > Help Topics\n"); printf("Help system...\n"); } void helpAbout() { printf("ℹ️ Help > About\n"); printf("My Application v1.0\n"); printf("Copyright © 2024\n"); } int main() { runMenu(mainMenuItems, "MAIN MENU"); return 0; }

Dynamic Menu with Configuration

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> // ============================================================ // DYNAMIC MENU WITH CONFIGURATION // ============================================================ typedef struct { int id; char name[50]; char command[200]; bool enabled; int permissions; // 0=user, 1=admin } MenuOption; typedef struct { MenuOption *options; int count; int capacity; bool adminMode; } MenuSystem; MenuSystem* createMenuSystem(int initialCapacity) { MenuSystem *menu = (MenuSystem*)malloc(sizeof(MenuSystem)); menu->options = (MenuOption*)malloc(initialCapacity * sizeof(MenuOption)); menu->count = 0; menu->capacity = initialCapacity; menu->adminMode = false; return menu; } void addMenuOption(MenuSystem *menu, const char *name, const char *command, bool enabled, int permissions) { if (menu->count >= menu->capacity) { menu->capacity *= 2; menu->options = realloc(menu->options, menu->capacity * sizeof(MenuOption)); } MenuOption *opt = &menu->options[menu->count]; opt->id = menu->count + 1; strcpy(opt->name, name); strcpy(opt->command, command); opt->enabled = enabled; opt->permissions = permissions; menu->count++; } void loadMenuFromFile(MenuSystem *menu, const char *filename) { FILE *file = fopen(filename, "r"); if (file == NULL) { printf("No menu configuration found. Using defaults.\n"); // Default menu addMenuOption(menu, "View Files", "ls -la", true, 0); addMenuOption(menu, "Show Date", "date", true, 0); addMenuOption(menu, "System Info", "uname -a", true, 0); addMenuOption(menu, "Disk Usage", "df -h", true, 0); addMenuOption(menu, "Process List", "ps aux", true, 0); addMenuOption(menu, "Network Config", "ifconfig", false, 1); addMenuOption(menu, "User Management", "useradd", false, 1); return; } char line[256]; while (fgets(line, sizeof(line), file)) { // Format: name|command|enabled|permissions char name[50]; char command[200]; int enabled, permissions; if (sscanf(line, "%49[^|]|%199[^|]|%d|%d", name, command, &enabled, &permissions) == 4) { addMenuOption(menu, name, command, enabled, permissions); } } fclose(file); } void saveMenuToFile(MenuSystem *menu, const char *filename) { FILE *file = fopen(filename, "w"); if (file == NULL) return; for (int i = 0; i < menu->count; i++) { fprintf(file, "%s|%s|%d|%d\n", menu->options[i].name, menu->options[i].command, menu->options[i].enabled, menu->options[i].permissions); } fclose(file); } void executeCommand(const char *command) { printf("\n📟 Executing: %s\n", command); printf("----------------------------------------\n"); int result = system(command); printf("----------------------------------------\n"); printf("Command exited with code: %d\n", result); } void toggleAdminMode(MenuSystem *menu) { menu->adminMode = !menu->adminMode; printf("\n%s mode activated.\n", menu->adminMode ? "👑 Admin" : "👤 User"); } void configureMenu(MenuSystem *menu) { printf("\n=== Menu Configuration ===\n"); for (int i = 0; i < menu->count; i++) { MenuOption *opt = &menu->options[i]; printf("\n%d. %s\n", i + 1, opt->name); printf(" Command: %s\n", opt->command); printf(" Enabled: %s\n", opt->enabled ? "✅" : "❌"); printf(" Access: %s\n", opt->permissions == 0 ? "User" : "Admin"); printf(" Options: (E)nable/Disable, (C)hange command, (D)elete\n"); char choice = getchar(); getchar(); // Clear newline switch (toupper(choice)) { case 'E': opt->enabled = !opt->enabled; break; case 'C': { printf("Enter new command: "); fgets(opt->command, sizeof(opt->command), stdin); opt->command[strcspn(opt->command, "\n")] = 0; break; } case 'D': // Shift remaining options for (int j = i; j < menu->count - 1; j++) { menu->options[j] = menu->options[j + 1]; } menu->count--; i--; // Adjust index break; } } } void displayMenu(MenuSystem *menu) { clearScreen(); printHeader(menu->adminMode ? "ADMIN MENU" : "USER MENU"); printf("\n"); printf(" Available options:\n"); printf(" =================\n\n"); for (int i = 0; i < menu->count; i++) { MenuOption *opt = &menu->options[i]; // Skip if not enabled or wrong permission if (!opt->enabled) continue; if (opt->permissions == 1 && !menu->adminMode) continue; printf(" %2d. %s\n", opt->id, opt->name); } printf("\n"); printf(" A. %s mode\n", menu->adminMode ? "👤 Switch to User" : "👑 Switch to Admin"); if (menu->adminMode) { printf(" C. Configure Menu\n"); } printf(" 0. Exit\n"); } int main() { MenuSystem *menu = createMenuSystem(10); // Load menu from file or create default loadMenuFromFile(menu, "menu.cfg"); int choice; char input[10]; do { displayMenu(menu); printf("\n Enter choice: "); if (fgets(input, sizeof(input), stdin) == NULL) break; // Remove newline input[strcspn(input, "\n")] = 0; if (strcasecmp(input, "A") == 0) { toggleAdminMode(menu); waitForKey(); continue; } if (menu->adminMode && strcasecmp(input, "C") == 0) { configureMenu(menu); saveMenuToFile(menu, "menu.cfg"); waitForKey(); continue; } if (strcmp(input, "0") == 0) { printf("\n👋 Goodbye!\n"); break; } // Try to parse as number char *endptr; choice = strtol(input, &endptr, 10); if (endptr != input && *endptr == '\0') { // Find and execute selected option int executed = 0; for (int i = 0; i < menu->count; i++) { if (menu->options[i].id == choice && menu->options[i].enabled && (menu->options[i].permissions == 0 || menu->adminMode)) { executeCommand(menu->options[i].command); executed = 1; break; } } if (!executed) { printf("❌ Invalid option or insufficient permissions.\n"); } waitForKey(); } else { printf("❌ Invalid input.\n"); waitForKey(); } } while (1); free(menu->options); free(menu); return 0; }

Colorful Menu with ANSI Codes

#include <stdio.h> #include <stdlib.h> #include <string.h> // ============================================================ // COLORFUL MENU WITH ANSI CODES // ============================================================ // ANSI color codes #define RESET "\033[0m" #define BLACK "\033[30m" #define RED "\033[31m" #define GREEN "\033[32m" #define YELLOW "\033[33m" #define BLUE "\033[34m" #define MAGENTA "\033[35m" #define CYAN "\033[36m" #define WHITE "\033[37m" #define BOLD "\033[1m" #define UNDERLINE "\033[4m" // Background colors #define BG_BLACK "\033[40m" #define BG_RED "\033[41m" #define BG_GREEN "\033[42m" #define BG_YELLOW "\033[43m" #define BG_BLUE "\033[44m" #define BG_MAGENTA "\033[45m" #define BG_CYAN "\033[46m" #define BG_WHITE "\033[47m" void printColored(const char *color, const char *text) { printf("%s%s%s", color, text, RESET); } void printBanner() { printf("%s", CYAN); printf("╔════════════════════════════════════════╗\n"); printf("║ COMMAND CENTER v1.0 ║\n"); printf("╚════════════════════════════════════════╝\n"); printf("%s", RESET); } void printMenuOption(int number, const char *description, const char *color) { printf(" %s[%d]%s %s", BOLD, number, RESET, color); printf("%-30s%s\n", description, RESET); } void showSystemStatus() { printf("\n%s📊 System Status:%s\n", BOLD, RESET); printf(" CPU: ████████░░ 80%%\n"); printf(" MEM: ███████░░░ 70%%\n"); printf(" DISK: █████████░ 90%%\n"); } int main() { int choice; do { clearScreen(); printBanner(); showSystemStatus(); printf("\n%sMAIN MENU%s\n", BOLD, RESET); printf("════════════════════════════════════════\n\n"); printMenuOption(1, "System Information", GREEN); printMenuOption(2, "Process Manager", YELLOW); printMenuOption(3, "Disk Analyzer", CYAN); printMenuOption(4, "Network Tools", MAGENTA); printMenuOption(5, "User Management", BLUE); printMenuOption(6, "Security Scan", RED); printMenuOption(0, "Exit", WHITE); printf("\n%sEnter choice:%s ", BOLD, RESET); if (scanf("%d", &choice) != 1) { while (getchar() != '\n'); choice = -1; } getchar(); // Clear newline clearScreen(); switch (choice) { case 1: printf("%s📋 System Information%s\n", BOLD, RESET); printf("OS: %s\n", "Linux 5.10"); printf("Kernel: %s\n", "5.10.0-generic"); printf("Uptime: %s\n", "2 days, 4 hours"); printf("Users: %d\n", 3); printf("Load average: 0.45, 0.62, 0.78\n"); break; case 2: printf("%s📊 Process Manager%s\n", BOLD, RESET); printf("%-10s %-20s %-10s %-10s\n", "PID", "NAME", "CPU%", "MEM%"); printf("----------------------------------------\n"); printf("%-10d %-20s %-10.1f %-10.1f\n", 1234, "systemd", 0.5, 1.2); printf("%-10d %-20s %-10.1f %-10.1f\n", 5678, "firefox", 15.3, 12.7); printf("%-10d %-20s %-10.1f %-10.1f\n", 9012, "terminal", 2.1, 3.4); break; case 3: printf("%s💾 Disk Analyzer%s\n", BOLD, RESET); printf("%-20s %-15s %-10s\n", "Mount", "Used", "Available"); printf("----------------------------------------\n"); printf("%-20s %-15s %-10s\n", "/", "45G (60%)", "30G"); printf("%-20s %-15s %-10s\n", "/home", "120G (45%)", "150G"); printf("%-20s %-15s %-10s\n", "/var", "8G (35%)", "15G"); break; case 4: printf("%s🌐 Network Tools%s\n", BOLD, RESET); printf("Interface: eth0\n"); printf("IP Address: 192.168.1.100\n"); printf("MAC Address: 00:1A:2B:3C:4D:5E\n"); printf("RX bytes: 1.2 GB\n"); printf("TX bytes: 850 MB\n"); break; case 5: printf("%s👥 User Management%s\n", BOLD, RESET); printf("Active users:\n"); printf(" • alice (admin)\n"); printf(" • bob (user)\n"); printf(" • charlie (user)\n"); break; case 6: printf("%s🔒 Security Scan%s\n", BOLD, RESET); printf("✓ Firewall active\n"); printf("✓ SELinux enforcing\n"); printf("⚠ Failed logins: 3\n"); printf("✓ All services secure\n"); break; case 0: printf("%s👋 Goodbye!%s\n", BOLD, RESET); break; default: printf("%s❌ Invalid choice%s\n", RED, RESET); } if (choice != 0) { printf("\n%sPress Enter to continue...%s", BOLD, RESET); while (getchar() != '\n'); } } while (choice != 0); return 0; }

Menu with Tab Completion

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // ============================================================ // MENU WITH TAB COMPLETION // ============================================================ #ifdef _WIN32 #include <conio.h> #else #include <termios.h> #include <unistd.h> int getch() { struct termios oldt, newt; int ch; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return ch; } #endif typedef struct { char *commands[50]; int count; } CommandList; CommandList commands = { .commands = { "help", "exit", "clear", "list", "add", "remove", "edit", "search", "sort", "filter", "save", "load", "export", "import", "config", "status", "info", "version", "about", "quit" }, .count = 20 }; void displayPrompt() { printf("\n%s>%s ", GREEN, RESET); fflush(stdout); } void clearInput(char *buffer, int *pos) { memset(buffer, 0, 100); *pos = 0; } void findCompletions(const char *partial, char matches[][50], int *matchCount) { *matchCount = 0; int len = strlen(partial); for (int i = 0; i < commands.count; i++) { if (strncmp(partial, commands.commands[i], len) == 0) { strcpy(matches[*matchCount], commands.commands[i]); (*matchCount)++; } } } void showCompletions(char matches[][50], int matchCount) { printf("\n"); for (int i = 0; i < matchCount; i++) { printf(" %s", matches[i]); if ((i + 1) % 5 == 0) printf("\n"); } if (matchCount > 0) printf("\n"); displayPrompt(); } void processCommand(const char *cmd) { if (strcmp(cmd, "help") == 0) { printf("\n📖 Available commands:\n"); for (int i = 0; i < commands.count; i++) { printf(" %s", commands.commands[i]); if ((i + 1) % 5 == 0) printf("\n"); } printf("\n"); } else if (strcmp(cmd, "clear") == 0) { clearScreen(); } else if (strcmp(cmd, "exit") == 0 || strcmp(cmd, "quit") == 0) { printf("\n👋 Goodbye!\n"); exit(0); } else if (strcmp(cmd, "list") == 0) { printf("\n📋 Listing items...\n"); for (int i = 1; i <= 5; i++) { printf(" Item %d\n", i); } } else if (strcmp(cmd, "status") == 0) { printf("\n📊 System status: OK\n"); } else if (strcmp(cmd, "info") == 0) { printf("\nℹ️ Command Line Interface v1.0\n"); } else { printf("\n❌ Unknown command: %s\n", cmd); } } int main() { char buffer[100]; int pos = 0; int ch; clearScreen(); printHeader("TAB-COMPLETION MENU"); printf("\nType a command and press TAB for completion.\n"); printf("Type 'help' for available commands.\n"); while (1) { displayPrompt(); pos = 0; memset(buffer, 0, sizeof(buffer)); while (1) { ch = getch(); if (ch == '\n') { // Enter printf("\n"); if (pos > 0) { processCommand(buffer); } break; } else if (ch == '\t') { // Tab if (pos > 0) { char matches[10][50]; int matchCount; findCompletions(buffer, matches, &matchCount); if (matchCount == 1) { // Unique match - complete it strcpy(buffer, matches[0]); pos = strlen(buffer); printf("\r%s>%s %s", GREEN, RESET, buffer); fflush(stdout); } else if (matchCount > 1) { // Multiple matches - show them showCompletions(matches, matchCount); } } } else if (ch == 127 || ch == 8) { // Backspace if (pos > 0) { pos--; buffer[pos] = '\0'; printf("\b \b"); fflush(stdout); } } else if (isprint(ch)) { // Printable character if (pos < sizeof(buffer) - 1) { buffer[pos++] = ch; buffer[pos] = '\0'; putchar(ch); fflush(stdout); } } } } return 0; }

Menu Design Patterns

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> // ============================================================ // MENU DESIGN PATTERNS // ============================================================ // 1. Wizard Pattern (step-by-step) void wizardPattern() { printf("=== Installation Wizard ===\n\n"); char name[50]; int option; bool confirm; // Step 1 printf("Step 1/4: Enter your name: "); fgets(name, sizeof(name), stdin); name[strcspn(name, "\n")] = 0; // Step 2 printf("\nStep 2/4: Choose installation type:\n"); printf(" 1. Typical\n"); printf(" 2. Custom\n"); printf(" 3. Minimal\n"); option = getValidInt("Choice", 1, 3); // Step 3 printf("\nStep 3/4: Select components:\n"); printf(" [x] Core files\n"); printf(" [ ] Documentation\n"); printf(" [ ] Development headers\n"); // Step 4 printf("\nStep 4/4: Confirm installation\n"); printf(" Name: %s\n", name); printf(" Type: %s\n", option == 1 ? "Typical" : option == 2 ? "Custom" : "Minimal"); confirm = getYesNo("Proceed with installation?"); if (confirm) { printf("\n✅ Installation complete!\n"); } else { printf("\n❌ Installation cancelled.\n"); } } // 2. Dashboard Pattern (information + actions) void dashboardPattern() { typedef struct { char name[20]; int value; int max; char status[10]; } Metric; Metric metrics[] = { {"CPU", 45, 100, "OK"}, {"MEM", 2, 8, "OK"}, {"DISK", 120, 250, "OK"}, {"NET", 500, 1000, "WARN"} }; while (1) { clearScreen(); printHeader("SYSTEM DASHBOARD"); // Metrics display printf("\n%sSystem Metrics:%s\n", BOLD, RESET); printf("┌──────────┬────────────┬────────────┬──────────┐\n"); printf("│ Metric │ Value │ Max │ Status │\n"); printf("├──────────┼────────────┼────────────┼──────────┤\n"); for (int i = 0; i < 4; i++) { printf("│ %-8s │ %-10d │ %-10d │ %s%-8s%s │\n", metrics[i].name, metrics[i].value, metrics[i].max, strcmp(metrics[i].status, "OK") == 0 ? GREEN : RED, metrics[i].status, RESET); } printf("└──────────┴────────────┴────────────┴──────────┘\n"); // Quick actions printf("\n%sQuick Actions:%s\n", BOLD, RESET); printf(" 1. Refresh Metrics\n"); printf(" 2. Clear Warnings\n"); printf(" 3. System Info\n"); printf(" 4. Settings\n"); printf(" 0. Back\n"); int choice = getValidInt("\nAction", 0, 4); switch (choice) { case 1: // Refresh logic for (int i = 0; i < 4; i++) { metrics[i].value = rand() % metrics[i].max; } break; case 2: strcpy(metrics[3].status, "OK"); break; case 3: printf("\nSystem Information:\n"); printf(" Hostname: server-01\n"); printf(" OS: Linux 5.10\n"); printf(" Uptime: 15 days\n"); waitForKey(); break; case 4: printf("\nSettings (not implemented)\n"); waitForKey(); break; case 0: return; } } } // 3. TUI (Text User Interface) Pattern void tuiPattern() { int selected = 0; const char *options[] = { "New File", "Open File", "Save File", "Save As...", "Print...", "Exit" }; int optionCount = 6; int ch; while (1) { clearScreen(); printHeader("TEXT EDITOR"); printf("\nUse ↑/↓ arrows to navigate, Enter to select\n\n"); for (int i = 0; i < optionCount; i++) { if (i == selected) { printf("%s→ %s%s\n", GREEN, options[i], RESET); } else { printf(" %s\n", options[i]); } } ch = getch(); if (ch == 27) { // ESC sequence getch(); // Skip [ ch = getch(); if (ch == 'A') { // Up arrow selected = (selected - 1 + optionCount) % optionCount; } else if (ch == 'B') { // Down arrow selected = (selected + 1) % optionCount; } } else if (ch == '\n') { // Enter printf("\nSelected: %s\n", options[selected]); waitForKey(); if (selected == optionCount - 1) break; } } } // 4. Multi-page Menu Pattern void multiPageMenu() { const char *items[] = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12", "Item 13", "Item 14", "Item 15" }; int totalItems = 15; int itemsPerPage = 5; int currentPage = 0; int totalPages = (totalItems + itemsPerPage - 1) / itemsPerPage; while (1) { clearScreen(); printHeader("MULTI-PAGE MENU"); printf("\nPage %d of %d\n", currentPage + 1, totalPages); printf("═══════════════════════════════\n\n"); int start = currentPage * itemsPerPage; int end = start + itemsPerPage; if (end > totalItems) end = totalItems; for (int i = start; i < end; i++) { printf(" %2d. %s\n", i + 1, items[i]); } printf("\n"); if (currentPage > 0) { printf(" ← (P)revious page\n"); } if (currentPage < totalPages - 1) { printf(" → (N)ext page\n"); } printf(" (0) Exit\n"); char input[10]; printf("\nChoice (item number or command): "); fgets(input, sizeof(input), stdin); input[strcspn(input, "\n")] = 0; if (strcasecmp(input, "P") == 0 && currentPage > 0) { currentPage--; } else if (strcasecmp(input, "N") == 0 && currentPage < totalPages - 1) { currentPage++; } else if (strcmp(input, "0") == 0) { break; } else { int item = atoi(input); if (item >= 1 && item <= totalItems) { printf("\nSelected: %s\n", items[item - 1]); waitForKey(); } } } } int main() { int choice; do { clearScreen(); printHeader("MENU DESIGN PATTERNS"); printf("\n"); printf(" 1. Wizard Pattern\n"); printf(" 2. Dashboard Pattern\n"); printf(" 3. TUI Pattern\n"); printf(" 4. Multi-page Pattern\n"); printf(" 0. Exit\n"); choice = getValidInt("\nSelect pattern", 0, 4); switch (choice) { case 1: wizardPattern(); break; case 2: dashboardPattern(); break; case 3: tuiPattern(); break; case 4: multiPageMenu(); break; case 0: break; } } while (choice != 0); return 0; }

Best Practices Summary

#include <stdio.h> #include <stdlib.h> // ============================================================ // MENU BEST PRACTICES // ============================================================ void menuBestPractices() { printf("=== Command Line Menu Best Practices ===\n\n"); printf("1. DESIGN PRINCIPLES\n"); printf(" ✓ Keep menus shallow (max 3-4 levels)\n"); printf(" ✓ Use consistent navigation (0=back, 0=exit at top)\n"); printf(" ✓ Show current context/location\n"); printf(" ✓ Provide clear exit options\n\n"); printf("2. INPUT HANDLING\n"); printf(" ✓ Always validate user input\n"); printf(" ✓ Clear input buffer after scanf\n"); printf(" ✓ Handle both upper/lower case\n"); printf(" ✓ Provide default values when appropriate\n\n"); printf("3. FEEDBACK\n"); printf(" ✓ Show confirmation for destructive actions\n"); printf(" ✓ Display success/error messages\n"); printf(" ✓ Wait for user to read messages\n"); printf(" ✓ Use colors consistently (if used)\n\n"); printf("4. NAVIGATION\n"); printf(" ✓ Indicate submenus (> symbol)\n"); printf(" ✓ Show current menu title\n"); printf(" ✓ Provide breadcrumbs for deep menus\n"); printf(" ✓ Allow quick exit (q, quit, 0)\n\n"); printf("5. ROBUSTNESS\n"); printf(" ✓ Handle Ctrl+C gracefully\n"); printf(" ✓ Save state before exit\n"); printf(" ✓ Validate all file operations\n"); printf(" ✓ Test edge cases (empty input, long input)\n\n"); printf("6. ACCESSIBILITY\n"); printf(" ✓ Support both numbered and named commands\n"); printf(" ✓ Provide help option\n"); printf(" ✓ Show available commands\n"); printf(" ✓ Consider screen readers (avoid flashing)\n"); } int main() { menuBestPractices(); return 0; }

Conclusion

Command line menus are essential for creating interactive C applications. Key takeaways:

  1. Basic Structure:
  • Clear screen, display options, get input, process choice
  • Loop until exit condition
  1. Input Validation:
  • Always validate user input
  • Handle invalid choices gracefully
  • Clear input buffer to prevent issues
  1. Navigation:
  • Consistent navigation patterns
  • Indicate current location
  • Provide easy way to go back/exit
  1. Advanced Features:
  • Hierarchical submenus
  • Color and formatting
  • Tab completion
  • Arrow key navigation
  • Configuration persistence
  1. Design Patterns:
  • Wizard (step-by-step)
  • Dashboard (information + actions)
  • TUI (text user interface)
  • Multi-page menus
  1. Best Practices:
  • Clear feedback
  • Confirmation for destructive actions
  • Error handling
  • Consistent interface
  • Accessibility considerations

Command line menus provide a lightweight, portable, and effective user interface for C applications, from simple utilities to complex system management tools.

Complete C Programming Guide + Compilers Collection


1. C srand() Function – Understanding Seed Initialization

https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.


2. C rand() Function Mechanics and Limitations

https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.


3. C log() Function

https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.


4. Mastering Date and Time in C

https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.


5. Mastering time_t Type in C

https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.


6. C exp() Function

https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.


7. C log() Function (Alternate Guide)

https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.


8. C log10() Function

https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.


9. C tan() Function

https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.


10. Random Numbers in C (Secure vs Predictable)

https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.


11. Free Online C Compiler

https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.


C Functions, Arguments, Parameters & Flow

Mastering Functions in C – Complete Guide

https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.


Function Arguments in C

https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.


Function Parameters in C

https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.


Function Declarations in C

https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.


Function Calls in C

https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.


Void Functions in C

https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.


Return Values in C

https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.


Pass-by-Value in C

https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.


Pass-by-Reference in C

https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.


C strstr() Function

https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.


C Preprocessor & Macros

https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/


C Structures, Memory, Scope & Linkage

https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/


C Scope, Storage Classes & Typedef

https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/


Extra Articles

https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/


Online Compilers

https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper