指针篇之十二 函数指针数组实现跳转表

    函数跳转表是把函数指针和数组结合在一起的应用方式,它充分利用数组的下标索引和函数指针的自动跳转功能,实现用户输入和功能函数的自动关联。比如一个软件计算器,用户输入两个数(op1/op2)和一个操作代号(oper),代码根据约定的代号/操作映射关系,决定调用哪种运算。常规实现方式为:

    switch(oper)

   {

      case ADD: result=add(op1,op2);break;

      case SUB: result=sub(op1,op2);break;

      case MUL: result=mul(op1,op2);break;

      case DIV: result=div(op1,op2);break;

      ......

    }

    这里用函数而不直接用加减乘除运算符只是举例,另外把具体操作独立出来也是一种良好的设计思想,且后面扩展诸如指数/三角函数等运算必须用独立函数实现。

    上面方式可实现简单加减乘除计算,但功能完善的计算器需要上百种运算,这时switch语句会非常长,一条条重复显得过于僵化。能不能用更简单的方法实现?

    考虑到操作代号是整数,如果约定所有操作代号值从零开始递增排列,就形成数组下标,于是可以用函数指针跳转表来实现。方法是:先声明一系列功能函数,然后按照操作代号依次用相应函数初始化,建立一个函数指针数组,如:

    int add(int, int);  int sub(int, int);  int mul(int, int);  int div(int, int);

    int (*oper_func[])(int, int)={add,sub,mul,div,...}

    数组初始化时,从下标0开始逐一用某操作代码映射相应计算函数,设ADD0SUB1,以此类推。初始化后,就能用一条语句替换整个switch模块,即:result=oper_func[oper](op1,op2);通过oper从函数指针数组中选择正确的函数指针并调用,完成相应功能。

    这里推荐大家了解—下中断向量的概念,它实际也使用了函数跳转表思想。而更进一步还可把函数指针数组扩展为映射函数指针的哈希表(自查hash),以更灵活的在用户输入与函数指针集合间建立映射。此外函数跳转表也是“有限状态机”的基础。

    这里简单展示了跳转表技巧,比这个技巧本身更重要的是,可以借此换个视角加深对函数指针的理解。就象旅游并不只为拍一堆漂亮照片,扩展视野体味人生才是更深层价值所在。技术也有思想和深度,也需要积累思考和感悟。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通过按键实现 LCD 多级菜单的数组查跳转页面以及执行函数的具体步骤如下: 1. 首先需要定义一个菜单项的结构体,包含菜单项名称、菜单项函数指针和下一级菜单项数组等信息。 ```c++ typedef struct { const char* name; // 菜单项名称 void (*function)(void); // 菜单项函数指针 const struct menu_item_t* next; // 下一级菜单项数组指针 } menu_item_t; ``` 2. 定义多级菜单的数组,每个菜单项包含菜单项名称、菜单项函数指针和下一级菜单项数组等信息。 ```c++ const menu_item_t main_menu[] = { {"Option 1", function_1, NULL}, {"Option 2", function_2, sub_menu_1}, {"Option 3", function_3, sub_menu_2}, {"Exit", NULL, NULL} }; const menu_item_t sub_menu_1[] = { {"Sub-option 1", function_4, NULL}, {"Sub-option 2", function_5, NULL}, {"Back", NULL, NULL} }; const menu_item_t sub_menu_2[] = { {"Sub-option 3", function_6, NULL}, {"Sub-option 4", function_7, NULL}, {"Back", NULL, NULL} }; ``` 3. 创建一个函数来处理按键事件,根据按下的按键决定当前菜单项的下一级菜单项数组,并在 LCD 上显示当前菜单项的名称。如果按下的是确认键,则执行当前菜单项的函数指针。 ```c++ void handle_key_press(int key) { static const menu_item_t* current_menu = main_menu; // 当前菜单项指针 int num_items = 0; // 统计当前菜单项的下一级菜单项数量 while (current_menu[num_items].name != NULL) { num_items++; } // 按键处理 switch (key) { case KEY_UP: // 显示上一个菜单项 current_menu--; if (current_menu < main_menu) { current_menu = &main_menu[num_items - 1]; } break; case KEY_DOWN: // 显示下一个菜单项 current_menu++; if (current_menu->name == NULL) { current_menu = &main_menu[0]; } break; case KEY_CONFIRM: // 执行当前菜单项的函数指针 if (current_menu->function != NULL) { current_menu->function(); } else { // 如果当前菜单项没有函数指针,则显示下一级菜单项数组 current_menu = current_menu->next; } break; } // 在 LCD 上显示当前菜单项名称 lcd_display(current_menu->name); } ``` 4. 在主程序中轮询按键状态,并调用 `handle_key_press` 函数处理按键事件。 ```c++ int main() { while (true) { int key = read_key(); if (key != KEY_NONE) { handle_key_press(key); } } } ``` 这样就可以通过按键实现 LCD 多级菜单的数组查跳转页面以及执行函数了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值