Datenstruktur für ein Menu
-
Hi,
in welcher Datenstruktur würdet ihr ein Menu ablegen?
-
Ich hab mal eins gebaut, weils mir aufn senkel ging, immer wieder das gleiche tippen zu müssen - und weil ich msvc eh gerad auf hab:
#ifndef H_MY_MENU_20100406012317 #define H_MY_MENU_20100406012317 #include <cassert> #include <iomanip> #include <iostream> #include <sstream> #include <utility> #include <vector> #include <boost/function.hpp> #include <boost/shared_ptr.hpp> namespace my { namespace detail { unsigned count_digits(unsigned int value) { if(value > 1000000000) return 10; if(value > 100000000) return 9; if(value > 10000000) return 8; if(value > 1000000) return 7; if(value > 100000) return 6; if(value > 10000) return 5; if(value > 1000) return 4; if(value > 100) return 3; if(value > 10) return 2; return 1; } } struct menu { struct function_t { function_t() {} function_t(boost::function0<void> to_call) : to_call(new boost::function0<void>(to_call)) {} void operator() () const { assert(to_call && "cannot dereference a nullptr"); boost::function0<void>& x = *to_call; x(); } friend bool operator== (function_t lhs, function_t rhs) { return lhs.to_call == rhs.to_call; } private: boost::shared_ptr< boost::function0<void> > to_call; }; typedef std::string text_t; typedef std::pair<text_t, function_t> pair_t; typedef std::vector<pair_t> container_t; typedef container_t::size_type size_t; void add(const text_t& title, function_t function) { items.push_back( pair_t(title, function) ); } void skip_nr() { items.push_back( pair_t() ); } void skip_till(size_t next_number) { while(items.size() < next_number-1) { skip_nr(); }; } void print(std::ostream& stream) const { const size_t size = items.size(); const unsigned length = detail::count_digits(size); size_t nr = 1; bool skipped_last = false; for(container_t::const_iterator i(items.begin()), e(items.end()); i != e; ++i, ++nr) { if(!i->first.empty()) { stream << '[' << std::setw( static_cast<std::streamsize>(length) ) << nr << ']' << '\t' << i->first; skipped_last = false; } if(!skipped_last) { stream << std::endl; skipped_last = true; } } stream << std::endl; } function_t operator() (std::istream& in, std::ostream& out) { for(;;) { size_t nr; in >> nr; --nr; if(nr < items.size()) { pair_t& choice = items[nr]; if(!choice.first.empty()) return choice.second; } out << "wrong number - again" << std::endl; std::string rubbish; std::getline(in, rubbish); in.clear(); } } private: container_t items; }; } #endif //#ifndef H_MY_MENU_20100406012317benutzung:
my::menu::function_t put_in_store = boost::bind(hwp::source::features::put_in_store, the_user, &store_house, boost::ref(logger)); my::menu::function_t remove_from_store = boost::bind(hwp::source::features::remove_from_store, the_user, &store_house, boost::ref(logger)); my::menu::function_t save_to_db = boost::bind(hwp::source::features::save_to_db, the_user, &store_house, boost::ref(logger)); my::menu::function_t show_store_house = boost::bind(hwp::source::features::show_store_house, the_user, &store_house, boost::ref(logger)); my::menu::function_t show_single_storing = boost::bind(hwp::source::features::show_single_storing, the_user, &store_house, boost::ref(logger)); my::menu::function_t add_user = boost::bind(hwp::source::features::add_user, the_user, boost::ref(std::cin), boost::ref(std::cout), boost::ref(logger)); my::menu::function_t abort = boost::bind(hwp::source::features::abort, the_user, boost::ref(logger)); my::menu menu; menu.add("Waren einlagern", put_in_store); menu.add("Waren auslagern", remove_from_store); menu.add("Speichern des Lagerzustands", save_to_db); menu.skip_till(5); menu.add("Etwas ueber einen bestimmten Lagerplatz erfahren", show_store_house); menu.add("Einlager-Priorität eines Produktes herausfinden", show_single_storing); menu.skip_till(7); if(the_user->is_admin()) menu.add("Nutzer hinzufügen", add_user); menu.skip_till(9); menu.add("Beenden", abort); menu.print(std::cout); my::menu::function_t to_do = menu(std::cin, std::cout); to_do(); if(to_do == abort) /*beenden, vll noch mal speichern etc.*/ /*...*/bb
-
vielen lieben dank, da habe ich erstmal was zu verdauen. witzig, ich habe auch gerade vc auf und probiere mit vectoren rum

-
Schau dir mal das Composite Design Pattern an. Die verwendete Datenstruktur ist ein Implementierungsdetail, das hängt von weiteren Anforderungen (welche Operationen wie oft benötigt, Validität der Iteratoren, Performance) ab.