关于状态机 finite-state machine
来源:互联网 发布:arm linux开机动画 编辑:程序博客网 时间:2024/05/22 00:09
相关资料来自Finite-state machine
可以看做一个抽象的机器,一次只能在一个状态。如果被一个触发事件或者条件所发起,可以从一个状态变到另外一个状态,这个过程叫做转变。一个特定的Finite-state machine(FSM)有有限个状态,每一种转变有一个特定的触发条件。
但是只有有限个状态,所以FSM得能力不如其他的计算模型,例如图灵机Turing machine。
Event-driven finite-state machine
/********************************************************************/#include <stdio.h> /********************************************************************/typedef enum { ST_RADIO, ST_CD} STATES; typedef enum { EVT_MODE, EVT_NEXT} EVENTS; EVENTS readEventFromMessageQueue(void); /********************************************************************/int main(void){ /* Default state is radio */ STATES state = ST_RADIO; int stationNumber = 0; int trackNumber = 0; /* Infinite loop */ while(1) { /* Read the next incoming event. Usually this is a blocking function. */ EVENTS event = readEventFromMessageQueue(); /* Switch the state and the event to execute the right transition. */ switch(state) { case ST_RADIO: switch(event) { case EVT_MODE: /* Change the state */ state = ST_CD; break; case EVT_NEXT: /* Increase the station number */ stationNumber++; break; } break; case ST_CD: switch(event) { case EVT_MODE: /* Change the state */ state = ST_RADIO; break; case EVT_NEXT: /* Go to the next track */ trackNumber++; break; } break; } }}
Automata-based programming
这是一种编程规范,这种程序或者它的一部分可以被认作是FSM或者其他的更正式的automaton。#include <stdio.h>int main(void){int c;while ((c = getchar()) != EOF){if ((c > 'Z'&&c<'a') || c>'z' || c < 'A')//对输入行的前面的字符进行处理continue;else{putchar(c);while (((c = getchar()) <= 'z'&&c >= 'a') || (c <= 'Z' && c >= 'A'))putchar(c);//输出第一个单词,跳出循环时候的第一个字符无效if (c == '\n'){putchar(c);continue;//这里换行,说明只输入一个有效单词,直接进入下一个大循环}while ((c = getchar()) != EOF&&c != '\n');if (c == '\n'){putchar(c);continue;}else if (c == EOF)break;}}}
WIKI上给的版本是
#include <stdio.h>int main(void){int c;do {c = getchar();while (c == ' ')c = getchar();while (c != EOF && c != ' ' && c != '\n') {putchar(c);c = getchar();}putchar('\n');while (c != EOF && c != '\n')c = getchar();} while (c != EOF);return 0;}
但是在实验中,这份代码连hsdf^&*(4545这种都认定为单词,有效,可以输出!!!所以我的复杂,但是功能大一点
#include <stdio.h>int main(void){int c;enum states { BEFORE, INSIDE, AFTER }state;state = BEFORE;while ((c = getchar()) != EOF){switch (state) {case BEFORE:switch (c){case ' ':break;case '\n':putchar(c);break;default:putchar(c);state = INSIDE;break;}break;case INSIDE:switch (c){case ' ':state = AFTER;break;case '\n':putchar(c);break;default:putchar(c);break;}break;case AFTER:switch (c){case '\n':putchar(c);break;default:break;}}}return 0;}这种方法相较于WIKI的那种方法,虽然代码长,但是只用了一个读取函数getchar(),而且只用到了一个循环。while循环内的程序就是自动机的步骤,而循环本身即可重复的运行自动机的程序。
#include <stdio.h>int main(void){int c;enum states { BEFORE, INSIDE, AFTER }state;state = BEFORE;while ((c = getchar()) != EOF){if (c=='\n'){putchar(c);state = BEFORE;}else{switch (state){case BEFORE:switch (c){case ' ':break;default:putchar(c);state = INSIDE;break;}break;case INSIDE:switch (c){case ' ':state = AFTER;break;default:putchar(c);break;}break;//don't need to care about case AFTER}}}return 0;}
独立的自动机步骤程序
上述程序的一个重要特点是自动机步骤的程序区块都只使用区域变量,以下的例子将自动机步骤集成为一个独立的函数step()
,更可以突显上述的特点:#include <stdio.h>enum states { BEFORE, INSIDE, AFTER };void step(enum states *, char);int main(void){int c;enum states state= BEFORE;while ((c = getchar()) != EOF){step(&state, c);}return 0;}void step(enum states* state, char c){if (c == '\n'){putchar(c);*state = BEFORE;}else{switch (*state){case BEFORE:switch (c){case ' ':break;default:putchar(c);*state = INSIDE;break;}break;case INSIDE:switch (c){case ' ':*state = AFTER;break;default:putchar(c);break;}break;//don't need to care about case AFTER}}}
此例清楚的呈现自动机编程程序的基本特点:
- 各自动机步骤程序的运行时间不互相重叠。
- 前一个步骤和下一个步骤之间所交换的数据只有标示为“自动机状态”的变量(此例中为变量state)。
显式的状态转换表
自动机编程可以用显式的状态转换表来表示。以下的程序中的the_table
数组即为状态转换表,其列表示三个不同的状态,其每一栏对应输入的字符(从左到右分别是空白、换行字符及其他字符)。
对于每一种可能的状态及输入字符的组合,表中有其对应的新状态及一个决定是否否显示输入字符的旗标。在实务的项目中状态转换表可能更为复杂,例如可能包括所有可能条件组合下需调用的函数指针。
#include <stdio.h>enum states { before = 0, inside = 1, after = 2 };struct branch {unsigned char new_state : 2;unsigned char should_putchar : 1;};struct branch the_table[3][3] = {<span style="white-space:pre"></span>/* ' ' '\n' others *//* before */{ { before, 0 }, { before, 1 }, { inside, 1 } },/* inside */{ { after, 0 }, { before, 1 }, { inside, 1 } },/* after */{ { after, 0 }, { before, 1 }, { after, 0 } }};void step(enum states *state, int c){int idx2 = (c == ' ') ? 0 : (c == '\n') ? 1 : 2;struct branch *b = &the_table[*state][idx2];*state = (enum states)(b->new_state);if (b->should_putchar) putchar(c);}int main(void){int c;enum states state = before;while ((c = getchar()) != EOF)step(&state, c);return 0;}
这个程序真的很(kan)高(bu)明(dong)...
首先,states的三种枚举可以各用0、1、2代替。state初始化为before,读入' '时候,idx2=0;
b是struct branch的指针向量,得到the_table[before][0],也就是b=&the_table[0][0](这里存疑:不是前面有一个去之地符号?答:这是对指针b进行初始化的过程中赋值,可以认为b就是指向 the_table[*state][idx2]={before,0} 的指针);这时候更新state:b->new_state是0,0在states中是before,所以state=before; 这时候,对b->should_putchar进行判断,值为0,不输出。返回main()。
如果这时候,输入!=' '&&!='\n'的字符,idx2=2,b=&the_table[before][2]即为*b=the_table[0][2],更新为指向{inside,1}的指针。然后state指向的值变为inside(main()函数中的state变量值为inside),b->should_putchar=1,输出字符。
这时候再读入空格,则b=&the_table[inside][0]={after,0};(这里的after主要处理的是后续字符,无论是什么都只能跳转到after,或者输出后初始化)state变为after,不输出字符
在after状态下,读入空格或者读入others都还是跳转到{after,0},只有读入'\n'跳转到{before,1}即状态初始化,但是输出这个回车字符。
如果,初始状态下输入字符是'\n',idex2=1,b得到的是{before,1}即输出后初始化state。
其实,跳转表已经用the_table列出。
- 关于状态机 finite-state machine
- FSM(finite state machine)
- The finite state machine
- Unity3D,Finite State Machine
- Finite State Machine
- Finite State Machine library Introduction
- 【Unity】Finite State Machine 有限状态机
- Finite State Machine library V1.0 Release
- 有限状态机—— FSM(finite-state machine)
- 有限状态机——The finite state machine
- 运输层:有限状态机(finite state machine FSM)
- 关于WF4 State Machine 状态机工作流的发布问题.
- 状态机(The State Machine Framework)
- Mina State machine状态机讲解
- 复制状态机(State Machine Replication)
- FSM (Finite State Machine Framework)源码共享
- Are Osworkflow and Activiti based on Finite State Machine(FSM)?
- Recommended FSM (Finite State Machine) Library for Java [closed]
- iOS -- 类簇在iOS开发中的应用
- wp8使用mvvm模式简单例子(二)---登陆功能,事件触发
- 茵茵的第一课
- android滑动按钮
- .net获取项目根目录方法大全
- 关于状态机 finite-state machine
- 乐视(letv)网tkey破解
- JMeter基础--测试计划元件
- string类find函数返回值判定
- 驱动开发之 加载NT式驱动
- 1005. 继续(3n+1)猜想 (25)
- [Android] AsyncTask使用实例---加载网络图片
- bzoj2662: [BeiJing wc2012]冻结 分层图最短路
- 让人死去活来的cocos2d-x安卓开发环境搭建(windows+eclipse+ndk)