基于链表的多级菜单设计

  • 前言
  • 主体

前言

最近在做一个简单的界面,需要用到多级菜单,一开始使用的是传统的索引法,在修改时比较乱,在网上有用链表写的,虽然一致都在用c语言,却很少使用链表,于是今天早上便打算用链表制作一个多级菜单,经过一天的努力,终于完成了一个简单的框架,现在只可以添加菜单,而且没有级数限制。 目前只是在gcc下运行成功,还没有在单片机上运行。

主体

传统的双向链表可以寻找上下级的关系,而在多级菜单中还包括同级关系,因此链表的解构应该是树形,包括,父级,子级,同级上和同级下
这里定义一个结构体

typedef struct _menu
{struct _menu * last;//父极菜单指针struct _menu * same_last;//同级菜单下一项指针struct _menu * same_next;//同级菜单上一项指针char * menu_name;//当前功能名称int id;//当前功能号void (*funsion)();//功能struct _menu*next;//子级菜单}menu_t;

这里,我们还需要几个变量
1.我们需要知道链表当前位置
2.通过按键上下可以在同级之间切换,左右分别表示退出和返回,但是如果我们进入一个界面不想通过上下左右切换链表,所以我们还需要一个全局变量,当这个变量为1时是正常操作,当变量为非1时,我们将获取的按键值交给一个全局变量,故我们需要两个变量

struct {menu_t *now;//当前链表位置
int ctrl;
char input;
}sys_info;

接下来便是创建表头

menu_t*add_funsion(menu_t *head,void * fun,char * str){    //添加一个功能 head为该界面的第一项,自动在该界面后添加一项功能menu_t *p = NULL,*pr = head;  p = (menu_t *)malloc(sizeof(menu_t)) ; if(p == NULL){        printf("NO enough momery to allocate!\n");exit(0);}if(head == NULL){        head = p;  //head为空,创建头节点   printf("创建头节点\n");                        }else{              //如果不是创建头节点 int i=1;                                          while(pr->same_next!= NULL){     //找到同级菜单最后的表{i++;pr = pr->same_next;}}pr->same_next = p;  //在同级菜单尾部创建一个功能p->same_last=pr;p->last=head->last;p->id=i;}p->funsion=fun;p->menu_name=str;p->same_next = NULL;//下一个同级功能为空p->next=NULL;          //下一个子集功能为空return head;
}

上面的函数中如果head是一个空指针,则创建头节点,如果不是空指针,则在其同级最后添加一个结构
然后是在一个目录功能下新建一个目录

menu_t * set_page(menu_t * head,int num)//输入为页的表头
{for(int i=0;i<num;i++){if(head->same_next!=NULL)head=head->same_next;else{printf("超出当前功能号\n");}}if(head->next!=NULL)head=head->next;else{printf("创建子菜单\n");menu_t *p = NULL;   p = (menu_t *)malloc(sizeof(menu_t)) ; if(p == NULL){     printf("NO enough momery to allocate!\n");exit(0);}head->next=p;p->last=head;p->id=0;//当前功能号为0p->same_last=NULL;p->same_next=NULL;return p;}return head;
}

第一个head指针为当前目录真正,第二个num代表要在当前目录那一项创建子级,并将创建子级的指针返回,但是,需要注意的是返回的指针已经开辟了内存,并没有使用,因此需要对此指针内容进行赋值

void set_fun(menu_t *menu,void * fun,char * str)//设置函数和功能
{menu->funsion=fun;menu->menu_name=str;
}

至此主要函数就已经写完了
然后就是进入目录时的刷新

void fun1()
{printf("%s","\033[1H\033[2J");//linux下的清屏函数,window下请用system("cls");printf("使用键盘选择以下功能\n");if(sys_info.now->last!=NULL)//如果父极不为空{menu_t * start=sys_info.now->last->next;//start指向同级第一个while(start!=NULL)//将所有功能打在屏幕上,如果功能和选中功能一样,变色{if(start->menu_name==sys_info.now->menu_name)//{printf("********%s*********\n",start->menu_name);}else{printf("    ****%s****\n",start->menu_name);}start=start->same_next;}}else{printf("父极为空");}}

由于是在linux下写完,清屏函数在window下需要system
下面是完整代码

#include <stdio.h>
#include <stdlib.h>
typedef struct _menu
{struct _menu * last;//父极菜单指针struct _menu * same_last;//同级菜单下一项指针struct _menu * same_next;//同级菜单上一项指针char * menu_name;//当前功能名称int id;//当前功能号void (*funsion)();//功能struct _menu*next;//子级菜单}menu_t;struct {menu_t *now;//当前链表位置
int ctrl;
char input;
}sys_info;menu_t * set_page(menu_t * head,int num)//输入为页的表头
{for(int i=0;i<num;i++){if(head->same_next!=NULL)head=head->same_next;else{printf("超出当前功能号\n");}}if(head->next!=NULL)head=head->next;else{printf("创建子菜单\n");menu_t *p = NULL;   p = (menu_t *)malloc(sizeof(menu_t)) ; if(p == NULL){     printf("NO enough momery to allocate!\n");exit(0);}head->next=p;p->last=head;p->id=0;//当前功能号为0p->same_last=NULL;p->same_next=NULL;return p;}return head;
}menu_t*add_funsion(menu_t *head,void * fun,char * str){    //添加一个功能 head为该界面的第一项,自动在该界面后添加一项功能menu_t *p = NULL,*pr = head;   p = (menu_t *)malloc(sizeof(menu_t)) ; if(p == NULL){     printf("NO enough momery to allocate!\n");exit(0);}if(head == NULL){        head = p;  //head为空,创建头节点   printf("创建头节点\n");                        }else{              //如果不是创建头节点 int i=1;                                          while(pr->same_next!= NULL){     //找到同级菜单最后的表{i++;pr = pr->same_next;}}pr->same_next = p;  //在同级菜单尾部创建一个功能p->same_last=pr;p->last=head->last;p->id=i;}p->funsion=fun;p->menu_name=str;p->same_next = NULL;//下一个同级功能为空p->next=NULL;          //下一个子集功能为空return head;
}menu_t * add_child(menu_t *head)//添加子级
{menu_t *p = NULL;   p = (menu_t *)malloc(sizeof(menu_t)) ; if(p == NULL){      printf("NO enough momery to allocate!\n");exit(0);}if(head == NULL){        printf("输入head错误,添加子级失败\n");                           }else{                                                             head->next=p;p->last=head;p->same_last=NULL;p->same_next=NULL;}return p;
}
void fun1()
{printf("%s","\033[1H\033[2J");//linux下的清屏函数,window下请用system("cls");printf("使用键盘选择以下功能\n");if(sys_info.now->last!=NULL)//如果父极不为空{menu_t * start=sys_info.now->last->next;//start指向同级第一个while(start!=NULL)//将所有功能打在屏幕上,如果功能和选中功能一样,变色{if(start->menu_name==sys_info.now->menu_name)//{printf("********%s*********\n",start->menu_name);}else{printf("    ****%s****\n",start->menu_name);}start=start->same_next;}}else{printf("父极为空");}}
void kong()//空函数
{printf("%s","\033[1H\033[2J");//linux下的清屏函数,window下请用system("cls");printf("***多级菜单显示****");
}
void set_fun(menu_t *menu,void * fun,char * str)//设置函数和功能
{menu->funsion=fun;menu->menu_name=str;
}
void switch_input()//判断输入
{scanf("%c", & sys_info.input);//把a仍给系统,交给对应函数处理if (sys_info.ctrl)//按键控制链表{switch (sys_info.input){case 'w'://上if(sys_info.now->same_last!=NULL)sys_info.now=sys_info.now->same_last;break;case 's'://下if(sys_info.now->same_next!=NULL)sys_info.now=sys_info.now->same_next;break;case 'a':// 左相当于返回if(sys_info.now->last!=NULL)sys_info.now=sys_info.now->last;break;case 'd'://右相当于确认if(sys_info.now->next!=NULL)sys_info.now=sys_info.now->next;break;default:break;}sys_info.now->funsion();}
}
void main()
{sys_info.ctrl=1;menu_t *head=NULL;head=add_funsion(head,kong,"添加头节点");//添加头节点menu_t *first=set_page(head,0);//主页面set_fun(first,fun1,"第一页选项一");add_funsion(first,fun1,"第一页选项二");add_funsion(first,fun1,"第一页选项三");menu_t *second=set_page(first,0);//第一个功能的页面 二级菜单set_fun(second,fun1,"选项一的选项一");add_funsion(second,fun1,"选项一的选项二");add_funsion(second,fun1,"选项一的选项三");sys_info.now=first;menu_t *three=set_page(first,1);//第一个功能的页面 二级菜单set_fun(three,fun1,"选项二的选项一");add_funsion(three,fun1,"选项二的选项二");add_funsion(three,fun1,"选项二的选项三");menu_t *four=set_page(second,0);//第一个功能的页面的第一个页面  三级菜单set_fun(four,fun1,"选项一的选项一的选项一");add_funsion(four,fun1,"选项一的选项一选项二");add_funsion(four,fun1,"选项一的选项一选项三");fun1();sys_info.now=first;while(1){switch_input();}}

基于链表的多级菜单设计相关推荐

  1. 基于STM32F407的简易菜单设计+LCD+按键

    基于STM32F407的简易多级菜单设计+LCD+按键 实现原理 主要使用 双向链表 结构实现的菜单: 结构体包含7个变量,分别是菜单中功能项的个数,当前菜单标题,菜单中各功能项标题,功能项的类型,然 ...

  2. STM32+0.96OLED的多级菜单设计

    硬件 硬件选型 STM32F103C8T6最小核心板 0.96寸四脚OLED屏幕IIC接口 普通按键5个 硬件连线 SCL ---- PA1 SDA ---- PA2 KEY_UP ---- PA4 ...

  3. 基于状态机的LCD多级菜单设计

    文章地址链接1:https://blog.csdn.net/embedded_guzi/article/details/35835755 文章地址链接2:http://eeskill.com/arti ...

  4. 基于单片机的LCD菜单设计

    在小型的单片机设备中,需要使用LCD菜单进行人机交互.对于这种交互的实现,一来无需像在手机上做APP一样,做出花哨的界面效果:二来这种小设备也不支持那样太消耗资源的界面系统.所以这种场合下,需要我们亲 ...

  5. 分享一个按键液晶多级菜单设计方法,工控行业中沿用多年,屡试不爽,附带本人一个调试通过

    转自:https://www.amobbs.com/forum.php?mod=viewthread&tid=4001689 typedef struct { uchar KeyStateIn ...

  6. 70+漂亮且极具亲和力的导航菜单设计推荐

    网站可用性是任何网站的基本要素,而可用的导航更是网站所必需的要素之一.导航决定了用户如何与网站进行交互.如果没有了可用的导航,那么网站内容就会变得毫无用处.导航菜单应当足够简单以让用户快速了解它,但还 ...

  7. 70 漂亮且极具亲和力的导航菜单设计推荐

    网站可用性是任何网站的基本要素,而可用的导航更是网站所必需的要素之一.导航决定了用户如何与网站进行交互.如果没有了可用的导航,那么网站内容就会变得毫无用处.导航菜单应当足够简单以让用户快速了解它,但还 ...

  8. 基于STM32的OLED多级菜单GUI实现(简化版智能手表)

    前言:本文的OLED多级菜单UI为一个综合性的STM32小项目,使用多传感器与OLED显示屏实现智能终端的效果.项目中的多级菜单UI使用了较为常见的结构体索引法去实现功能与功能之间的来回切换,搭配DH ...

  9. Vue 里,多级菜单要如何设计才显得专业?

    老生常谈了! 虽然我们是 Java 猿,但是写起来前端代码也不含糊!今天我想来和大家聊聊这个前端的动态菜单,要如何设计才显得专业!还是以我们的 TienChin 项目为例,大家一起来看看. 先来一张截 ...

最新文章

  1. java api中的设计模式_Java API 设计模式之策略(Strategy)
  2. 阿里云数据库产品HybridDB简介——OLAP数据库,支持行列混合存储,为用户提供基于开源 OLTP、OLAP、BigData 生态的一站式解决方案...
  3. 北京理工大学 python专题课程-Python第七章(北理国家精品课 嵩天等)
  4. 一天搞定CSS: CSS选择器优先级--08
  5. VTK:vtkCaptionActor2D用法实战
  6. Bash Shell学习笔记二
  7. Echarts 地图绘制
  8. 网络蚂蚁(netants) v1.25 国际版 bt
  9. linux 平铺式桌面,Linux 桌面平铺管理器 - i3wm
  10. Java FTP工具类
  11. 物联网卡的6个应用案例全面解析
  12. 手机格式化的计算机原理,格式化不了怎么办 手机电脑方法大不同【图解】
  13. Guitar Pro8.1吉他谱神器下载及简谱功能
  14. 信息学奥赛一本通1055《判断闰年》C++方法+Python方法
  15. 经典进程同步问题(十)
  16. Windows Server 2012修改光驱盘符
  17. 产品读书《金字塔原理》
  18. 宏观经济学gdp计算方法_宏观经济学GDP中存货是怎么算的,能说一下吗
  19. Rocket MQ 详解
  20. SMO的MSDN文档

热门文章

  1. excel2013鼠标滑动滚动条时出现已停止工作(故障模块OSF.dll)
  2. 软件工程专业考研是否更有利于找工作?
  3. matlab求函数的极小值和零点,函数的根、极小值原来可以这么求!
  4. 学习DVB知识的疑问与自我解答
  5. 免费的sql工具_免费SQL工具
  6. Android 分屏模式 问题总结
  7. 深度解读:《数字孪生世界白皮书(2023)》全方位剖析
  8. MSN登陆不上去的解决方法
  9. MSN登陆后死机的解决方案
  10. js刷新当前页面窗口