【问题标题】:Finite State Machine With Function Pointers带函数指针的有限状态机
【发布时间】:2019-08-12 06:02:33
【问题描述】:

我正在学习将有限状态机用于某些任务,但在导航状态表和执行功能以使其成为有用的系统时遇到问题。

考虑一下我的状态机:


(来源:wikimedia.org

说明:
* = 将字符打印到标准输出
N = '\n'
S = ' '
A = aA-zZ

我从Automata-based programming on Wikipedia 开始的代码适用于这么简单的机器,但我想对其进行修改,以便拥有更强大的状态转换表并根据这些状态调用函数。

我已经在 Pastebin 上发布了 working basic code 以及 the transtion table style I want to use

我之前没有使用过指向函数的指针,所以我不确定如何根据process_event 接收到的数据编写转换函数。最终,我希望有一个模板,让我能够拥有状态输入/输出和转换输入/输出功能,这样我就可以更有效地编写复杂的用户菜单甚至编程算法。

【问题讨论】:

  • 有趣的设置。你有什么问题?
  • 我的问题是我不确定如何实现我的状态机来执行地址通过状态转换表传递给它的函数。 (第二个链接)
  • 我现在有一个更完整的代码版本和一个带有一些调试输出的工作程序HERE。我遇到的主要问题是我无法为函数指针分配地址而不会出现编译器错误(我使用的是 g++)。我显然做错了什么,但我不明白......
  • 好吧,我脑子里放了个屁……我有铸造问题,经过足够的返工后我解决了。我用调试信息HERE 做了一个简单的用户界面我的设计的缺点是它非常笨重,你需要修改 StateMachine 类,特别是事件处理器来处理一种新的交互。我会使用 BOOST::FSM,但这是在 ARM 微控制器上进行的,所以我需要自己编写

标签: c++ state-machine


【解决方案1】:

将函数用作状态非常强大,但与使用递归函数(返回函数的函数状态)相比,使用转换表非常容易出错且痛苦。 quantum hierarchical statem machine 是一个供您考虑的绝妙实现。虽然它只有大约 1000 行代码作为基础,但它有 an accompanying book 来解释您可能对它的工作原理有任何疑问。非常强大,非常快。

【讨论】:

  • 我以前看过 Quantums 的产品,但它们看起来有点复杂,我不知道那本书。我现在仔细看看。为了学习,我仍然想编写自己的版本,因为我希望自己的版本与 c++、Java 和嵌入式平台相似。
  • @uMinded:Quantum 库已经移植到您将遇到的每一种语言,无论是嵌入的还是其他的。源代码/实现非常简洁,您可以轻松地根据自己的目的对其进行修改,就好像它是您自己的代码一样。没有任何状态机实现像这个一样被完整地记录下来。这是一个肯定的赌注。
  • 您可以消除转换表的所有错误倾向,并通过利用具有后期绑定的预处理器实际上使其超级健壮。例如。一处:"define STATE_LIST STATE_LIST_ENTRY(A) STATE_LIST_ENTRY(B) STATE_LIST_ENTRY(C) ...,然后(暂时)定义使用的入口宏,例如 `#define STATE_LIST_ENTRY(s) #s, \n char *state_names[] = {STATE_LIST}; \n #undef STATE_LIST_ENTRY"。这样你可以保证,如果你以后添加或删除一个状态,它会在任何地方应用。这同样适用于转换事件/信号。
  • 还有额外的好处:你可以通过在函数名中结合状态和事件来强制状态函数命名一致。
【解决方案2】:

您检查了吗
Boost.msm - 用于表达 UML2 有限状态机的高性能库。

阅读文档,因为这完全是关于管理状态机的复杂性。

您可能更喜欢 boost 中的其他状态机实现,因为它编译得更快,因为它不是为超高速而设计的(这并不意味着它不够快)Boost.Statechart - 任意复杂的有限状态机可以以易于阅读和可维护的 C++ 代码实现。

正如 Brent Arias 所说,您应该阅读来自 http://www.state-machine.com/psicc2/index.php 的书,这是状态机圣经。

【讨论】:

  • 感谢您提供的链接和那本书的链接!我之前没有使用过 BOOST 的许多功能,最近才发现它的元编程工具。当我在桌面环境中运行时,我希望代码清晰简洁,比速度更容易阅读。
  • 我将阅读上面的材料,然后我将布置我的代码结构,因为我想在伪代码中实现它,然后一次实现它。什么是合适的 stackExchange 站点来执行此操作?
  • 我认为这与您希望状态机库的外观无关,而是相反。您希望使用此库的代码是什么样的。
  • 因为除了我之外的其他人将使用我的 FSM 实现来使用我的程序,我需要接口具有极高的可读性,即使从非代码的角度来看也是如此。这是一个奇怪的时代,速度没有任何意义,一切都只是为了有条理的外观
【解决方案3】:

您的编译问题说它无法从 int 转换为 void (*)(int) 来自分支结构:

struct branch
{
    int event_type:3;
    enum states state_new:2;
    int do_func:1;
};

do_func 被定义为整数而不是void (*do_func)(int)

【讨论】:

  • 确实,我在查看代码 10 次但没有看到它之后发现了这一点。我终于记得我在结构中声明了它。
猜你喜欢
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多