用函数指针替代Switch/Case语句的程序设计方法

2014-07-03 03:33龚松显董锐刘跃宣
单片机与嵌入式系统应用 2014年9期
关键词:表达式语句代码

龚松显,董锐,刘跃宣

(总参通信训练基地 教研部,宣化075100)

引 言

在单片机程序中,诸如键盘按键扫描、菜单处理等多种逻辑功能,在代码上常采用Switch/Case语句的实现方式。Switch/Case语句是一种简单、初级的逻辑表达式,当代码较为复杂时,不利于程序的功能调试和逻辑修改[1],程序的可扩充性和可移植性都受到影响。为了在单片机常用的结构化程序设计中避免Switch/Case语句过于冗长,提出一种使用函数指针来替代Switch/Case语句的实现思路,并给出两种情况下的代码模型。事实证明,该方法可使程序的结构清晰、易于维护,可提高单片机程序的可读性和设计效率。

1 Switch/Case语句的代码模型及特点

1.1 Switch/Case语句代码模型

Switch/Case是C语言中的基本语句,其使用方法在大量教材及书籍中均有介绍[2],这里不再赘述。一般来说,Switch/Case语句代码模型如下:

在该代码模型中,假定function函数形参及返回值均为void类型,其使用Switch/Case分支语句进行不同情况下的程序处理。Prm Value是从前面的程序处理代码中获得的表达式,Prm_A、Prm_B和Prm_C等常量是表达式的值。当表达式的值与某一个Case后面的常量表达式的值匹配时,就执行此Case后面的语句。

1.2 Switch/Case语句的不足

从模型上可以看出,对于简单的功能实现,Switch/Case语句清晰、简便;但当项目功能较为复杂,例如键盘数或菜单级数较多时[3],Switch/Case语句的判断分支较多,导致代码冗长,常常一个Case分支语句动辄跨越数十行,程序整体的可读性和可移植性降低,程序的结构不够清晰。另外,当Switch/Case语句需要扩展功能时,需要在已经臃肿的Case分支上继续“添砖加瓦”,造成了程序语句的进一步冗长,不便于后期程序逻辑功能的修改。

2 使用函数指针替代Switch/Case语句的两种设计方法

2.1 Case表达式的值连续情况下的设计方法

在Switch/Case语句代码模型中,较为常见的一种情况是:Prm_A、Prm_B、Prm_C等常量是连续的数值。对于这种情况,设计思路是定义相关的函数指针数组[4],然后实现相对应的函数。在使用时,只需调用对应的函数指针数组元素即可。该方式下代码模型如下:

在该代码模型中,假定函数指针指向的函数形参及返回值均为void类型,Prm Value是从前面的程序处理代码中获得的表达式。设计方法中,将每个Case分支的处理代码封装成函数,并将每个函数地址按照Case表达式的值的顺序赋给函数指针数组各元素。在功能代码中,程序的实现主体只需使用Prm Value的值调用对应的处理函数即可,原本冗长的Switch/Case语句被一条简单的函数指针调用代替,形式较为简洁。使用这种设计方法,当程序需要扩展新的功能逻辑的时候,只需要依次增加函数指针数组元素的值并实现对应的函数,功能代码的主体部分不需改动。需要注意的一点是,第2种的代码模型中,假定Prm Value的值是从0开始的,对于Case表达式的值不是从0开始但Case表达式的值连续的情况,上面的代码模型仍然可以使用。例如,如果Case表达式的值是从delta开始的,在这种情况下只需要将第2种代码模型中的(p Fun[Prm Value])()表达式改为(p Fun[Prm Valuedelta])()即可,代码的其他部分均可以保持不变。

2.2 Case表达式的值离散情况下的设计方法

第1种代码模型中,在Prm_A、Prm_B、Prm_C等数值相差较大且不连续的情况下,如果仍然套用2.1节的设计方法,函数指针数组中需要人为填充大量冗余数据,造成资源的浪费,并且在修改时需要做到精确的一一对应,程序的设计反而变得更为麻烦,失去了设计方法的本意。此时需要对第2种代码模型进行增强设计。其设计思路是通过构建一个数据结构,将离散的Case表达式的值和对应的处理函数一一对应,在功能代码中对函数指针进行轮询操作。其实现模型如下:

在该代码模型中,构建的StructFun结构体数组实现了Case表达式的值和函数指针的一一对应。当程序需要扩展新的功能逻辑时,只需要添加StructFun结构体数组的内容并实现对应函数体即可,设计方法的优点与2.1节的设计方法类似。实际上,2.1节的设计方法是特殊情况下本设计方法的退化,两种设计方法在思路上仍是保持一致的。

结 语

本文介绍的两种使用函数指针替代Switch/Case语句的方法,使程序的任务处理逻辑关系变得简洁明了,易于增加程序状态,更改程序逻辑,程序的可读性、可调试性强,减少了单片机程序设计中的错误。笔者在工程项目中验证了这两种设计方法,实际可行且快捷有效,对于单片机常用的结构化程序开发具有一定的借鉴意义。

[1]张腊明,佟宇.状态机技术在数据通讯协议栈中的编程应用[J].现代电子技术,2008(3):146-147.

[2]谭浩强.C程序设计[M].3版.北京:清华大学出版社,2008.

[3]汪高勇,宋毅恒,尚举邦.C51与单片机系统多级菜单的模块化设计[J].光电技术应用,2009,24(2):62-66.

[4]朱博,许伦辉.Keil C51中函数指针的使用[J].单片机与嵌入式系统应用,2008(5):71-72.

猜你喜欢
表达式语句代码
重点:语句衔接
一个混合核Hilbert型积分不等式及其算子范数表达式
表达式转换及求值探析
浅析C语言运算符及表达式的教学误区
创世代码
创世代码
创世代码
创世代码
如何搞定语句衔接题
议C语言中循环语句