使用 类 C++ 的控制台应用程序菜单
Console Application Menu with Classes C++
我目前正在使用 C++ 开发一个个人项目,我从中获得了很多乐趣。我刚刚学到了一些关于使用继承和虚函数的想法。我决定创建一个预算跟踪控制台应用程序!当然,我可以使用控制语句和开关;但是,我想尝试使用 类 来解决这个问题。到目前为止,这是我的代码:
Main.cpp
#include <iostream>
#include "MainMenu.h"
#include "Menu.h"
int main() {
std::cout << "Welcome to BudgetTracker!\n" <<
"Let's get started!\n\n";
Menu *menu = new MainMenu;
int mainInput;
menu->displayMenu();
std::cin >> mainInput;
menu->input(mainInput);
//Somehow switch my menu to a sub menu
//Add a loop without terminating entirely
}
MainMenu.cpp
#include "MainMenu.h"
MainMenu::MainMenu(){}
MainMenu::~MainMenu(){}
void MainMenu::displayMenu() {
std::cout << "Welcome to the MainMenu! \n" <<
"Select an option from the following: \n" <<
"1.....Overall View\n" <<
"2.....Accounts\n" <<
"3.....Spending\n" <<
"4.....Statistics\n" <<
"5.....Budgeting\n" <<
"0.....Close Program\n\n";
}
void MainMenu::input(int userInput) {
m_input = userInput;
std::cout << "You have entered " << m_input << ".\n\n";
//some code to enter a different submenu
}
最后,我想象一个用户输入,类似于 while in mainMenu -> input 2。现在在 accountMenu -> input 3 来管理账户。输入2->添加账号。
你们能帮我想办法实现这个想法吗?我看到了一些关于复合模式设计的东西;但是,我觉得它似乎与这个想法不符。我错了吗?这是错误的做法吗?
提前致谢!
在我看来,您需要的是状态模式:https://en.wikipedia.org/wiki/State_pattern
对于菜单,我推荐使用状态表(数据驱动软件):
// Define short hand for function pointer
typedef void (*Menu_Processing_Function_Ptr)();
struct Menu_Item
{
unsigned int number;
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
鉴于上述菜单项结构,您可以创建一个处理{any}菜单的通用引擎。菜单将是 Menu_Item
.
的数组
void Menu_Engine(Menu_Item * p_menu, unsigned int item_quantity)
{
// Display the menu
for (unsigned int i = 0; i < item_quantity; ++i)
{
std::cout << p_menu[i].number
<< ". "
<< p_menu[i].text
<< "\n";
}
std::cout << "Enter selection: ";
unsigned int selection;
std::cin >> selection;
for (unsigned int i = 0; i < item_quantity; ++i)
{
if (selection == p_menu[i].number)
{
// Execute the processing function for the selection.
(p_menu[i].p_processing_function)();
break;
}
}
if (i >= item_quantity)
{
std::cout << "invalid selection\n";
}
}
然后您可以将菜单定义为:
// Forward declarations
void Process_Selection_1();
void Process_Selection_2();
void Process_Selection_3();
Menu_Item first_menu[] =
{
{1, "First Selection", Process_Selection_1},
{2, "Second Selection", Process_Selection_2},
{3, "Third Selection", Process_Selection_3},
};
static const unsigned int menu_size =
sizeof(first_menu) / sizeof(first_menu[0]);
用法示例:
int main()
{
// Process the menu
Menu_Engine(&first_menu[0]);
// Pause.
std::cout << "Paused. Press ENTER to continue.";
std::cin.ignore(1000000, '\n');
return 0;
}
此模式允许您更改菜单而无需重新测试或更改代码(引擎)。添加选择或修改选择不会影响引擎。
这允许将菜单放入只读存储器。
您只需要一个引擎即可处理多个菜单。
编辑 1:std::map
另一种可能性是使用关联数组,将选择编号映射到选择属性:
struct Menu_Item_Attributes
{
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
typedef std::map<unsigned int, Menu_Item_Attributes> Menu_Item_Container;
您的输入处理将是:
unsigned int selection;
std::cout << "Enter selection: ";
std::cin >> selection;
try
{
Menu_Item_Attributes attributes = menu.at(selection);
(attributes.p_processing_function)();
}
catch (std::out_of_range& e)
{
std::cout << "Invalid selection";
}
提醒 std::map
不能存储在只读存储器中,需要在 运行 时间内初始化。
我目前正在使用 C++ 开发一个个人项目,我从中获得了很多乐趣。我刚刚学到了一些关于使用继承和虚函数的想法。我决定创建一个预算跟踪控制台应用程序!当然,我可以使用控制语句和开关;但是,我想尝试使用 类 来解决这个问题。到目前为止,这是我的代码:
Main.cpp
#include <iostream>
#include "MainMenu.h"
#include "Menu.h"
int main() {
std::cout << "Welcome to BudgetTracker!\n" <<
"Let's get started!\n\n";
Menu *menu = new MainMenu;
int mainInput;
menu->displayMenu();
std::cin >> mainInput;
menu->input(mainInput);
//Somehow switch my menu to a sub menu
//Add a loop without terminating entirely
}
MainMenu.cpp
#include "MainMenu.h"
MainMenu::MainMenu(){}
MainMenu::~MainMenu(){}
void MainMenu::displayMenu() {
std::cout << "Welcome to the MainMenu! \n" <<
"Select an option from the following: \n" <<
"1.....Overall View\n" <<
"2.....Accounts\n" <<
"3.....Spending\n" <<
"4.....Statistics\n" <<
"5.....Budgeting\n" <<
"0.....Close Program\n\n";
}
void MainMenu::input(int userInput) {
m_input = userInput;
std::cout << "You have entered " << m_input << ".\n\n";
//some code to enter a different submenu
}
最后,我想象一个用户输入,类似于 while in mainMenu -> input 2。现在在 accountMenu -> input 3 来管理账户。输入2->添加账号。
你们能帮我想办法实现这个想法吗?我看到了一些关于复合模式设计的东西;但是,我觉得它似乎与这个想法不符。我错了吗?这是错误的做法吗?
提前致谢!
在我看来,您需要的是状态模式:https://en.wikipedia.org/wiki/State_pattern
对于菜单,我推荐使用状态表(数据驱动软件):
// Define short hand for function pointer
typedef void (*Menu_Processing_Function_Ptr)();
struct Menu_Item
{
unsigned int number;
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
鉴于上述菜单项结构,您可以创建一个处理{any}菜单的通用引擎。菜单将是 Menu_Item
.
void Menu_Engine(Menu_Item * p_menu, unsigned int item_quantity)
{
// Display the menu
for (unsigned int i = 0; i < item_quantity; ++i)
{
std::cout << p_menu[i].number
<< ". "
<< p_menu[i].text
<< "\n";
}
std::cout << "Enter selection: ";
unsigned int selection;
std::cin >> selection;
for (unsigned int i = 0; i < item_quantity; ++i)
{
if (selection == p_menu[i].number)
{
// Execute the processing function for the selection.
(p_menu[i].p_processing_function)();
break;
}
}
if (i >= item_quantity)
{
std::cout << "invalid selection\n";
}
}
然后您可以将菜单定义为:
// Forward declarations
void Process_Selection_1();
void Process_Selection_2();
void Process_Selection_3();
Menu_Item first_menu[] =
{
{1, "First Selection", Process_Selection_1},
{2, "Second Selection", Process_Selection_2},
{3, "Third Selection", Process_Selection_3},
};
static const unsigned int menu_size =
sizeof(first_menu) / sizeof(first_menu[0]);
用法示例:
int main()
{
// Process the menu
Menu_Engine(&first_menu[0]);
// Pause.
std::cout << "Paused. Press ENTER to continue.";
std::cin.ignore(1000000, '\n');
return 0;
}
此模式允许您更改菜单而无需重新测试或更改代码(引擎)。添加选择或修改选择不会影响引擎。
这允许将菜单放入只读存储器。
您只需要一个引擎即可处理多个菜单。
编辑 1:std::map
另一种可能性是使用关联数组,将选择编号映射到选择属性:
struct Menu_Item_Attributes
{
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
typedef std::map<unsigned int, Menu_Item_Attributes> Menu_Item_Container;
您的输入处理将是:
unsigned int selection;
std::cout << "Enter selection: ";
std::cin >> selection;
try
{
Menu_Item_Attributes attributes = menu.at(selection);
(attributes.p_processing_function)();
}
catch (std::out_of_range& e)
{
std::cout << "Invalid selection";
}
提醒 std::map
不能存储在只读存储器中,需要在 运行 时间内初始化。