C语言利用函数指针+函数指针数组去掉冗长的if-else
函数指针
定义函数指针
int(*p)(int, int);
void(*p)(void);
函数指针数组
定义函数指针数组
typedef void (*p)(void);
const p Box[3] = {fun1,fun2,fun3};
void fun1(void){};
void fun2(void){};
void fun3(void){};
实战代码
应用场景概况
- 单片机按键扫描,有3个可用按键
- 用二进制思维,3个可用按键可以映射为8个数字,忽略数字0,也就是有7种不同情况
- 简单的测试,7种不同的情况,用7个普通的函数做对应的动作
- 最简单的设计方法是用if,elseif。囊括7个不同分支,但是如果有拓展,就会让代码冗长难读
code
int _beepTime = 0;
struct rt_semaphore KeyOnSem; //按键有效信号量
//定义函数指针数组
typedef void (*beepBox)(void);
static const beepBox Box[8] = {NULL,_beep1,_beep2,_beep3,_beep4,_beep5,_beep6,_beep7};
/*
* struct BeepStrategy{
* int type;
* void (*_beep_)(void);
* };
*/
struct BeepStrategy Strategy = {
.type = 0,
._beep_ = NULL
};
//入口
void _beepType(void){
if(_beepTime == 0) return;
Strategy.type = _beepTime; //这里感觉其实多余了
Strategy._beep_ = Box[Strategy.type];
Strategy._beep_();
/*用完之后必须要把这个指针指向NULL,否则会宕机*/
Strategy.type = 0;
Strategy._beep_ = NULL;
}
//这个是按键的状态初始化,根据引脚上拉和下拉的情况初始化的
KeyVal Val = {
.key1 = 1,
.key2 = 1,
.keyup = 0
};
//这个函数是实现3个按键输出1~7,把值赋给_beepTime
void _beepmode(KeyVal* val){
val->key1 = ~val->key1;
val->key2 = ~val->key2;
_beepTime |= val->keyup;
_beepTime <<= 1;
_beepTime |= val->key2;
_beepTime <<= 1;
_beepTime |= val->key1;
if(_beepTime == 0) return;
rt_sem_release(&KeyOnSem);
}
//这个rtthread线程,用来检测按键状态
void scankey_task_entry(void* parameter)
{
while(1)
{
Val.key1 = rt_pin_read(_KEY0_);
Val.key2 = rt_pin_read(_KEY1_);
Val.keyup = rt_pin_read(_KEYUP_);
_beepmode(&Val);
rt_thread_mdelay(200);
}
}
//这个线程,用来响应按键的结果。用一个信号量永远阻塞,当按键按下并产生有效数据(_beepTime)就释放一个信号让这里运行
void BeepTask_entry(void* parameter){
rt_sem_init(&KeyOnSem,"KeyOn",0,RT_IPC_FLAG_FIFO);
while(1){
rt_sem_take(&KeyOnSem,RT_WAITING_FOREVER);
_beepType(); //直接调用这个函数,自动就会根据_beepTime的值调用相应的函数
_beepTime = 0; //用完之后要初始化
}
}
//下面是具体动作
void _beep1(void){
rt_kprintf("beep1~~~\r\n");
rt_pin_write(_BEEP_,PIN_HIGH);
rt_thread_mdelay(100);
rt_pin_write(_BEEP_,PIN_LOW);
rt_thread_mdelay(100);
}
void _beep2(void){
rt_kprintf("beep2~~~\r\n");
rt_pin_write(_BEEP_,PIN_HIGH);
rt_thread_mdelay(200);
rt_pin_write(_BEEP_,PIN_LOW);
rt_thread_mdelay(200);
}
void _beep3(void){
rt_kprintf("beep3~~~\r\n");
}
void _beep4(void){
rt_kprintf("beep4~~~\r\n");
rt_pin_write(_BEEP_,PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(_BEEP_,PIN_LOW);
rt_thread_mdelay(500);
}
void _beep5(void){
rt_kprintf("beep5~~~\r\n");
}
void _beep6(void){
rt_kprintf("beep6~~~\r\n");
}
void _beep7(void){
rt_kprintf("beep7~~~\r\n");
}
ps:要是不定序的数字或者字符串怎么办
- 多用一个数组做匹配,然后返回下标吧
总结
- 这样拓展的时候就直接拓展数组,并实现相应的函数就可以了。
- 但是我认为嵌入式依赖硬件平台,资源比起纯软件开发少多了,未来拓展的可能性和规模也不如互联网的需求大。