数电的状态机\C语言的状态机
状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转换,是协调相关信号动作、完成特定操作的控制中心。***有限状态机简称为FSM***,主要分为2大类:

第一类:若输出只和状态有关而与输入无关则称为Moore状态机。
第二类:若输出不仅和状态有关而且和输入有关系,则称为Mealy型状态机。
就是状态转移图。

举例:人有三个状态:健康,感冒,康复中。触发的条件有:淋雨,吃药,打针,休息。
所以状态机就是健康-(休息)->健康;健康-(淋雨)->感冒;感冒-(打针)->健康;感冒-(吃药)->康复中;康复中-(休息)->健康,等等。就是这样状态在不同的条件下跳转到自己或不同状态的图。

状态机综述

关于状态机的一个极度确切的描述是它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态, 状态机停止

包含一组状态集,一个起始状态,一组输入符号集,一个映射输入符号和当前状态到下一状态的转换函数的计算模型。当输入符号串,模型随机进入起始状态。他要改变到新的状态,依赖于转换函数。在有限状态机中,会有许多变量,例如:状态机有很多与动作转换(Mealy)或状态关联(Moore)动作,多起始状态,基于没有输入符号的转换,或者指定符号和状态(非定有限状态机)的多个转换,指派给接收状态(识别者)的一个或多个状态。

传统应用程序的控制流程基本是顺序的:遵循事先设定的逻辑,从头到尾地执行。很少有事件能改变标准执行流程;而且这些事件主要涉及异常情况。“命令行实用程序”是这种传统应用程序的典型例子。

另一类应用程序由外部发生的事件来驱动——换言之,事件在应用程序之外生成,无法由应用程序或程序员来控制。具体需要执行的代码取决于接收到的事件,或者它 相对于其他事件的抵达时间。所以,控制流程既不能是顺序的,也不能是事先设定好的,因为它要依赖于外部事件。事件驱动的GUI应用程序是这种应用程序的典 型例子,它们由命令和选择(也就是用户造成的事件)来驱动。
Web应用程序由提交的表单和用户请求的网页来驱动,它们也可划归到上述类别。但是,GUI应用程序对于接收到的事件仍有一定程度的控制,因为这些事件要依赖于向用户显示的窗口和控件,而窗口和控件是由程序员控制的。Web应用 程序则不然,因为一旦用户采取不在预料之中的操作(比如使用浏览器的历史记录、手工输入链接以及模拟一次表单提交等等),就很容易打乱设计好的应用程序逻辑。
显然,必须采取不同的技术来处理这些情况。它能处理任何顺序的事件,并能提供有意义的响应——即使这些事件发生的顺序和预计的不同。***有限状态机***正是为了满足这方面的要求而设计的。
有限状态机是一种概念性机器,它能采取某种操作来响应一个外部事件。具体采取的操作不仅能取决于接收到的事件,还能取决于各个事件的相对发生顺序。之所以能 做到这一点,是因为机器能跟踪一个内部状态,它会在收到事件后进行更新。为一个事件而响应的行动不仅取决于事件本身,还取决于机器的内部状态。另外,采取 的行动还会决定并更新机器的状态。这样一来,任何逻辑都可建模成一系列事件/状态组合。

[2]
状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果关系的考虑。“现态”和“条件”是***因***,“动作”和“次态”是***果***。详解如下:
①现态:是指当前所处的状态。
②条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

后面是重点

有限状态机

有限状态机FSM

思想广泛应用于硬件控制电路设计,也是软件上常用的一种处理方法(软 件上称为FMM–有限消息机)。它把复杂的控制逻辑分解成***有限个稳定状态***,在每个状态上判断事件,变连续处理为离散数字处理,符合计算机的工作特点。同时,因为有限状态机具有有限个状态,所以可以在实际的工程上实现。但这并不意味着其只能进行有限次的处理,相反,有限状态机是***闭环系统***,有限无穷,可以用有限的状态,处理无穷的事务

有限状态机有两种写法:
竖着的那种写法 还有横着的状态机,是用函数指针的形式来实现的,其实速度是一样的
现在的编译器 都会对switch进行优化的,
不过横着的那种状态机 可维护型更高,只需要增加 功能即可,不用每增加一次就修改switch的语句。
注:这个虽然使用了当前状态实现不同的功能但是,他没有转换到其他状态。所以和有限状态机是有区别的
状态机的可以用两种方法实现:
(1)竖着写(在状态中判断事件,即先通过switch来判断状态的,然后再通过不同的case里的时间来执行动作)
(2) 横着写(在事件中判断状态,即先发生事件,然后执行函数,把状态传递进去,然后根据不同的状态来执行不同的事件)

(下面的说法其实有些过时了,现在的编译器一般会优化竖着写的情况,但是为了可读性和习惯,一般使用第二种方法。)
竖着写和横着写,实现的功能是完全相同的,但是,横着写的效果明显好于竖着写的效果。理由如下:
1、竖着写隐含了优先级排序(其实各个时间是同优先级的),排在前面的事件判断将毫无疑问地优先于排在后面的事件判断。这种If/else if写法上的限制将破坏事件原有的关系。而横着写不存在此问题。
2、由于处于每个状态时的事件数目不一致,而且事件发生的事件是随机的,无法预先确定,导致竖着写沦落为顺序查询方式,结构上的缺陷使得大量时间被浪费。对于横着写,在某个时间点,状态时唯一确定的,在事件里查找状态只要使用switch语句,就能一步定位到相应的状态,延迟时间可以预先准确估算,而且在事件发生时,调用事件函数,在函数里查找唯一确定的状态,并根据其执行动作和状态转移的思路清晰简洁,效率高,富有美感。