用C语言实现有限状态自动机FSM
摘要:状态机模式是一种行为模式,在《设计模式》这本书中对其有详细的描述,通过多态实现不同状态的调转行为的确是一种很好的方法,只可惜在嵌入式环境下,有时只能写纯C代码,并且还需要考虑代码的重入和多任务请求跳转等情形,因此实现起来着实需要一番考虑。本文主要为你实现一个简单的有限状态机,没有考虑代码的重入和多任务跳转,为以后复杂的状态机实现,打下基础。
本文来源:用C语言实现有限状态自动机FSM
一、状态机实现的要素
首先,分析一下一个普通的状态机究竟要实现哪些内容。
状态机存储从开始时刻到现在的变化,并根据当前输入,决定下一个状态。这意味着,状态机要存储状态、获得输入(我们把它叫做跳转条件)、做出响应。
如上图所示,{s1, s2, s3}均为状态,箭头c1/a1表示在s1状态、输入为c1时,跳转到s2,并进行a1操作。
最下方为一组输入,状态机应做出如下反应:
当前状态 | 输入 | 下一个状态 | 动作 |
s1 | c1 | s2 | a1 |
s2 | c2 | s3 | a2 |
s3 | c1 | s2 | a3 |
s2 | c2 | s3 | a2 |
s3 | c1 | s2 | a3 |
s2 | c1 | s_trap | a_trap |
s_trap | c1 | s_trap | a_trap |
当某个状态遇到不能识别的输入时,就默认进入陷阱状态,在陷阱状态中,不论遇到怎样的输入都不能跳出。
为了表达上面这个自动机,我们定义它们的状态和输入类型:
1
2
3
4
5
6
7
8
9
10
11
12
|
typedef int s tate;
typedef int c ondition;
#define STATES 4
#define STATE1 0
#define STATE2 1
#define STATE3 2
#define STATETRAP 3
#define CONDITIONS 2
#define CONDITION1 0
#define CONDITION2 1
|
总结一下,我们需要定义的有状态、输入、行为(动作+下一个状态),其中,行为的个数是“状态数*输入数量”(其中有一些是重复的);其中动作一般来说可以用一个函数指针来实现。
二、具体设计
在嵌入式环境中,由于存储空间比较小,因此把它们全部定义成宏。此外,为了降低执行时间的不确定性,我们使用O(1)的跳转表来模拟状态的跳转。
首先定义跳转类型:
1
2
3
4
5
6
7
|
typedef void (*actiontype)(state mystate, condition condition);
typedef struct
{
s tate next;
a ctiontype action;
} trasition, * ptrasition;
|
然后按照上图中的跳转关系,把三个跳转加一个陷阱跳转先定义出来:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// (s1, c1, s2, a1)
trasition t1 = {
STATE2,
action1
};
// (s2, c2, s3, a2)
trasition t2 = {
STATE3,
action2
};
// (s3, c1, s2, a3)
trasition t3 = {
STATE2,
action3
};
// (s, c, trap, a1)
trasition tt = {
STATETRAP,
actiontrap
};
|
其中的动作,由用户自己完成,在这里仅定义一条输出语句。
1
2
3
4
|
void action1(State state, Condition condition)
{
printf ( "Action 1 triggered.\n" );
}
|
1
|
最后定义跳转表:
|
1
2
3
4
5
6
7
|
pt rasition transition_table[STATES][CONDITIONS] = {
/* c1, c2*/
/* s1 */ &t1, &tt,
/* s2 */ &tt, &t2,
/* s3 */ &t3, &tt,
/* st */ &tt, &tt,
};
|
即可表达上文中的跳转关系。
最后定义状态机,如果不考虑多任务请求,那么状态机仅需要存储当前状态便行了。例如:
1
2
3
4
5
6
7
8
9
10
11
12
|
typedef struct
{
State current;
} StateMachine, * pStateMachine;
State step(pStateMachine machine, Condition condition)
{
pTrasition t = 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.用程序实现这个内容如下
三、程序实现
#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_table[STATENUM][CONDITIONS] = {
/* c1, c2*/
/* s1 */&t1, &tt,
/* s2 */&tt, &t2,
/* s3 */&t3, &tt,
/* st */&tt, &tt,
};
typedef struct
{state current;
} StateMachine, * pStateMachine;state step(pStateMachine machine, condition mycondition)
{ptrasition t = transition_table[machine->current][mycondition];(*(t->action))(machine->current, mycondition);machine->current = t->next;printf("the current state is %d\n",t->next );return machine->current;
}
int main(int argc, char *argv[])
{StateMachine mymachine;mymachine.current=STATE1;int mycon;char ch;while(1){scanf("%d",&mycon); step(&mymachine,mycon);}return 0;
}
程序输入与输出结果示例:
【1】 嵌入式设计模式:有限状态自动机的C语言实现 http://www.cnblogs.com/autosar/archive/2012/06/22/2558604.html
用C语言实现有限状态自动机FSM相关推荐
- 有限状态自动机(FSM)的一些逻辑
FSM状态机 概念 : 状态机是有限状态自动机(英语:finite-state machine,缩写:FSM)的简称,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型. 概念 : 有限状 ...
- 状态机(有限状态自动机 FSM)介绍以及常用状态机种类对比
目录 状态机概念 : 为什么需要状态机: 使用场景 状态机四要素: 常见类型状态机: Squirrel State Machine Spring Statemachine 状态机概念 : 概念 : 状 ...
- 有限状态自动机java实现_有限状态机FSM的几种简单实现
标签: 有限状态机,Akka fsm,squirrel-foundation,java状态模式.责任链模式 1. 有限状态机的概念 有限状态机(英语:finite-state machine,缩写:F ...
- 第十二篇:形式语言理论与有限状态自动机
目录 我们到目前已经介绍了什么? 形式语言理论 为什么要去做这个事情 ? 例子 超越会员问题-- 大纲 常规语言/正则语言 例子重现 正则语言的特性 有限状态接受器 样例 派生形态学 形态学 FSA ...
- 计算机态,(计算机)有限态自动机,FSM(finite state machine),音标,读音,翻译,英文例句,英语词典...
补充资料:ω-有限自动机 ω-有限自动机 ω-finite state automata 1094·.一youx一anz}dongJ-..有限自动机(.一rinite state automata)一 ...
- 有限状态自动机java实现_用java开发编译器之:Thompson构造,将正则表达式转换为有限状态自动机...
阅读博客的朋友可以到我的网易云课堂中,通过视频的方式查看代码的调试和执行过程: 上一节,我们通过代码,实现了一个有限状态自动机,并将其应用于对整形和浮点数的识别.构造有限状态自动机,并驱动它,从而实现 ...
- 一.正则表达式转换为有限状态自动机:正则表达式转NFA
原文:https://study.163.com/course/courseMain.htm?courseId=1002830012 一.有限状态自动机的分类 有限状态自动机,其实可以分成两类.第一类 ...
- 用java开发编译器之:Thompson构造,将正则表达式转换为有限状态自动机
阅读博客的朋友可以到我的网易云课堂中,通过视频的方式查看代码的调试和执行过程: http://study.163.com/course/courseMain.htm?courseId=10028300 ...
- 【Codeforces 506E】Mr.Kitayuta’s Gift【BZOJ 4214】黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化...
神题-- 胡乱讲述一下思维过程-- 首先,读懂题. 然后,转化问题为构造一个长度为|T|+n的字符串,使其内含有T这个子序列. 之后,想到一个简单的dp.由于是回文串,我们就增量构造半个回文串,设f( ...
最新文章
- syslog-ng 正确配置udp接受端口
- 数据挖掘-聚类分析(Python实现K-Means算法)
- ITK:将自定义操作应用于图像中的每个像素
- douchat 4.0 新版发布,助力小程序后台开发
- 精述IBM的MQTT协议和MQTT-S协议
- 阿里云:Table Store(OTS) Writer
- 开源-一步步实现cnblogs博客采集工具-实现过滤设置对话框
- fopen()及相关函数使用
- MapReduce过程卡在reduce处的67%
- 快速排序 与 归并排序
- Python项目开发基础 -- with open (filename) as 读写文件
- 永久删除暴风影音服务项,去除 stormliv.exe 进程
- 服务器时间修改方法,修改云服务器时间设置方法
- mrpoid模拟器java版_mrpoid模拟器2019下载
- 领域平均滤波 matlab,平均值滤波器
- MATLAB Simulink
- MathWorks 中国
- 便携式频谱仪无人机机载频谱仪解决方案
- 箫演奏技巧符号大全图解
- 一纵一横,搭建完整数据分析体系
- WinForm实现倒计时锁定程序完整源码附注释
- 今日头条(App和MainActivity类)
热门文章
- matlab 矩阵序列R6(n),MATLAB___09年试题加答案
- linux 远程控制权限,总结一下linux远程控制方法
- 蓝色三角_梅山!长三角唯一近海蓝色海湾成网红打卡地
- 面试题整理6 栈的压入、弹出序列
- MFC 不存在从 CString 到 char * 的适当转换函数
- 彻底解决Git中文乱码问题
- windows中遍历指定文件夹下的所有子文件夹
- ExtJs、ASP.net运用Linq to SQL与SQL储存过程交互
- 计算机网络探究二之利用PHP实现登录验证之后上网
- Sed教程(五):管理模式、正则表达式、使用功能