I'm attempting to create a menu system within my C program and I'm having trouble implementing past the initial main menu.
I want to have multiple Menu objects that I pass to my function
called showMenu()
that calls the function that pairs with
the respective menu item.
Should I be storing function pointers in the vector? Any advice is helpful - the cleaner the solution, the better.
Here's my code:
struct Menu {
vector<string> items;
vector<function> functions; // incorrect
};
Menu mainMenu = {
{ "Quit", "Income Menu", "Expenses Menu" },
{ return, showMenu(incomeOptions), showMenu(expenseOptions) } // incorrect
};
Menu incomeOptions = {
{"Back" , "Add Income", "Edit Income"},
{ return, addIncome(), editIncome()} // incorrect
};
Menu expenseOptions = {
{"Back" , "Add Expense", "Edit Expense"},
{ return, addExpense(), editExpense()} // incorrect
};
void showMenu(Menu menu, string title = "") {
system("cls");
if (title != "") {
cout << "================ [" << title << "] ================" << endl;
cout << endl;
}
for (int i = 0; i < menu.items.size(); i ) {
cout << " (" << i << ") " << menu.items[i] << endl;
}
int selection;
cout << "\t> ";
cin >> selection;
if (selection >= 0 && selection < menu.items.size()) {
// call function that's paired with selected item
menu.functions[selection];
}
else {
// invalid selection made, display menu again
showMenu(menu, title);
}
}
int main() {
showMenu(mainMenu, "Main Menu");
}
I've attempted to research the c library . I'm pretty sure that's what I need, but like I said, am having trouble implementing it. I'd love to get some suggestions.
CodePudding user response:
You have to provide template parameters for std::function:
struct Menu
{
vector<string> items;
vector<function<void(void)>> functions;
};
And than you can pass lamdas to it:
Menu incomeOptions = {
{"Add Income", "Edit Income"},
{[]{ addIncome(); }, []{ editIncome(); }}
};
Menu expenseOptions = {
{"Add Expense", "Edit Expense"},
{[]{ addIncome(); }, []{ editIncome(); }}
};
Menu mainMenu = {
{"Income Menu", "Expenses Menu"},
{[]{ showMenu(incomeOptions); }, []{ showMenu(expenseOptions); }}
};
You will have to handle the return differently.
And in you showMenu
function. Calling the function also requires the use of the parentheses.
menu.functions[selection]();
And anyway, it it not a good idea to store your menus as global variables. You should change this! But pay attention to the fact that for the mainMenu you must add the other menus to the capture of its lambda.
int main()
{
Menu incomeOptions = {
{"Add Income", "Edit Income"},
{[]{ addIncome(); }, []{ editIncome(); }}
};
Menu expenseOptions = {
{"Add Expense", "Edit Expense"},
{[]{ addIncome(); }, []{ editIncome(); }}
};
Menu mainMenu = {
{"Income Menu", "Expenses Menu"},
{[&incomeOptions]{ showMenu(incomeOptions); }, [&expenseOptions]{ showMenu(expenseOptions); }}
};
showMenu(mainMenu, "Main Menu");
}
Passing the menus by value to the showMenu function is a waste of resources. Feel free to modify it for reference.
void showMenu(Menu &menu, string title = "")
{
// ...
}
And adding "using std; namespace" to your code is also bad practice in the long run.