2011-01-14 98 views
5

如何在命令行程序中創建菜單?我試過的東西,如:在命令行中創建菜單

cin >> input; 
switch (input) { 
    case (1): 
    // do stuff 
    case (2): 
    // ... 
} 

但當時我已經有子菜單的問題,並要回同樣的菜單,等等。第一個程序我寫的(除了練習)那些試圖使用switch想法的菜單有goto陳述,因爲替代是堆(當時)複雜的循環。

回答

8

如果我試圖計算創建1,2,3菜單的方法,我們在迭代它們的1/2之前都會死掉。但這裏有一個方法,你可以嘗試讓你開始(未經測試,你可能需要清理幾件事情):

struct menu_item 
{ 
    virtual ~menu_item() {} 
    virtual std::string item_text() const = 0; 
    virtual void go() = 0; 
}; 

struct print_hello_item 
{ 
    std::string item_text() const { return "display greeting"; } 
    void go() { std::cout << "Hello there, Mr. User."; } 
}; 

struct kill_everyone_item 
{ 
    std::string item_text() const { return "Go on murderous rampage"; } 
    void go() { for(;;) kill_the_world(); } 
}; 

struct menu_menu_item 
{ 
    menu_menu_item(std::string const& text) : text_(text), items() {} 
    void add_item(std::unique_ptr<menu_item> item) { items.push_back(std::move(item)); } 
    void go() 
    { 
    std::cout << "Choose: \n"; 
    std::for_each(items.begin(), items.end(), [](std::unique_ptr<menu_item> const& item) 
    { 
     std::cout << "\t" << item->item_text() << "\n"; 
    }); 
    std::cout << "\n\n\tYour choice: "; 
    int choice = get_number_from_console(); 
    if (items.size() > choice) items[choice]->go(); 
    } 
    std::string item_text() const { return text_; } 

private: 
    std::string text_; 
    std::vector<std::unique_ptr<menu_item> > items; 
}; 

int main() 
{ 
    menu_menu_item top_item; 
    top_item.add(std::unique_ptr<menu_item>(new print_hello_item)); 
    top_item.add(std::unique_ptr<menu_item>(new kill_everyone_item)); 

    top_item.go(); 
} 

作爲exercize,我怎麼可能會定義像這樣的菜單項:

top_level.add() 
    ("Drive off a cliff", &die_function) 
    ("Destroy the world", &global_thermal_nuclear_war) 
    ("Deeper", submenu() 
       ("Hey, check this shit out!", &gawk)) 
; 

它可以用上述框架作爲出發點。

這是OO設計和可能被稱爲「程序性」的區別。我創建了一個抽象,它意味着它是一個菜單選項(可以是另一個菜單),可以在各個方向上擴展。我創建了我需要的擴展,將它們放在一起,並告訴事情要走。良好的OO設計就是這樣......你的程序的主要部分是組裝東西並告訴它去。

從中取得的關鍵不一定是按照我剛剛做的方式來做,而是以不同的方式來思考它。如果你能得到上面代碼的要點,那麼你會發現你可以用新的菜單將新的項目添加到任意深度,而不必處理交換風格導致的那種過於複雜的代碼。

2

您可以在菜單中有你的方法整合子菜單:

cin >> input; 
switch (input) { 
    case (1): 
    cin >> input; 
    switch (input) { 
     case (1): //do stuff 
     case (2): //do stuff 
    } 
    break; 
    case (2): 
    break; 
} 

這是你在找什麼?否則:你想要完全解決什麼問題?

編輯: 所以你需要的是在你的子菜單中有一個額外的循環與休息條件?

do{ 
    cin >> input; 
    switch (input) { 
     case (1): 
     do{ 
      cin >> input; 
      switch (input) { 
      case (1): //do stuff 
      case (2): //do stuff 
      } 
     }while(input != 3); 
     break; 
     case (2): 
     break; 
    } 
    }while(true); 
+0

在你給出的菜單的上下文中,我希望一旦用戶完成一個動作(例如第一個做的東西,它會返回到子菜單,並且會有一個選項返回到第一個菜單,這是否有意義? – 2011-01-14 04:56:06

+0

啊,好的 - 我看到了......我已經添加了這種情況下的源代碼 – Constantin 2011-01-14 05:08:24

+0

這似乎會起作用 – 2011-01-14 05:25:16