层次状态机(HSM)用c语言的实现

合集下载

状态机编程思路及方法

状态机编程思路及方法

状态机编程思路及方法以状态机编程思路及方法为标题,写一篇文章。

一、引言状态机是一种常用的编程思路,它可以将程序的状态和状态之间的转换清晰地表达出来,使代码更加易于理解和维护。

本文将介绍状态机的基本概念、原理和实际应用,帮助读者更好地掌握状态机编程思路及方法。

二、状态机的基本概念1. 状态状态指的是程序运行过程中的一个特定阶段或情况,可以是系统状态、对象状态或任务状态等。

状态机将程序的运行过程抽象成一系列离散的状态,这些状态之间通过事件进行转换。

2. 事件事件是触发状态转换的信号或条件,可以是用户的输入、系统的通知或其他外部因素。

当一个事件发生时,状态机会根据当前的状态和事件,决定应该转换到哪个新的状态。

3. 转换转换表示状态之间的切换,它是从一个状态到另一个状态的过程。

转换可以是确定性的,也可以是非确定性的。

确定性转换是指根据当前状态和事件,只能转换到一个确定的新状态;非确定性转换是指根据当前状态和事件,可能转换到多个新状态中的任意一个。

三、状态机的原理状态机的原理是基于有限状态自动机(Finite State Automaton,简称FSA)。

FSA由一组状态、一组输入符号、一组输出符号和一组转移函数组成。

状态机在某个状态下,根据输入符号,通过转移函数确定下一个状态,并输出相应的输出符号。

通过这种方式,状态机能够根据不同的输入,自动地在不同的状态之间切换。

四、状态机的实际应用1. 编译器编译器是一个典型的实际应用场景,其中的词法分析和语法分析阶段使用状态机来处理输入的字符序列。

状态机可以根据不同的字符,切换到不同的状态,从而实现对输入的有效解析。

2. 游戏开发游戏中的角色状态管理、敌人行为控制等都可以使用状态机来实现。

例如,角色可以有站立、行走、奔跑等不同的状态;敌人可以有巡逻、追击、攻击等不同的状态。

通过状态机,游戏开发者可以方便地管理角色和敌人的行为逻辑。

3. 设备控制在嵌入式系统中,状态机常用于对设备的控制和调度。

C#状态机Stateless

C#状态机Stateless

C#状态机Stateless最近在折腾⼀些控制相关的软件设计,想起来状态机这个东西,对解决⼀些控制系统状态切换还是挺有⽤的。

状态机(有限状态⾃动机)⽹上有很多。

简单理解就是定义⼀系列状态,通过⼀系列的事件,可以使得状态可以相互之间切换。

如果不使⽤状态机的思想来编程,那么针对过程的编程⽅法会使得程序拓展性变差,并且不容易调试。

⽽状态机只需要定义好了各种状态和状态切换之间的事件,你只管触发事件,剩下的事情它⾃⼰就⾃动完成了(毕竟名称叫做有限状态⾃动机),这对于很多需要定义各种控制阶段的系统简直是完美适配。

了解到.NET也有很多库可以实现这些功能,本⽂主要介绍⼀下Stateless的应⽤。

Stateless介绍可以创建极简的状态机与对应的⼯作流。

很多项⽬(包括VisualStudio Extension、AIlab)都有使⽤到它。

它⽀持以下特性:⽀持各种类型作为状态和触发事件⽀持状态继承⽀持状态进⼊/离开事件⽀持条件状态转移⽀持状态/转移查询也有⼏点需要注意的:它⽀持异步语法,但是它是单线程的,不是线程安全的。

可以导出DOT graph安装起来很简单,直接在nuget中安装即可:Install-Package StatelessStateless使⽤⽤起来也挺简单的,以打电话这个事情为例,针对打电话的种种动作和状态做成⼀个状态机。

需要先定义⼀些状态和事件/触发器,电话有拨号、接通、留⾔等事件,有响铃、挂起、挂断等事件://代码来⾃官⽅⽰例,可以在官⽅github库上找到,略有修改以完整展⽰功能。

