题
我只是想知道,如果任何人知道的一些良好的教程,在互联网为发展中国家的机器。或者电子书?
我开始的工作在国家机,只是需要一些东西一般要让我开始。
解决方案
状态机是非常简单的用C,如果你使用的函数指针。
基本上你需要2个阵列 - 一个用于状态函数指针,一个用于状态转移规则。每个州函数返回的代码,您可以通过状态查找状态转移表并返回代码,寻找下一个状态,然后就执行它。
int entry_state(void);
int foo_state(void);
int bar_state(void);
int exit_state(void);
/* array and enum below must be in sync! */
int (* state[])(void) = { entry_state, foo_state, bar_state, exit_state};
enum state_codes { entry, foo, bar, end};
enum ret_codes { ok, fail, repeat};
struct transition {
enum state_codes src_state;
enum ret_codes ret_code;
enum state_codes dst_state;
};
/* transitions from end state aren't needed */
struct transition state_transitions[] = {
{entry, ok, foo},
{entry, fail, end},
{foo, ok, bar},
{foo, fail, end},
{foo, repeat, foo},
{bar, ok, end},
{bar, fail, end},
{bar, repeat, foo}};
#define EXIT_STATE end
#define ENTRY_STATE entry
int main(int argc, char *argv[]) {
enum state_codes cur_state = ENTRY_STATE;
enum ret_codes rc;
int (* state_fun)(void);
for (;;) {
state_fun = state[cur_state];
rc = state_fun();
if (EXIT_STATE == cur_state)
break;
cur_state = lookup_transitions(cur_state, rc);
}
return EXIT_SUCCESS;
}
我不把lookup_transitions()
功能,因为它是微不足道的。
这是我多年做状态机的方式。
其他提示
我更喜欢使用函数指针在巨大switch
声明,但与 qrdl的答案我通常不使用显式的返回代码或转换表。
此外,在大多数情况下,你会希望有一个机制来沿着其他数据传递。下面是一个例子的状态机:
#include <stdio.h>
struct state;
typedef void state_fn(struct state *);
struct state
{
state_fn * next;
int i; // data
};
state_fn foo, bar;
void foo(struct state * state)
{
printf("%s %i\n", __func__, ++state->i);
state->next = bar;
}
void bar(struct state * state)
{
printf("%s %i\n", __func__, ++state->i);
state->next = state->i < 10 ? foo : 0;
}
int main(void)
{
struct state state = { foo, 0 };
while(state.next) state.next(&state);
}
状态机不是固有地需要一个教程加以解释或者甚至使用。我的建议是,你看看数据,它需要如何进行解析。
例如,我不得不解析为一个近空间气球飞行计算机的数据协议,它存储的数据在SD卡上,其中需要被解析出到逗号分隔文件的特定格式(二进制)。因为这取决于信息的下一位是我们需要改变我们的解析使用状态机这个是很有道理的。
的代码是用C ++编写,并且可作为 ParseFCU 。正如你所看到的,它首先检测的是什么版本,我们分析,并从那里进入两个不同的状态机。
它进入状态机在一个已知的良好状态,在这一点上,我们开始分析,并根据我们遇到什么角色,我们到下一个状态上移,或返回到以前的状态。这基本上允许代码自适应的数据被存储的方式,以及是否某些在所有偶数数据存在。
在我的实例中,GPS字符串不是为飞行计算机登录的要求,因此,如果没有发现该单个日志写入的结束字节GPS串的处理可以被跳过。
状态机编写简单,和一般我按照它应该流动的规则。输入通过该系统打算应与一定缓解流从状态到状态。
不幸的是,大多数的文章在国家机器写的C++或其他语文具有直接的支持对于多态性的,因为它是很好的模型国家在一个密克罗尼西亚执行类,从一个抽象的国家类。
然而,这是很容易实现的国家机器在C使用开声明,派遣事件的国家(为简单的Fsm,他们几乎码的权利)或者使用表格地图活动的状态过渡。
有几个简单,但是体面的条款的基本框架国家机器中的C这里:
- http://www.gedan.net/2008/09/08/finite-state-machine-matrix-style-c-implementation/
- http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
编辑:网站的"项下的维护",网页的档案链接:
- http://web.archive.org/web/20160517005245/http://www.gedan.net/2008/09/08/finite-state-machine-matrix-style-c-implementation
- http://web.archive.org/web/20160808120758/http://www.gedan.net/2009/03/18/finite-state-machine-matrix-style-c-implementation-function-pointers-addon/
switch
声明为基础的国家机经常使用的一套宏"隐藏"的机制 switch
声明(或使用一套 if
/then
/else
报表,而不是一个 switch
)和作什么样的数额,以一个"密克罗尼西亚语言",用于描述国家机器在C源。我个人喜欢的表为基础的方法,但这些肯定有价值的,被广泛使用,并可以是有效的,尤其是采用较简单的Fsm.
这样一个框架概述了通过史蒂夫*拉宾在 "游戏的编程宝石"3.0章(设计一个一般强大的艾引擎).
一个类似的宏讨论了这里:
如果你还感兴趣C++状态机的实现还有很多,可以找到。我会发布指针,如果你有兴趣。
实时面向对象建模太棒(发表于1994年现在售价低至81美分,另加$ 3.99运费)。
这是所有你需要知道的。
int state = 0;
while (state < 3)
{
switch (state)
{
case 0:
// Do State 0 Stuff
if (should_go_to_next_state)
{
state++;
}
break;
case 1:
// Do State 1 Stuff
if (should_go_back)
{
state--;
}
else if (should_go_to_next_state)
{
state++;
}
break;
case 2:
// Do State 2 Stuff
if (should_go_back_two)
{
state -= 2;
}
else if (should_go_to_next_state)
{
state++;
}
break;
default:
break;
}
}
有很多教训的学习用C手工制作状态机,但让我也建议Ragel状态机编译:
http://www.complang.org/ragel/
它定义状态机的相当简单的方法,然后就可以生成图表,产生不同的风格(表驱动,转到驱动),如果你要等分析该代码,它是强大的代码,可以在生产代码用于各种协议。
状态机可以是用于一个复杂的问题很复杂。他们也受到意想不到的错误。如果有人跑入错误或需要改变在未来的逻辑,他们可以变成一场噩梦。他们也很难跟踪和调试无状态图。结构化编程是更好的(例如,你可能不会用在主线水平状态机)。你甚至可以在中断上下文中使用结构化程序设计(这是国家机器通常使用)。看到这篇文章的“宏来模拟多任务/在中断级阻断代码」在codeproject.com找到。