2011-01-14 13 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)) 
; 

यह उपरोक्त ढांचे के साथ शुरुआती बिंदु के रूप में किया जा सकता है।

यह ओओ डिजाइन के बीच अंतर है और जिसे "प्रक्रियात्मक" कहा जा सकता है। मैंने मेन्यू पसंद (जो एक और मेनू हो सकता है) के माध्यम से इसका मतलब है कि विभिन्न दिशाओं में विस्तार किया जा सकता है, इसके पीछे एक अमूर्तता बनाई गई है। मैं जो एक्सटेंशन चाहता हूं, उन्हें एक साथ रखता हूं, और चीज़ को जाने के लिए कहता हूं। अच्छा ओओ डिज़ाइन बस इसी तरह है ... आपके प्रोग्राम का मुख्य भाग एक साथ सामान डालने और इसे जाने के लिए कह रहा है।

इस से लेने की मुख्य बात यह है कि मैंने ऐसा करने के लिए जरूरी नहीं है, लेकिन इसके बारे में सोचने के लिए। यदि आप उपर्युक्त कोड का सारांश प्राप्त कर सकते हैं तो आप देखेंगे कि स्विच मेनू के कारण अत्यधिक जटिल कोड से निपटने के बिना, आप नए मेनू के साथ, मनमाने ढंग से गहराई तक नए आइटम जोड़ सकते हैं।

+0

मुझे लगता है कि यह एक पसंदीदा समाधान है, क्योंकि यह अधिक लचीला है, और आप फ्रेमवर्क-वाई सामान को किसी अन्य फ़ाइल में स्टोर कर सकते हैं, और बाद में इसका उल्लेख कर सकते हैं। –

+0

यह किसी भी स्विचकी तरीके से निश्चित रूप से बेहतर है। हां, आप निश्चित रूप से इसे किसी प्रकार के फ़ाइल प्रारूप पाठक के साथ विस्तारित कर सकते हैं ताकि मेनू बाहरी इनपुट से भी बनाया गया हो। –

+0

std :: kill_everyone_item में स्ट्रक्चर को std :: string – Septagram

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

आपके द्वारा दिए गए मेनू के संदर्भ में, मैं उम्मीद कर रहा था कि एक बार जब उपयोगकर्ता कोई कार्रवाई पूरी कर लेता है (जैसे पहली चीजें, यह सबमेनू पर वापस जायेगी, और वहां वापस जाने का विकल्प होगा पहला मेनू। क्या यह समझ में आता है? –

+0

आह, ठीक है - मैं देखता हूं ... मैंने इस मामले के लिए स्रोत कोड जोड़ा है – Constantin

+0

ऐसा लगता है कि यह काम करेगा। –

1

मैंने अभी भी Libraries for displaying a text-mode menu? पर एक समान प्रश्न पूछा - ऐसा लगता है जैसे ncurses मेनू-प्रदर्शित भागों को नाटकीय रूप से सरल बना देगा।

+1

imho, ncurses एक अच्छा जवाब नहीं है, क्योंकि इसके मेनू ओओपी नहीं हैं और इसके बजाय '*' और '**' सूचक आधारित लिंक्ड सूचियों को लागू करते हैं। मैं मेनू, एनएवी, कंट्रोल क्लास/लाइब्रेरी के लिए एक समान खोज पर हूं और वाईएईआई या वाईएपीबीएलएल नहीं करने की कोशिश कर रहा हूं। फिर भी एक और (अगर-अन्य-अगर | सूचक आधारित लिंक्ड सूची) –

+0

मैं सहमत हूं। मैंने शापित मेनू कार्यक्षमता का उपयोग करने की कोशिश की, लेकिन इसके बजाय अपना खुद का (सी ++ - शैली, एसटीएल-उपयोग) संस्करण छोड़ दिया और लिखा। मैं उस प्रश्न में जोड़ूंगा जो मैंने पूछा था। – ExOttoyuhr

+0

मैंने ओओपी को छोड़ दिया। :(मैं थोड़ी देर की तरह महसूस करता हूं, लेकिन मुझे वास्तव में काम करने के लिए वापस जाना होगा और ओओपी की कोशिश करने के लिए इस हफ्ते के लंबे उद्यम पर्याप्त थे। मैं अपने मस्तिष्क में टुकड़ों को एक साथ नहीं खींच सकता। मैंने इस संरचना को टेम्पलेटिंग उदाहरण लिया 1 99 5 से और यह वही करता है जो मैं चाहता हूं। http://dec.bournemouth.ac.uk/staff/awatson/micro/articles/9509_066.pdf नमूना मेरे गिथब में है। –