UNIX 环境下非图形终端上的通用下拉弹出式菜单工具
摘要 该文在 AIX 环境下,利用 C 语言的指针机制,开发出了非图形终端(HT-382)上通
用下拉弹出式菜单工具
一、 问题 的提出随着 计算 机在 社会 生产、生活各部门的广泛 应用 和高档微机、小型
机的不断出台,高性能 UNIX/XENIX 多用户、多任务操作系统正在逐步取代原有单用户的
DOS 系统。这就迫切需要在新环境下开发出大批功能齐全的应用软件工具,以取代 DOS 环
境下的各种应用软件,从而满足用户新的要求。以往的菜单工具虽各有其特点,但均是在
DOS 环境下开发的,都借助于 Windows 或 TurboC 强大的图形处理库函数,有良好的开发环
境,而且一般的做法是,为每一个菜单编制一特定的程序,即:用户菜单与程序具有一一对应的
关系,一旦菜单做出修改,对程序也必须做相应的改动,从而导致编程工作量大,重复劳动多,
灵活性差等不足。能否在 UNIX 操作系统下的中西文终端上,脱离 TurboC 强大的函数库,开
发出一个独立于用户菜单,对不同 内容 与结构的若干个用户菜单实现管理的应用程序呢?
针对这个问题,笔者经过探索和实践,以 AIX 为背景,利用 C 语言的指针机制,在非图
形终端(HT-382)上开发出一通用的下拉弹出式菜单工具软件。该程序和具体用户菜单的联
接是通过相应于菜单的描述文件(*.TXT)实现。*.TXT 文件不仅描述了用户菜单的内容与结
构,而且对其屏幕显示属性也做了相应描述
二、问题 分析 与具体的用户菜单无关是该通用软件的主要特征。通用性要求:使程序相对
于菜单而独立,必须通过某种方式将一个菜单的信息传递给程序,而不同的菜单其内容与功
能选项,以及各功能选项所包含的子菜单嵌套层数(以下简称结构)都是不同的,这就要求程序
必须能"动态"地处理用户菜单的内容与结构
1.动态处理菜单程序要想"动态"地处理不同的用户菜单,则必须在程序中实现变量的"动态
定义",以便将数目不定的各功能选项进行所需处理。C 语言中变量定义的实质,是为了在编
译时能为其分配相应的存储单元。同时,C 语言又提供了指针机制,允许使用指针对内存单
元进行操作。而且,C 语言经编译后,取得并使用四个逻辑上不同、用于不同对象的内存区
域,分别是:栈、堆、全局变量区、程序代码区,其中"堆"是一个自由内存区域,C 语言可通过
内存分配函数(malloc()、calloc()),动态地从中获得所需空间。由指针指向被分配的内存块,
使之可作为变量空间使用。当该内存空间无用时,可利用内存释放函数 free()释放指针所指
向的内存块。而数据结构中链表的特点是:逻辑上相邻的元素在物理上不一定相邻,数据元
素之间的逻辑关系是由结点中的指针指示的,换句话说,指针为数据元素之间的逻辑关系的
映像。它是一种动态结构,链表所占用的空间不需预先分配,而是由系统应需求即时生成
2.用双向循环链表实现菜单功能下拉弹出式菜单系统系在顶端水平显示包含各主功能选项
的菜单条行,用户可以利用$-→键或←键移动并回车选择所需的主功能选项,而被选取的主
功能选项将会显示其相关的子功能选项在下拉的弹出式菜单框中。同级菜单的功能选项形
成一闭合循环,即:当用户利用↑(或↓)键移动高亮度反白亮条至同级功能选项的顶(或底)部
时,再往上(或下)移动,则高亮度反白条将自动返回底(或顶)部。子菜单可在该级任一功能选
项上按"q"键返回其父菜单。为了实现这一功能,采用双向式循环链表作为该软件的基本数
据结构。将一个窗口下的菜单(仅有一个)作为一相对独立的双向循环链表,即:同一级的菜单
以各功能选项信息的结构体形式为结点,构造成双向循环链表。各菜单之间(即:相对独立的
双向循环链表之间)又有父子关系,采用 C 语言的指针机制使各链表有机地连结成网。基于
此,菜单便可"大"可"小",可"深"可"浅"("大":指菜单项目多,反之为"小";"深":指子菜单嵌套
层数多)
3.创建与控制屏幕窗口与许多操作系统只在汇编语言级向用户提供系统调用的接口不同
,UNIX 不仅在汇编语言级,而且在程序设计语言 C 中提供了这种接口。这给编程者提供了很
大方便。笔者充分利用此特点,借助 AIX 操作系统()提供的 CURSES 库完成屏幕窗口
的创建与操纵。CURSES 库是一组屏幕控制子程序,它允许用 C 程序调用这些子程序去控
制终端的输入与输出。由此提供给用户友好的界面。由于 CURSES 库是一个较为复杂的问
题,因此本文不作详细论述,有关这方面的内容,请读者 参考 相应的书籍。通过以上分析,笔
者想到了一种应用内存分配(指针)和链表相结合来实现变量的动态定义,利用 C 语言的递归
调用最终实现程序通用性的 方法 。现将该方法与程序提供出来供大家参考
三、具体方
1.先根据相应的 text 文件内容创建双向循环链表网
2.再用自定义函数 menu()实现对该链表网的应用。详见程序清单和 text 文件示例。(1)下
拉弹出式菜单程序清单(以 W 开头的有关窗口函数是 CURSES 提供的)# include
<># include <># include <># define LEN sizeof(struct link)struct
link{char str[50],subp[20],prname[20],subtitl[30],mbegin,mend; int
tlin,tcol,subhigh,subwide,sublin,subcol,lin,col; struct
link*next,*befo,*subm,*parem,*paret;WINDOW *pwin,*subwin;};struct link *mhead;
char tree[40];main() /*主函数*/{struct link *creat(); void menu();char
fname[10],tname[30];int wi,hi,li,co,tlin,tcol;FILE *fp1;if
((fp1=fopen("","r"))==NULL) { exit(0); }fscanf(fp1,"%s %d %d %s %d %d %d %d
%s\n",fname,&tlin,&tcol,tname,&hi,&wi,&li,&co,tree);free(fp1); initscr();
cbreak();mhead=creat(fname,NULL,NULL);/*创建双向循环链表网
*/menu(mhead,NULL,tlin,tcol,tname,hi,wi,li,co);/*操纵双向循环链表网*/endwin();
exit(0);}/*操纵菜单函数*/void
menu(head,parewin,tline,tcolu,titl,high,wide,line,colu)struct link *head; int
high,wide,line,colu,tline,tcolu;char titl[30]; WINDOW *parewin;{WINDOW *win,*pw; struct
link *p,*stout,*head1;int keycode;win=newwin(high,wide,line,colu); /*创建窗口
*/keypad(win,TRUE); keycode=0; box(win,'*','*');mvwaddstr(win,tline,tcolu,titl);
wrefresh(win);stout=head1=head; wrefresh(win);for (p=head1;p->mend!='T';) /*菜单显示
*/{ p->pwin=parewin; p=p->next; }p->pwin=parewin
四、结束语该软件具有以下特点
1.通用性强:该菜单工具适用于任何用户,即使不懂得编程,也能很快地构造出所需的菜单,具
编程经验的用户更是易如反掌
2.易于维护:当用户需对菜单进行修改时,只要对相应的 text 文件中的有关数据进行维护即
可,而程序无需任何改动
3.使用灵活方便。笔者已将该工具软件成功应用于 RISC/6000AIX 操作系统下的部
级课题《钻井数据库分系统及应用》,并且推广到相同环境下的所有应用软件系统中,大大
缩短了系统的开发周期,并且具有很强的通用性和可维护性,收到了显著的效果