文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>标准状态机的实现

标准状态机的实现

时间:2007-03-03  来源:wwling2001

标准状态机的实现

实现状态机不是很容易的事情,甚至对经典的非层次式的FSM,都必须作数量惊人的设计,判断和权衡:

²        如何表示时间?

²        具有参量的事件又怎样的?

²        如何表示状态?

²        如何表示转换?

²        如何分发事件到状态机?

当加入状态机层次,退出/进入动作以及带监视器的转换等时,设计就成了非常麻烦的工作。

在高级语言中,一般是状态机方法有:

²        嵌套的switch语句。

²        状态表(不介绍,自己实现或者看相关文档)。

²        面向对象的设计模式。

²        其他技术,可能是上面的混合(不介绍,自己实现或者看相关文档)。

该部分主要将平面状态机(非层次)的实现。

1:范例描述

统计数组中数字,字母和符号的个数。

2:状态图如下:

500)this.width=500;" border="0">

 

3:代码实现:

(1)       通过switch语句实现。

#include <stdio.h>

 

typedef enum tagState

{

    STA_NUM, STA_LET, STA_SYM,STA_EMPTY

} STATE;

 

typedef enum  tagSignal

{

    SIG_NUM, SIG_LET, SIG_SYM, SIG_EMPTY

} Signal;

 

static STATE CurState = STA_NUM;

static int Total_Num = -1;

static int Total_Let = 0;

static int Total_Sym = 0;

 

#define TRANS(state) (CurState = (state));

 

static void dispatch(Signal const sig)

{

    switch (CurState)

    {

    case STA_NUM:

       printf("Now in Number state\n");

       switch (sig)

       {

       case SIG_LET:

           TRANS(STA_LET);

           break;

       case SIG_SYM:

           TRANS(STA_SYM);

       }

       Total_Num++;

       break;

    case STA_LET:

       printf("Now in Letter state\n");

       switch (sig)

       {

       case SIG_NUM:

           TRANS(STA_NUM);

           break;

        case SIG_SYM:

           TRANS(STA_SYM);

           break;

       }

       Total_Let++;

       break;

    case STA_SYM:

       printf("Now in Symbol state\n");

       switch (sig)

       {

       case SIG_NUM:

           TRANS(STA_NUM);

           break;

       case SIG_LET:

           TRANS(STA_LET);

           break;

       }

       Total_Sym++;

       break;

    default:

       break;

    }

}

 

void main()

{

    char strBuf[20] = "1a2n3f4N5F&67%%#BT!";

    Signal curSig = SIG_EMPTY;

 

    for (int i = 0; i < 20 && strBuf[i] != '\0'; i++)

    {

       if (strBuf[i] >= '0' && strBuf[i] <= '9') curSig = SIG_NUM;

       else if ((strBuf[i] >= 'a' && strBuf[i] <= 'z')

           ||( strBuf[i] >= 'A' && strBuf[i] <= 'Z'))

           curSig = SIG_LET;

       else

           curSig = SIG_SYM;

 

       dispatch(curSig);

    }

    dispatch(curSig);

 

    printf("%s\n", strBuf);

    printf("The total number of figure is:%d\n", Total_Num);

    printf("The total number of letter is:%d\n", Total_Let);

    printf("The total number of symbol is:%d\n", Total_Sym);

}

(2)       通过面向对象的设计模式,分为C和C++实现。下面代码只是C++实现代码

下面是state_work.h的代码

#ifndef STATE_WORK_H

#define STATE_WORK_H

 

 

typedef enum  tagSignal

{

    SIG_NUM, SIG_LET, SIG_SYM, SIG_EMPTY

} Signal;

 

class CParser;

typedef void  (CParser::* State) (unsigned const sig);

#define TRANS(target_) m_state = (target_);

 

class  CParser

{

private:

    int m_nTotalFig;

    int m_nTotalLetter;

    int m_nTotalSymbol;

 

public:

    CParser();

    void Init();

    void Dispatch(unsigned const sig)

    {

       (this->*m_state)(sig);

    }

   

    int GetFigure(){return m_nTotalFig;}

    int GetLetter(){return m_nTotalLetter;}

    int GetSymbol(){return m_nTotalSymbol;}

 

private:

    void initial(unsigned const);

    void Figure(unsigned const sig);

    void Letter(unsigned const sig);

    void Symbol(unsigned const sig);

 

protected:

    State m_state; 

};

#endif //STATE_WORK_H

 

下面是State_work.cpp的代码

#include "state_work.h"

 

CParser::CParser()

{

    TRANS(&CParser::Figure);

}

void CParser::Init()

{

    (this->*m_state)(0);

    m_nTotalFig = -1;

    m_nTotalLetter = 0;

    m_nTotalSymbol = 0;

}

 

void CParser::Figure(unsigned const sig)

{

    switch (sig)

    {

    case SIG_LET:

       TRANS(&CParser::Letter);

       break;

    case SIG_SYM:

       TRANS(&CParser::Symbol);

    }

    m_nTotalFig++;

}

void CParser::Letter(unsigned const sig)

{

    switch (sig)

    {

    case SIG_NUM:

       TRANS(&CParser::Figure);

       break;

    case SIG_SYM:

       TRANS(&CParser::Symbol);

       break;

    }

    m_nTotalLetter++;

}

