next up previous contents
Elõre: Saját include file-ok Fel: A tervezés egyes fázisai Vissza: Leképezés adatstruktúrákra és vezérlési

A konkrét deklarációk

Most tekintsük tehát az egyes típusdeklarációkat! A menürendszerünk különbözõ menükbõl áll, a különbözõ menük pedig több menüpontból. Egy menüpont legfontosabb jellemzõje az a függvény, amit a menüpont kiválasztásakor aktivizálni kell. Ezek a függvények igen sokfélék lehetnek, így hagyományos C-ben célszerû a függvények címeit nyilvántartani. Ehhez két lépcsõben definiáljuk a fad (function address) típust:
typedef int intfunc(int);/* int-et visszaado, 1 int-et varo *
                          * fuggvenytipus                   */

typedef intfunc *fad;    /* intfunc tipusu  tarolasi  egy-  *
                          * segre mutato tipus              */
A fent definiált intfunc típust felhasználhatjuk a majdan meghívandó egyes függvények elõzetes deklarálására.

A végrehajtandó függvényen kívül egy menüpont fontos jellemzõje az illetõ menüpont neve (azonosító szövege), az a nyomtatható karakter, amivel Enter megnyomása helyett kiválasztható a menüpont. Célszerû megengednünk, hogy a menüpont által meghívandó függvénynek egy, a menüpont leírásában tárolt paramétert is átadjunk. Ha a menürendszerünkhöz alkalmas help-rendszert is szeretnénk, célszerû az egyes menüpontokhoz rendelt help-szövegre utaló információt (például egy file-indexet) is tárolni. Ezeket az informáiókat - a menüponthoz rendelt függvény címével együtt - az alább deklarált menuitem (menüpont) struktúrába szerveztük:

typedef struct 
{
   char *text;        /* A menupont azonosito szovege       */
   char key;          /* A menupontot kivalaszto betu       */
   int  helpindex;    /* A menuponthoz rendelt help-kod     */
   fad  function;     /* A menuponthoz tartozo fv-re mutat  */
   int  param;        /* A '*function' fuggveny parametere  */
} menuitem;
A figyeljük meg, hogy a fenti struktúra definicóból kimaradt a típuscímke, hiszen typedef-fel eleve azonosítót rendelünk hozzá - rekurzív adatdefinicóról pedig szó sincs.

Most lássuk, hogy szervezhetünk egy menüt a fenti módon deklarált menuitem struktúrák segítségével.

A menüpontjainkat célszerûen egy menuitem típusú tömbben tároljuk, amelynek méretét is tudnunk kell. A menü tartalma mellett fontos annak megjelenése is. Szükségünk lehet arra, hogy a menüt keretezõ doboz tetején esetleg egy menünevet, egy fejlécet (header-t) is megjelenítsünk. Fontos azt is tudnunk, hogy melyik x-y karakterpozicióba kerül a menüdoboz (annak például a bal felsõ sarka) a képernyõn, és az is lényeges információ, hogy hány karakterpoziciót foglal le a menüdoboz vízszintes és függõleges irányban. Azt is nyilvántarthatjuk egy menürõl, hogy melyik menüpontot választottuk ki benne utoljára és fontos lehet az is, hogy az adott menü hol helyezkedik el egy hierarchikus menü-fán. Ezeket az információkat foglaltuk egybe az alábbi menutype struktúrában:

typedef struct 
{
  char     *header;  /* A menu fejlecszovegere mutat        */
  int      x;        /* A menudoboz bal felso sarkanak      */
  int      y;        /* x es y koordinatai, valamint        */
  int      xs;       /* a menudoboz x es                    */
  int      ys;       /* y iranyu merete.                    */
  int      itemno;   /* A menupontok szama                  */
  menuitem *items;   /* A menupontok listajara mutat.       */
  int      hierarch; /* Ha 1, kozvetlenul a fomenu hivja    */
  int      lastitem; /* Utoljara kivalasztott pont szama    */
} menutype;
A menuitem típusból egy-egy inicializált tömböt szervezve hozhatjuk létre az egyes menük tartalmára vonatkozó adathalmazt. Egy ilyen lista kezdõcíme kerül egy menutype struktúra items mezõjébe. Egy-egy menutype struktúra egy komplett menü leírását tartalmazza. Ezekbõl a struktúrákból szintén egy tömböt szervezünk, ez lesz a menus tömb. E tömb elsõ néhány eleme egy-egy menüfa gyökerét (azaz a fõmenü egyes pontjaiként aktivizálandó menüket) reprezentálja, a többi elem pedig az egyes fákra felfûzött almenüket írja le. Tekintsük át tehát a teljes menürendszert definiáló adatstruktúrát:
/* Kulso fuggvenyek deklaracioja                            */

