用C语言实现有限状态自动机FSM
摘要:状态机模式是一种行为模式,在《设计模式》这本书中对其有详细的描述,通过多态实现不同状态的调转行为的确是一种很好的方法,只可惜在嵌入式环境下,有时只能写纯C代码,并且还需要考虑代码的重入和多任务请求跳转等情形,因此实现起来着实需要一番考虑。本文主要为你实现一个简单的有限状态机,没有考虑代码的重入和多任务跳转,为以后复杂的状态机实现,打下基础。本文来源:用C语言实现有限状态自动机FSM一、状态机实现的要素首先,分析一下一个普通的状态机究竟要实现哪些内容。状态机存储从开始时刻到现在的变化,并根据当前输入,决定下一个状态。这意味着,状态机要存储状态、获得输入(我们把它叫做跳转条件)、做出响应。如上图所示,{s1, s2, s3}均为状态,箭头c1/a1表示在s1状态、输入为c1时,跳转到s2,并进行a1操作。最下方为一组输入,状态机应做出如下反应:当前状态 输入 下一个状态 动作s1 c1 s2 a1s2 c2 s3 a2s3 c1 s2 a3s2 c2 s3 a2s3 c1 s2 a3s2 c1 s_trap a_traps_trap c1 s_trap a_trap当某个状态遇到不能识别的输入时,就默认进入陷阱状态,在陷阱状态中,不论遇到怎样的输入都不能跳出。为了表达上面这个自动机,我们定义它们的状态和输入类型:typedef int state;typedef int condition;#defineSTATES 4#defineSTATE1 0#defineSTATE2 1#defineSTATE3 2#defineSTATETRAP 3#defineCONDITIONS 2#defineCONDITION1 0#defineCONDITION2 1总结一下,我们需要定义的有状态、输入、行为(动作+下一个状态),其中,行为的个数是“状态数*输入数量”(其中有一些是重复的);其中动作一般来说可以用一个函数指针来实现。二、具体设计在嵌入式环境中,由于存储空间比较小,因此把它们全部定义成宏。此外,为了降低执行时间的不确定性,我们使用O(1)的跳转表来模拟状态的跳转。首先定义跳转类型:typedef void (*actiontype)(statemystate, condition condition);typedef struct{statenext;actiontypeaction;}trasition, * ptrasition;然后按照上图中的跳转关系,把三个跳转加一个陷阱跳转先定义出来://(s1, c1, s2, a1)trasitiont1 = {STATE2,action1};//(s2, c2, s3, a2)trasitiont2 = {STATE3,action2};//(s3, c1, s2, a3)trasitiont3 = {STATE2,action3};//(s, c, trap, a1)trasitiontt = {STATETRAP,actiontrap};其中的动作,由用户自己完成,在这里仅定义一条输出语句。1234void action1(Statestate, Condition condition){printf("Action1 triggered.\n");}1最后定义跳转表:asitiontransition_table[STATES][CONDITIONS] = {/*c1, c2*//*s1 */&t1,&tt,/*s2 */&tt,&t2,/*s3 */&t3,&tt,/*st */&tt,&tt,};即可表达上文中的跳转关系。最后定义状态机,如果不考虑多任务请求,那么状态机仅需要存储当前状态便行了。例如:typedef struct{Statecurrent;}StateMachine, * pStateMachine;Statestep(pStateMachine machine, Condition condition){pTrasitiont = transition_table[machine->current][condition];(*(t->action))(machine->current,condition);machine->current= t->next;return machine->current;}总结:我们现在设计实现好了一个状态机,然后要给这个状态机特定的输入,看看状态机的运转情况,以上面图中的那个状态机为例,我们输入的序列是0和1分别代表c1和C2,然后状态s1,s2分别对应0,1.用程序实现这个内容如下三、程序实现程序清单:小型状态机的实现[cpp#include<stdio.h>#include<unistd.h>#include<stdlib.h>typedef int state;typedef int condition;#define STATENUM 4#define STATE1 0#define STATE2 1#define STATE3 2#define STATETRAP 3#define CONDITIONS 2#define CONDITION1 0#define CONDITION2 1typedef void (* actiontype)(state mystate,condition mycondition);typedef struct{state next;actiontype action;}trasition, *ptrasition;void action1(state mystate,condition myconditon);void action2(state mystate,condition myconditon);void action3(state mystate,condition myconditon);void actiontrap(state mystate,condition myconditon);trasition t1={STATE2,action1};trasition t2={STATE3,action2};trasition t3={STATE2,action3};trasition tt={STATETRAP,actiontrap};void action1(state mystate,condition myconditon){printf("action1 one triggered\n");}void action2(state mystate,condition myconditon){printf("action2 one triggered\n");}void action3(state mystate,condition myconditon){printf("action3 one triggered\n");}void actiontrap(state mystate,condition myconditon){printf("actiontrap one triggered\n");}ptrasition transition_tabl补充:软件开发 , C语言 ,
上一个:C类型转换函数
下一个:C语言中常数的数据类型
- 更多C/C++疑问解答:
- 关于c++的cout输出的问题。
- 在学校里学过C和C++,不过学的很一般,现在自学C#,会不会很难?
- 全国计算机二级C语言笔试题
- 已知某树有2个2度结点,3个3度结点,4个4度结点,问有几个叶子结点?
- c++数据结构内部排序问题,整数排序
- 2012九月计算机二级C语言全国题库,,急求急求
- 如果assert只有一个字符串作为参数,是什么意思呢?
- C语言中,哪些运算符具有左结合性,哪些具有右结合性,帮忙总结下,谢谢了!
- 为什么用结构体编写的程序输入是,0输不出来啊~~~
- 将IEEE—754的十六进制转化为十进制浮点类型,用C或C++都行,多谢各位大侠啊,非常感谢!
- 为什么这个程序求不出公式?
- 这个链表倒置的算法请大家分析下
- c语言函数库调用
- C语言unsigned int纠错
- C语言快排求解啊