ncurses - C++ code reduction for identical submenus -
i coding way last project of semester , have code duplication issue. using ncurses
or pdcurses
make menu interact user.
the problem: each choice of menu(five in total) need submenu. submenu's difference main menu is, array of items
printed, , parameters go functions, result of items
array size. since need 5 submenus, need 5 times same code(six if add main menu).
could of me make function same thing, i'll call 6 times create menu?
here's code
void menu(){ const char* items[]={ "[1]...new tax declaration", "[2]...modify tax declaration", "[3]...cancel tax declaration", "[4]...additional information", "[5]...exit" }; int cur=0; int ch, i; int flag=0; do{ werase(wm); mvwaddstr(wm, 2, 16, "menu"); for(int i=0; i<5;i++){ if(i==cur) wattr_on(wm, a_reverse, 0); mvwaddstr(wm, 4+i, 4, items[i]); wattr_off(wm, a_reverse, 0); } mvwaddstr(wm, 14, 3, "choice: "); wprintw(wm, "%1d", cur+1); wrefresh(wm); ch=wgetch(wm); switch(ch){ case '1':cur=0;sub2();break; case '2':cur=1;sub1();break; case '3':cur=2;break; case '4':cur=3;break; case '5':flag=1;break; case key_up: case key_left: cur--; if (cur<0) cur=4; break; case key_down: case key_right: cur++; if(cur>4) cur=0; break; case 27: flag=1; break; case 32: case 13: switch (cur){ case 0:sub2();break; case 1:sub1();break; case 2:break; case 3:break; case 4:flag=1;break; } } }while(!flag); }
thank you.
p.s code book. have little experience ncurses, don't hard on me :p. want final project code better :).
a simple menu-driven program. based on using std::map
instead of conditional logic. map stores list of menuitem
structures define menu looks , each option does.
this best explained work through code, let's dive in!
// headers used in example #include <iostream> #include <string> #include <map> #include <functional> #include <cctype> // function perform menu option b sub option 1 void optionb1() { std::cout << "perfoming b1" << std::endl; } // function perform menu option b sub option 2 void optionb2() { std::cout << "perfoming b2" << std::endl; } // function perform menu option void optiona() { std::cout << "perfoming a" << std::endl; } // defines menu item. naming can save need comment struct menuitem { std::function<void()> doit; // function run if option chosen std::string description; // pretty message describing option }; // draw menu , wait user select option. void domenu(const std::map<char, menuitem> & menu) { while (true) // loop until user gives option. or use retry count. // decide. { (auto &items : menu) { // items in menu, print out item , it's description text // first , second mean, read on std::map , std::pair std::cout << items.first << ") " << items.second.description << std::endl; } char ch; std::cin >> ch; // user's choice // may want eliminate 1 of cases reduce amount // of possible inputs need provide handling code for. // line below allows use same code input of , a. ch = std::tolower(ch); // convert input lower case try { menu.at(ch).doit(); // call function mapped user's choice. // may produce or may // display menu. end wor-- return; // done. } catch (...) { // print error message on unsupported input std::cout << "error. invalid option!" << std::endl; } } } // b menu std::map<char, menuitem> bmenu { // user input doit function description {'1', {optionb1, "option b1"}}, {'2', {optionb2, "option b2"}} // add more options here. or don't. you. }; // main menu std::map<char, menuitem> mainmenu { // user input doit function description {'a', {optiona, "option a"}}, {'b', {std::bind(domenu, bmenu), "option b"}} // ok, last 1 bit weird. std::bind makes function , // specifies arguments called. takes // domenu binds bmenu std::function<void()> // satisfied. far world concerned, bound function // returns nothing , takes no parameters. complicated functions // can bound long end result returns nothing , requires // no parameters. // it's doing here allowing call domenu draw b // submenu, wait valid input, , call chosen function. }; // 'ol trusty main can test above code isn't utter bs. int main() { while (true) // loop forever. or use whatever exit logic required. { domenu(mainmenu); // kick-start calling menu run main menu } return(0); }
this keep code down minimum. of duplicated code reduced domenu
function , smurfload of code hidden sight in standard library , written folks have far more experience in getting stuff right or i. whenever possible, stand on shoulders of giants.
domenu
driven lists of options , execution instructions option. want option? add item list , possibly provide new function fulfill obligations of option.
all have fill in blanks.