有限状态机FSM详解及其实现
有限状态机,也称为 FSM(Finite State Machine) ,其在任意时刻都处于有限状态集合中的某一状态。当其获得一个 输入字符 时,将从 当前状态 转换到 另一个状态 ,或者仍然 保持在当前状态 。任何一个FSM都可以用状态转换图来描述,图中的节点表示FSM中的一个状态,有向加权边表示输入字符时状态的变化。如果图中不存在与当前状态与输入字符对应的有向边,则FSM将进入 “消亡状态 (Doom State) ”,此后FSM将一直保持“消亡状态”。状态转换图中还有两个特殊状态:状态1称为 “起始状态” ,表示FSM的初始状态。状态6称为 “结束状态” ,表示成功识别了所输入的字符序列。
在启动一个FSM时,首先必须将FSM置于“起始状态”,然后输入一系列字符,最终,FSM会到达“结束状态”或者“消亡状态”。
说明:
在通常的FSM模型中,一般还存在一个“接受状态”,并且FSM可以从“接受状态”转换到另一个状态,只有在识别最后一个字符后,才会根据最终状态来决定是否接受所输入的字符串。此外,也可以将“其实状态”也作为接受状态,因此空的输入序列也是可以接受的。
FSM的实现
程序设计思路大致如下:
- 使用状态转换图描述FSM
- 状态转换图中的结点对应不同的状态对象
- 每个状态对象通过一个输入字符转换到另一个状态上,或者保持原状态不变。
通过输入字符从一个状态切换到另一个状态的过程,我们称之为一个 映射 。在计算机程序设计中, 我们可以有两种表示映射的方法:
- 通过算法表示,即“可执行代码(Executable Code)”方式
- 通过一张映射表,即“被动数据(Passive Data)”方式
如下详细介绍这两种实现方式:
- 通过Executable Code 实现映射的FSM :
这种方式主要是通过条件分支来处理不同的字符,如if或者switch语句块,如
1 State* State1::Transition(char c)
2 {
3 switch(c)
4 {
5 case 'A':
6 return &s2;
7 case 'B':
8 return &s3;
9 case 'C':
10 return &s4;
11 case 'D':
12 return &s5;
13 case '\0':
14 return NULL;
15 default:
16 return NULL;
17 }
18 }
1 // fsm_with_executable_code.h
2 #ifndef FSM_WITH_EXECUTABLE_CODE_H
3 #define FSM_WITH_EXECUTABLE_CODE_H
4
5 #include <string.h>
6
7 class State
8 {
9 public:
10 virtual State* Transition(char c) = 0;
11 };
12
13 class Fsm
14 {
15 public:
16 Fsm();
17 void Reset(); // move to start state
18 void Advance(char c); // advance one transition
19 int EndState();
20 int DoomState();
21
22 private:
23 State* p_current; // &s1, &s2, ..., &s6; NULL ==> doom
24 };
25
26
27 class State1 : public State
28 {
29 public:
30 State* Transition(char c);
31 };
32
33 class State2 : public State
34 {
35 public:
36 State* Transition(char c);
37 };
38
39 class State3 : public State
40 {
41 public:
42 State* Transition(char c);
43 };
44
45 class State4 : public State
46 {
47 public:
48 State* Transition(char c);
49 };
50
51 class State5 : public State
52 {
53 public:
54 State* Transition(char c);
55 };
56
57 class State6 : public State
58 {
59 public:
60 State* Transition(char c);
61 };
62
63 #endif // FSM_WITH_EXECUTABLE_CODE_H
64
65 // fsm_with_executable_code.cc
66 #include "fsm_with_executable_code.h"
67
68 State1 s1;
69 State2 s2;
70 State3 s3;
71 State4 s4;
72 State5 s5;
73 State6 s6;
74
75 Fsm::Fsm()
76 {
77 p_current = NULL;
78 }
79
80 void Fsm::Reset()
81 {
82 p_current = &s1;
83 }
84
85 void Fsm::Advance(char c)
86 {
87 if (p_current != NULL)
88 p_current = p_current->Transition(c);
89 }
90
91 int Fsm::EndState()
92 {
93 return p_current == &s6;
94 }
95
96 int Fsm::DoomState()
97 {
98 return p_current == NULL;
99 }
100 State* State1::Transition(char c)
101 {
102 switch(c)
103 {
104 case 'A':
105 return &s2;
106 case 'B':
107 return &s3;
108 case 'C':
109 return &s4;
110 case 'D':
111 return &s5;
112 case '\0':
113 return NULL;
114 default:
115 return NULL;
116 }
117 }
118
119 State* State2::Transition(char c)
120 {
121 switch(c)
122 {
123 case