extern intfunc data,  r_data, w_data, statf,
               regr,  linf, barf,
               save,  load; 
               
/* A a menukezelo fuggveny prototipus erteku deklaracioja   */
               
intfunc menu;       /* Elore hivatkozashoz                  */
intfunc dir, shell; /* Tovabbi fv-ek elore hivatkozshoz     */

/* Az egyes menulistak (items_0 .. items_3) es a menuk:     */

menuitem items_0[ ] = 
{ /* text      key hlp func. param.   */
  "Directory", 'D', 1, dir,   0,
  "Os shell",  'O', 2, shell, 0,
  "File",      'F', 3, menu,  3,/*a 3.sz. menu almenu lesz  */
  exitxt,      'X',-1, NULL,  0 /*-1-es parameter: exit     */
};                              /* Tombmeret:               */
#define N0 sizeof(items_0)/sizeof(menuitem) 

menuitem items_1[ ] = 
{
  "Default",   'D', 4, data,  7,
  "Read data", 'R', 5, r_data,1,
  "List data", 'L', 6, w_data,2,
  "Statistics",'S', 7, statf, 3,
  exitxt,      'X',-1, NULL,  0
};
#define N1 sizeof(items_1)/sizeof(menuitem) 

menuitem items_2[ ] = 
{
  "Regression",'R', 8, regr,  4,
  "Plot",      'P', 9, linf,  5,
  "Bar",       'B',10, barf,  6,
  exitxt,      'X',-1, NULL,  0
};
#define N2 sizeof(items_2)/sizeof(menuitem) 

menuitem items_3[ ] = 
{
  "Save",      'S',11, savef, 0,
  "Load",      'L',12, loadf, 0,
  exitxt,      'X',-1, NULL,  0
};
#define N3 sizeof(items_3)/sizeof(menuitem) 

/*      A teljes menurendszer leirasa:                      */
menutype menus[ ] = 
{/* head.  x  y  xs  ys  itemno items   hier. last   */
  "",      9, 2, 13, N0+3, N0,  items_0,  1,   0,
  "",     35, 2, 14, N1+3, N1,  items_1,  1,   0,
  "",     61, 2, 14, N2+3, N2,  items_2,  1,   0,
  "Files",11, 6,  8, N3+3, N3,  items_3,  0,   1
};
Figyeljük meg, hogy a menülisták méretének meghatározását a fordító programra bíztuk: a sizeof operátor segítségével megkapjuk mind az egyes menülistákat tartalmazó tömbök helyfoglalását byte-okban, mind a menuitem típus méretét; ezek hányadosa adja meg a menülista tömbök logikai méretét (azaz azt, hogy hány elemû egy menülista). Ezeket a kifejezéseket #define makróként definiáljuk, és az így kapott kifejezéseket használjuk fel a menus tömb inicializálására. Ez egy igen flexibilis megoldás, ugyanis egy menülista bõvítése során a menus tömb inicializálásakor a menüdoboz méretére és a menülista hosszára vonatkozóan automatikusan helyes adatot fog a fordító felhasználni. A menus tömb kitöltését legfeljebb csak akkor kell módosítani, ha egy új menülista-elem hossza nagyobb, mint az adott menüdobozhoz megadott xs érték.


next up previous contents
Elõre: Saját include file-ok Fel: A tervezés egyes fázisai Vissza: Leképezés adatstruktúrákra és vezérlési