c++ - 带有类C++的控制台应用程序菜单

标签 c++ oop menu console composite

我目前正在使用C++进行个人项目,并且学习中很多乐趣。我刚刚学习了有关使用继承和虚拟函数的一些想法。我决定创建一个Budget Tracking控制台应用程序!当然,我可以使用控制语句和开关。但是,我想尝试使用类解决此问题。到目前为止,这是我的代码:

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
}

最后,我想像一个用户在mainMenu->输入2中输入while的内容。现在在accountMenu->输入3中管理帐户。输入2->添加帐户。

你们可以帮我找到一种实现这一想法的方法吗?我看到了有关复合图案设计的一些信息。但是,我觉得这与这个想法不符。我错了吗?这是错误的方法吗?

提前致谢!

最佳答案

对于菜单,我建议使用状态表(数据驱动软件):

// 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++ - 带有类C++的控制台应用程序菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55296835/

相关文章:

c++ - 如何绕过模板虚函数来实现我的目标?

我无法理解的 PHP OOP 错误

c++ - 如何使用 union 类型 Protobuf C++

java - 如何摆脱 "Failed to resolve attribute at index 1: TypedValue{t=0x2/d=0x7f01005e a=-1}"

html - 使用 CSS3 菜单

jquery - css 菜单制作器无法在移动设备上运行

c++ - 读/写同一配置文件不同版本的设计方法

c++ - visual c++ 2013 显示与标识符相关的错误。找不到标识符,但我已经定义了它们,但存在错误

c++ - C++中类的常量

c++ - 如何移动 ArrayFire 3D 阵列