enum Trigger{CallDialed,CallConnected,LeftMessage,PlacedOnHold,TakenOffHold,PhoneHurledAgainstWall,MuteMicrophone,UnmuteMicrophone,SetVolume}enum State{OffHook,Ringing,Connected,OnHold,PhoneDestroyed}然后就是创建⼀个状态机了:_machine = new StateMachine<State, Trigger>(() => _state, s => _state = s);最后也是最需要详细解释的,就是配置状态机的⾏为了:/*为了解释尽可能多的功能,以下程序修改了官⽅的代码,可以在官⽅找可以直接执⾏的代码。

程序设计之有限状态机

程序设计之有限状态机

程序设计之有限状态机程序设计之有限状态机状态机?以前听说过,忘了是老师说的,还是老大说得了。

当时的认识也就是字面的意思,无非是和状态以及状态转换有关系。

也许在写过或者读过的一些代码中有遇到过有限状态机的程序,但是当时是一定没有想到这就是状态机吧。

最近在学习一些东西的时候竟然多次遇到,觉得还是有必要写点关于程序设计中有限状态机的东西。

,这里是一篇对状态机从定义到实现都有很好解释的文章,摘录部分如下:*************************************************************** ************************依据状态之间是否有包含关系,分以下两种(1)常规状态机。

状态机中的所有状态是不相交的、互斥的。

(2)层次状态机。

状态机中的状态之间要么是互斥的,要么是真包含的,可以用树性结构来描述这些状态集,包含其它状态的状态称为枝节点,不包含其它状态的状态称为叶节点,为方便单树描述,总是设计一个状态包含所有的状态节点,称为根节点。

状态机的状态只能停留在叶节点,而不能停留在枝节点,每个枝节点需要指定一个子节点为它的默认子节点,以便状态机进入枝节点的时候能够停留到叶节点。

一般都用switch/case if/else方式实现。

在少量状态(3个及其以下)的时候,不需要引入专门的状态机模块。

常规状态机模块实现涉及到的结构由上而下为:顶层结构是状态机:当前状态id,缺省操作,状态表,状态表:状态数组状态结构:状态id,状态名,进入操作,退出操作,缺省操作,状态事件表(数组)状态事件结构:操作,事件,下一状态的id*************************************************************** ************************从代码易读及美观角度来说,建议用switch/case来实现。

从经验来看,在一些稍大的程序设计中一般都会有状态机的实现,特别是在分层实现,协议栈实现,编解码方面。

c语言信号量的使用

c语言信号量的使用

c语言信号量的使用信号量是操作系统中用于实现进程间同步和互斥的一种机制。

在C 语言中,通过使用信号量,可以控制多个进程或线程的并发访问共享资源,避免出现竞态条件和死锁等问题。

信号量的使用通常涉及到三个主要操作:创建、等待和释放。

在C 语言中,可以使用系统提供的信号量函数来完成这些操作。

我们需要创建信号量。

在C语言中,可以使用semget函数来创建一个信号量集合。

该函数接受三个参数,分别是信号量的标识符、信号量的数量和信号量的访问权限。

创建成功后,semget函数会返回一个唯一的标识符,用于后续的操作。

接下来,我们可以使用semop函数来等待和释放信号量。

semop 函数接受三个参数,分别是信号量的标识符、一个指向sembuf结构体数组的指针和结构体数组的长度。

sembuf结构体中包含了信号量操作的相关信息,例如等待或释放信号量的数量。

对于等待操作,可以将sembuf结构体的sem_op字段设置为负数,表示等待信号量。

如果当前信号量的值大于等于等待的数量,则可以继续执行后续代码。

否则,当前进程或线程将被阻塞,直到信号量的值大于等于等待的数量。

对于释放操作,可以将sembuf结构体的sem_op字段设置为正数,表示释放信号量。

释放操作会增加信号量的值,从而允许其他进程或线程继续执行等待操作。

除了等待和释放操作外,还可以使用semctl函数来获取或修改信号量的值。

semctl函数接受三个参数,分别是信号量的标识符、要执行的操作和一个union semun结构体。

通过设置semun结构体的val字段,可以修改信号量的值。

在使用信号量时,需要注意以下几点。

首先,要确保所有的进程或线程都使用相同的信号量标识符,以便它们可以访问同一个信号量集合。

其次,要避免出现死锁的情况,即所有的进程或线程都在等待信号量,而没有释放信号量的操作。

为此,可以使用PV操作来保证互斥访问共享资源。

PV操作是指通过等待和释放信号量来实现进程间互斥的一种方法。

c语言中system函数的使用

c语言中system函数的使用

c语言中system函数的使用system(函数是C语言中的库函数之一,可以用于执行系统命令。

它是通过调用操作系统的shell来执行命令,并在命令执行完成后返回。

system(函数的声明如下:```c```下面是使用system(函数的一些常见用法:1.执行简单的单个命令```c#include <stdlib.h>#include <stdio.h>int maisystem("ls"); // 在Linux下,执行ls命令return 0;```利用system(函数可以执行一些简单的命令,例如在Linux下执行`ls`命令,可以通过输出来查看当前目录下的文件和文件夹。

2.执行带有命令行参数的命令```c#include <stdlib.h>#include <stdio.h>int maisystem("gcc -o hello hello.c"); // 编译hello.c文件为可执行文件helloreturn 0;```使用system(函数可以执行带有命令行参数的命令,例如在Linux下使用GCC编译`hello.c`文件为可执行文件`hello`。

3.使用条件语句判断命令执行结果```c#include <stdlib.h>#include <stdio.h>int maiint result = system("gcc -o hello hello.c"); // 编译hello.c 文件为可执行文件helloif (result == 0)printf("编译成功!\n");} elseprintf("编译失败!\n");}return 0;```可以将system(函数的返回值与预先定义的常量进行比较,例如0表示命令执行成功。

c语言同步的实现方式

c语言同步的实现方式

c语言同步的实现方式C语言中,同步(synchronization)是一种用来协调不同线程或进程之间执行顺序的技术。

同步的实现方式可以通过以下几种机制:1. 互斥锁(Mutex):互斥锁是最常用的同步机制之一。

它允许线程通过获取锁将自己排他地访问共享资源,其他线程必须等待锁释放后才能访问该资源。

C语言提供了互斥锁相关的函数,如`pthread_mutex_init`、`pthread_mutex_lock`、`pthread_mutex_unlock`等。

2. 信号量(Semaphore):信号量是一种计数器,用于控制对资源的访问。

当信号量的值大于零时,线程可以访问资源,访问后将信号量值减一;当信号量的值等于零时,线程必须等待。

C语言提供了信号量相关的函数,如`sem_init`、`sem_wait`、`sem_post`等。

3. 条件变量(Condition Variable):条件变量用于在某些条件满足时才允许线程继续执行。

线程可以通过条件变量等待某个条件的发生,当条件满足时,其他线程可以通过条件变量通知等待的线程继续执行。

C语言提供了条件变量相关的函数,如`pthread_cond_init`、`pthread_cond_wait`、`pthread_cond_signal`等。

4. 屏障(Barrier):屏障用于让多个线程在某个点上等待,直到所有线程都到达该点后才能继续执行。

屏障可以用于同步多个线程的执行流程,以便它们在某个共享状态达到一致后再继续执行。

C语言提供了屏障相关的函数,如`pthread_barrier_init`、`pthread_barrier_wait`等。

这些同步机制可以根据具体的应用场景选择使用。

在使用这些同步机制时,需要注意避免死锁(Deadlock)和竞态条件(Race Condition)等常见的同步问题,确保线程可以正确、安全地协作。

同时,还可以使用线程和进程间的通信机制,如管道、消息队列、共享内存等,来实现更复杂的同步和数据共享需求。

c语言编译原理详解

c语言编译原理详解
将.o文件转化成可执行程序
使用的gcc 命令是: gcc
对应于链接命令是 ld
总结起来编译过程就上面的四个过程:预编译、编译、汇编、链接。了解这四个过程中所做的工作,对我们理解头文件、库等的工作过程是有帮助的,而且清楚的了解编译链接过程还对我们在编程时定位错误,以及编程时尽量调动编译器的检测错误会有很大的帮助的。
第二个阶段编译、优化阶段。经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。
编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
第一种是链接程序可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个 目标文件;
第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。
(3)可执行文件
它包含了一个可以被操作系统创建一个进程来执行之的文件。汇编程序生成的实际上是第一种类型的目标文件。对于后两种还需要其他的一些处理方能得到,这个就是链接程序的工作了。
一、编译过程
编译过程又可以分成两个阶段:编译和汇编。
1、编译
编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,源文件的编译过程包含两个主要阶段:
第一个阶段是预处理阶段,在正式的编译阶段之前进行。预处理阶段将根据已放置在文件中的预处理指令来修改源文件的内容。如#include指令就是一个预处理指令,它把头文件的内容添加到.cpp文件中。这个在编译之前修改源文件的方式提供了很大的灵活性,以适应不同的计算机和操作系统环境的限制。一个环境需要的代码跟另一个环境所需的代码可能有所不同,因为可用的硬件或操作系统是不同的。在许多情况下,可以把用于不同环境的代码放在同一个文件中,再在预处理阶段修改代码,使之适应当前的环境。

层次状态机

层次状态机

层次状态机1状态机介绍状态机(State Machine)是计算机科学的一种抽象模型,它简化了复杂系统的行为和运作流程。

通过刻画状态(State)和转换(Transition),它能够描述一个系统以及如何从一种状态转变为另一种状态的复杂性。

状态机模型有利于综合研究一个系统的多种性能指标和行为规律,以及帮助软件工程师提高软件系统的可读性,可维护性和可重用性。

2多层次状态机多层次状态机(Hierarchical State machine,简称HFSM)是由相关状态(State)和可从一个状态到另一个状态进行转换(Transition)形成的被定义的数据结构。

HFSM可以通过状态和变迁构建多层次的状态机模型,存在嵌套状态(Nested State),并且每个状态可以有多个外部或内部状态(External or Internal State)。

HFSM能帮助开发者分层(Layer)结构化的描述模型,并可以求解一个状态下各子状态的转换、判断,以及决定它们在不同状态下行为的结果。

3优势HFSM有以下几个优势:1.模型可读性强:由于HFSM可以分层描述系统的行为,使得模型更加可读,更容易理解;2.模型易维护:HFSM可以做到调整一个模块不影响其他模块;3.可可重用性:HFSM提供多层次、嵌套结构,可以较大程度上提高软件系统的可重用性,节约开发时间;4.调控正确性:HFSM可以确保模型能够正确地调控和管理复杂系统的多层行为,确保系统的正确运行。

4应用HFSM模型被广泛应用于计算机科学的水平,尤其是自动控制、视觉处理和通信技术等领域的开发工作中,可以高效地描述系统的行为,并实现系统的层次抽象,加快系统设计过程,提高软件系统质量。

因此,多层次状态机模型得到了日益广泛的应用。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

分类:本文讲述层次状态机实现形式中的行为继承。

从行为继承与类继承之间的OO类相似来看,一个成功的层次状态机应该能够模拟下列属于C++对象模型。

✧使用和维护简单✧应允许转态机拓扑容易改变,不应要求转换连接的人工代码,所需要的修改限制在代码的一个地方。

✧提供好的运行-时间效率和小的存储。

✧遵守C++中的“零额外开销”原则。

为了满足上面的要求,层次状态机的实现着重于下面的主要元素:✧完全支持行为继承的层次关系✧用状态进入和退出动作实现有保证得初始化和清除✧通过类继承支持规定的状态模型1.基本要素(1)状态:在层次状态的情形下,状态处理器必须返回朝状态,这导致层次状态处理特征标记的递归定义。

构造这种特征标记在C++是不可能的,于是定义下面宏来近似:typedef void (* QPseudoState)(QEVENT const *pEvent);typedef QPseudoState (* QState)(QEVENT const *pEvent);(2)进入/退出动作和初始状态:这些元素是状态专有的特征,在转态中他们被定义,而特别的是与到达状态所进过的路径无关。

保留信号的转态定义为:typedef enum tagQSIG{Q_EMPTY_SIG = 1,Q_INIT_SIG,Q_ENTRY_SIG,Q_EXIT_SIG,Q_USER_SIG,} QSIG;状态处理机可以用一般的switch语句规定适当的用例处理这些信号,可以自由的执行相应信号的操作。

(3)状态转换:状态处理机用Q_TRAN实现状态转换,并且在原状态的上下文中执行动作,即:改变状态之前调用Q_TRAN(和UML规定不一致)。

#define Q_TRAN(target_) Q_TranDyc((QState)(target_))(4)Top状态和初始伪状态:每个层次状态机都有一个Top状态,包括整个状态的所有其它元素。

Top状态没有超状态,用户也不能覆盖;Top状态的唯一目的是提供状态层次的最高的根,使最高处理器能返回Top;Top状态唯一能订制的是初始化。

初始化伪状态处理机仅规定初始化转换,必须指明被窃套的Top状态的状态机的缺省状态。

2.实现代码:(1)头文件代码:#ifndef STATE_INHERIT_H#define STATE_INHERIT_Htypedef unsigned short QSIG;// Define the signal of state machineenum{Q_EMPTY_SIG = 0,Q_INIT_SIG = 1,Q_ENTRY_SIG,Q_EXIT_SIG,Q_USER_SIG};// Define the signal of state machinetypedef struct tagQEVENT{QSIG sig;unsigned char *pEvent1;unsigned char *pEvent2;// TODO: add fields to the event} QEVENT;// define state data typetypedef void (* QPseudoState)(QEVENT const *pEvent); typedef QPseudoState (* QState)(QEVENT const *pEvent); typedef QPseudoState QSTATE;#define Q_TRIGGER(state, sig) \(QState)(*(state))((QEVENT*)&pkgStdEvt[sig])// define a transation that don't change the state,// just treat the pEvent with the target state.// this is used by concurrent state#define Q_INIT(target_) Init_((QState)(target_));#define Q_TRAN(target_) Q_TranDyc((QState)(target_));void Init_(QState target);void Q_Init(QSTATE target);void Q_Initial(QEVENT const* pQevt);void Q_Dispatch(QEVENT const* pQevt);void Q_TranDyc(QState target);#endif//STATE_INHERIT_H(2)实体代码:#include <stdio.h>#include <assert.h>#include "state_inherit.h"static QState srcState; // source state static QState actState; // active state static QEVENT const pkgStdEvt[] ={{Q_EMPTY_SIG, 0, 0},{Q_INIT_SIG, 0, 0},{Q_ENTRY_SIG, 0, 0},{Q_EXIT_SIG, 0, 0}};void Q_Initial(QEVENT const* pQevt){printf("Top_Init;");}void Q_Dispatch(QEVENT const* pQevt){for (srcState = actState; srcState;srcState = (QState)(*srcState)(pQevt)) {}}void Init_(QState target){actState = target;}void Q_Init(QSTATE target){register QState s;actState = (QState)target;srcState = (QState)Q_Initial;s = actState; // save actState in a temporary(*(QPseudoState)srcState)((QEVENT*)0); // top-most initial tran.// initial transition must go one level deeps = actState; // update the temporaryQ_TRIGGER(s, Q_ENTRY_SIG); // enter the state while (0 == Q_TRIGGER(s, Q_INIT_SIG)){// init handled// initial transition must go one level deeps = actState;Q_TRIGGER(s, Q_ENTRY_SIG); // enter the substate}}void Q_TranDyc(QState target){QState entry[8], p, q, s, *e, *lca;for (s = actState; s != srcState; ){QState t;t = Q_TRIGGER(s, Q_EXIT_SIG);if (t){// exit action unhandled, t points to superstates = t;}else{// exit action handled, elicit superstates = Q_TRIGGER(s, Q_EMPTY_SIG);}}*(e = &entry[0]) = 0;*(++e) = target; // assume entry to target// (a) check source == target (transition to self)if (srcState == target){Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source goto inLCA;}// (b) check source == target->superp = Q_TRIGGER(target, Q_EMPTY_SIG);if (srcState == p) goto inLCA;//(c) check source->super == target->super (most common)q = Q_TRIGGER(srcState, Q_EMPTY_SIG);if (q == p){Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source goto inLCA;}// (d) check source->super == targetif (q == target){Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source--e; // not enter the LCA goto inLCA;}// (e) check rest of source == target->super->super... hierarchy*(++e) = p;for (s = Q_TRIGGER(p, Q_EMPTY_SIG); s; s = Q_TRIGGER(s, Q_EMPTY_SIG)) {if (srcState == s){goto inLCA;}*(++e) = s;}Q_TRIGGER(srcState, Q_EXIT_SIG); // exit source // (f) check rest of source->super == target->super->super...for (lca = e; *lca; --lca){if (q == *lca){e = lca - 1; // do not enter the LCAgoto inLCA;}}// (g) check each srcState->super->super..for each target...for (s = q; s; s = Q_TRIGGER(s, Q_EMPTY_SIG)){for (lca = e; *lca; --lca){if (s == *lca){e = lca - 1; // do not enter the LCAgoto inLCA;}}Q_TRIGGER(s, Q_EXIT_SIG); // exit s}assert(0); // malformed HSMinLCA: // now we are in the LCA of srcState and targetassert(e < &entry[sizeof(entry) / sizeof(*entry)]); // entry fits while (s = *e--){// retrace the entry path in reverse orderQ_TRIGGER(s, Q_ENTRY_SIG); // enter s}actState = target; // update current state while (0 == Q_TRIGGER(target, Q_INIT_SIG)){// initial transition must go one level deepassert(target == Q_TRIGGER(actState, Q_EMPTY_SIG));target = actState;Q_TRIGGER(target, Q_ENTRY_SIG); // enter target }3.范例:(1)范例状态图(2)范例代码#include <stdio.h>#include "state_inherit.h"QSTATE s0(QEVENT const *e);QSTATE s1(QEVENT const *e);QSTATE s2(QEVENT const *e);QSTATE s11(QEVENT const *e);QSTATE s21(QEVENT const *e);QSTATE s211(QEVENT const *e);QSTATE Q_Top(QEVENT const *e);static void Initial(QEVENT const *e);static bool bFoo;enum QSignals {A_SIG = Q_USER_SIG,B_SIG, C_SIG, D_SIG, E_SIG, F_SIG, G_SIG, H_SIG};static const QEVENT testQEvt[] ={{A_SIG, 0, 0}, {B_SIG, 0, 0}, {C_SIG, 0, 0}, {D_SIG, 0, 0}, {E_SIG, 0, 0}, {F_SIG, 0, 0}, {G_SIG, 0, 0}, {H_SIG, 0, 0} };int main(){printf("Hiberarchy state machine testing\n");Initial(0); // trigger initial transition for (;;){char c;printf("\nSignal<-");c = getc(stdin);getc(stdin); // discard '\n'if (c < 'a' || 'h' < c) {return 0;}Q_Dispatch(&testQEvt[c - 'a']); // dispatch}return 0;}static QSTATE Q_Top(QEVENT const *e){return 0;}void Initial(QEVENT const *e){bFoo = false;Q_Init((QSTATE)s0);}QSTATE s0(QEVENT const *e) {if (e != NULL){switch (e->sig){case Q_ENTRY_SIG: printf("s0-ENTRY;"); return 0;case Q_EXIT_SIG: printf("s0-EXIT;"); return 0;case Q_INIT_SIG: printf("s0-INIT;"); Q_INIT(s1); return 0;case E_SIG: printf("s0-E;"); Q_TRAN(s211); return 0; }}return (QSTATE)Q_Top;}QSTATE s1(QEVENT const *e) {switch (e->sig) {case Q_ENTRY_SIG: printf("s1-ENTRY;"); return 0;case Q_EXIT_SIG: printf("s1-EXIT;"); return 0;case Q_INIT_SIG: printf("s1-INIT;");Q_INIT(s11); return 0;case A_SIG: printf("s1-A;"); Q_TRAN(s1); return 0;case B_SIG: printf("s1-B;"); Q_TRAN(s11); return 0;case C_SIG: printf("s1-C;"); Q_TRAN(s2); return 0;case D_SIG: printf("s1-D;"); Q_TRAN(s0); return 0;case F_SIG: printf("s1-F;"); Q_TRAN(s211);return 0;}return (QSTATE)s0;}QSTATE s11(QEVENT const *e) {switch (e->sig) {case Q_ENTRY_SIG: printf("s11-ENTRY;"); return 0;case Q_EXIT_SIG: printf("s11-EXIT;"); return 0;case G_SIG: printf("s11-G;"); Q_TRAN(s211); return 0;case H_SIG: // internal transition with a guard if (bFoo){ // test the guard conditionprintf("s11-H;");bFoo = false;return 0;}break;}return (QSTATE)s1;}QSTATE s2( QEVENT const *e) {switch (e->sig) {case Q_ENTRY_SIG: printf("s2-ENTRY;"); return 0;case Q_EXIT_SIG: printf("s2-EXIT;"); return 0;case Q_INIT_SIG: printf("s2-INIT;");Q_INIT(s21); return 0;case C_SIG: printf("s2-C;"); Q_TRAN(s1); return 0;case F_SIG: printf("s2-F;"); Q_TRAN(s11); return 0;}return (QSTATE)s0;}QSTATE s21(QEVENT const *e) {switch (e->sig) {case Q_ENTRY_SIG: printf("s21-ENTRY;"); return 0;case Q_EXIT_SIG: printf("s21-EXIT;"); return 0;case Q_INIT_SIG:printf("s21-INIT;");Q_INIT(s211);return 0;case B_SIG: printf("s21-C;"); Q_TRAN(s211);return 0;case H_SIG: // self transition with a guard if (!bFoo){ // test the guard conditionprintf("s21-H;");bFoo = true;Q_TRAN(s21); // self transitionreturn 0;}break; //break to return the superstate }return (QSTATE)s2;}QSTATE s211(QEVENT const *e) {switch (e->sig) {case Q_ENTRY_SIG: printf("s211-ENTRY;"); return 0;case Q_EXIT_SIG: printf("s211-EXIT;"); return 0;case D_SIG: printf("s211-D;"); Q_TRAN(s21); return 0;case G_SIG: printf("s211-G;"); Q_TRAN(s0); return 0;}return (QSTATE)s21;}(3)输出结果:Hiberarchy state machine testingTop_Init;s0-ENTRY;s0-INIT;s1-ENTRY;s1-INIT;s11-ENTRY;Signal<-as1-A;s11-EXIT;s1-EXIT;s1-ENTRY;s1-INIT;s11-ENTRY;Signal<-es0-E;s11-EXIT;s1-EXIT;s2-ENTRY;s21-ENTRY;s211-ENTRY;Signal<-es0-E;s211-EXIT;s21-EXIT;s2-EXIT;s2-ENTRY;s21-ENTRY;s211-ENTRY; Signal<-aSignal<-hs21-H;s211-EXIT;s21-EXIT;s21-ENTRY;s21-INIT;s211-ENTRY;Signal<-hSignal<-x说明:上面功能都是通过C语言实现的,大家可以将其用C++实现,共享一下。

相关文档
最新文档