void CParser::Symbol(unsigned const sig)

{

    switch (sig)

    {

    case SIG_NUM:

       TRANS(&CParser::Figure);

       break;

    case SIG_LET:

       TRANS(&CParser::Letter);

       break;

    }

    m_nTotalSymbol++;

}

 

下面是Test.cpp的代码

#include <stdio.h>

#include "state_work.h"

 

void main()

{

    char strBuf[20] = "1a2n3f4N5F&67%%#BT!";

    Signal curSig = SIG_EMPTY;

    CParser parserObj;

   

    parserObj.Init();

    for (int i = 0; i < 20 && strBuf[i] != '\0'; i++)

    {

        if (strBuf[i] >= '0' && strBuf[i] <= '9') curSig = SIG_NUM;

       else if ((strBuf[i] >= 'a' && strBuf[i] <= 'z')

           ||( strBuf[i] >= 'A' && strBuf[i] <= 'Z'))

           curSig = SIG_LET;

       else

           curSig = SIG_SYM;

 

       parserObj.Dispatch(curSig);

    }

    parserObj.Dispatch(curSig);

 

    printf("%s\n", strBuf);

    printf("The total number of figure is:%d\n", parserObj.GetFigure());

    printf("The total number of letter is:%d\n", parserObj.GetLetter());

    printf("The total number of symbol is:%d\n", parserObj.GetSymbol());

}

 
状态机在嵌入式中的应用

嵌入式系统中很多方面都涉及到状态的变化,而在状态转化的设计工程中,一般是设计为居于优先状态机的状态图。

1:基本概念

²        状态:是系统声明中一种情况和条件。

²        扩展状态:程序变量一般和状态是分离的。系统的所有条件称为扩展状态,扩展状态是定性方面,状态和定量方面及扩展状态变量的集合。

²        事件:对系统很重要的时间和空间中的现象。严格讲,时间一词指现象的类型而不是任何具体事例。

²        动作:当一事件实例被分发时,状态机用完成动作来响应它。

²        转换:一个状态却换到另一个状态,称为状态转换。

²        触发:引起状态转换的事件,称为触发事件,简称出发。

²        状态转换图:以图形的形式描述状态转换。这些图是有向图,图中节点表示状态,而连接线表示转换。

500)this.width=500;" border="0">

²        组合状态:包含任何另外状态的状态。

²        简单状态:没有内部构造的状态。

²        内部转换:一些事件只引起执行某些内部动作,而不导致状态的改变。

²        伪状态:各种“泵转动装置”节点成为伪状态,伪装态是一种抽象,包含了在状态机图中过度节点的各种类型。

l             初始伪状态(黑点表示)表示约定转换的源,在一组和状态中,最多只能有一个初始伪状态。

l             浅-历史伪装态(用带圆圈的字母H表示)是缩写表示法。

l             深-历史伪装态(用带圆圈的H表示)

l             汇合伪转态

l             分支伪装态

l             接合伪装态

l             选择伪转态

2:层次式状态

500)this.width=500;" border="0">

如果系统是被嵌套在substate中,那么它也是在包围状态state1中。此状态机尝试处理在状态substate上下文的任何事件,但是如果状态substate没有规定如何处理事件,则该事件不是被或略掉,而是自动地在状态的较高一级状态state1的上下文中处理。

3:行为继承

状态嵌套的主要特性是来自抽象和层级的结合,即软件中的继承。继承的所有基本特性也同样适用于被嵌套的状态,因为状态嵌套也是基于is a 分类。只是在被嵌套的状态情况下,需要以is in某状态关系代替is a某类关系。状态嵌套允许子状态来继承自超状态的状态行为,即行为继承。

 

层次状态分解可被看作为应用于状态的“异或“。所以常被称为“或-分解”,而被嵌套状态称为“或-状态”。

500)this.width=500;" border="0">

用类描述嵌套关系为:

class CHeating

{

    //TODO: add your codes

    ...

}

class CToasting : public CHeating

{

    //TODO: add your codes

    ...

}

 

class CBaking : public CHeating

{

    //TODO: add your codes

    ...

}

3:正交区域

正交区域着重于,当系统的行为被划分成独立,并发的活动部分时,在状态数量上的组合增加这个常见问题。应用于状态的“和-分解”,这种分解意味着组合转态能包含两个或多个正交区域(正交意味独立上下文),以及在这样的组合状态中意味着同时在所有独立的正交区域中。

比如:Windows中的两个程序,Mp3播放器和Word Editor。他们在操作系统中是两个独立的进程,互不干扰多方工作。

500)this.width=500;" border="0">

4:细化事件处理

²        信号事件(Signal Event):表示特定(异步)信号的接受。

²        时间事件(Time Event):建模特定对后期限的期满。

²        调用事件(Call Event):表示对同步地调用特定的操作的请求。

²        变更事件(Change Event):建模当显式布尔表达式变成TRUE时出现的事件。

 

说明:具体的语法规范,参见<<UML使用指南>>

相关阅读 更多 +
排行榜 更多 +
寻找水源

寻找水源

休闲益智 下载
海星消灭战

海星消灭战

飞行射击 下载
激光狙击手

激光狙击手

飞行射击 下载