C语言最优状态机规范


 

 

 

typedef unsigned char State; typedef State(*Procedure)(void *);

这样就可以方便地定义一个函数指针数组:

Procedure Steps[] = { step_init, step_count, step_done, step_default };

step_init,step_count等是函数名,再定义状态:

enum states{ s_init, s_count, s_done, s_default };

枚举定义对应着{0,1,2,3},有了这些再状态机联系那么可以想到,数组的索引就是状态定义,上核心代码,两行(简单吧!关键是想到):

void BestStateMachine(void * invar) {

static State NS = s_init; //定义下一状态

NS = Steps[NS](invar);

}

static的变量NS在每次BestStateMachine调用会得到维护,我们只需再每Steps返回下一个状态并保存到NS中可以实现状态的保存和切换。再说说为什么要加个void*的参数,状态机一般有很多自身变量的维护,而且对于mealy状态机还需根据输入判断,因为函数调用返回是不保留局部变量的,那么就需要将变量传递来实现更改和保存,之所以只用了一个void*参数是因为,如果需要保存和传递的变量很多,直接传递会在调用函数是浪费大量的栈空间,且效率低下,采用这种模式,你可以将变量用一个结构体封装,然后将结构体指针传递给void *的形参,再函数内部再强制转换即可使用结构体内部的变量。现在你已经在嘀咕这作者真啰嗦,好上实例代码,就是一个简单的计数器(以前学状态机都从计数器开始),在计数完成打印信息:

#include<stdio.h> typedef unsigned char State; typedef State(*Procedure)(void *); enum states{ s_init, s_count, s_done, s_default };//状态定义 typedef struct _SM_VAR //对状态机参数封装 { int cnt; }SM_VAR; State step_init(void * arg)//初始化 { SM_VAR *p = (SM_VAR *)arg; p->cnt = 0; printf("CS:init ;cnt=%d;NS:count\n", p->cnt); return s_count; } State step_count(void * arg)//计数 { SM_VAR *p = (SM_VAR *)arg; if (p->cnt < 3){ p->cnt+=1; printf("CS:count;cnt=%d;NS:count\n", p->cnt); return s_count; } else{ printf("CS:count;cnt=%d;NS:done\n", p->cnt); return s_done; } } State step_done(void * arg)//计数完成 { SM_VAR *p = (SM_VAR *)arg; printf("CS:done ;cnt=%d;NS:init\n", p->cnt); return s_init; } State step_default(void * arg)//错误过程 { SM_VAR *p = (SM_VAR *)arg; printf("Wrong State\n"); return s_init; } Procedure Steps[] = { step_init, step_count, step_done, step_default }; void BestStateMachine(void * invar) { static State NS = s_init; //定义下一状态 NS = Steps[NS](invar); } int main(void) { SM_VAR var; int i; for (i = 0; i <8; i++){//给状态机8个周期的时钟驱动 BestStateMachine(&var); } return 0; }

最后在VS2013上调试如下:

CS:init ;cnt=0;NS:count CS:count;cnt=1;NS:count CS:count;cnt=2;NS:count CS:count;cnt=3;NS:count CS:count;cnt=3;NS:done CS:done ;cnt=3;NS:init CS:init ;cnt=0;NS:count CS:count;cnt=1;NS:count 请按任意键继续. . .

总结

以这种模式不仅可以实现上面的Moore型状态机,还可根据实际实现Mealy型状态机,结构清晰易懂,在这里我敢说最优,是因为这是C函数式编程的极限了,如果你有更好的想法联系我,邮箱:869119842@qq.com,唐童鞋。如果你对嵌入式GUI感兴趣,我们可以一起探讨写出我们自己的GUI。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM