C语言实现有限状态机

C语言实现有限状态机1 什么是有限状态机有限状态机在百度百科上的解释为 有限状态自动机 FSM finitestatem 或者 FSA finitestatea 是为研究有限内存的计算过程和某些语言类而抽象出的一种计算模型 有限状态自动机拥有有限数量的状态 每个状态可以迁移到零个或多个状态 输入字串决定执行哪个状态的迁移 有限状态自动机可以表示为一个有向图 2 有

1. 什么是有限状态机

2. 有限状态机的应用场景

3.状态机的基本框架

3.1 定义状态

如果要使用状态机进行解决问题,首先要确定这个问题本事有几个状态,然后我们把所用的状态做一个枚举类型的定义,问什么是枚举类型呢? 因为我们定义==状态的目的就是把状态当作索引值==,这可以说是状态机实现的精髓了,因为它就是根据当前的状态来确定下一步的行为。
例如:一个问题有三种状态,则可以使用这样的定义:

enum { 
    STATE_0 = 0, /* 数据下标从0开始,因此开始设置为0,后边逐渐递增*/ STATE_1, STATE_2, }FSM_STATE; 

3.2定义事件

enum { 
    EVENT_NOT_SPACE=0, /*数据下标索引,从0开始*/ EVENT_SPACE, EVENT_STR, }FSM_EVENTS; 

3.3定义状态机的结构体

因为我们已经知道状态机是有状态和事件构成的,因此状态机的结构体可以定义为 “动作”+“下一状态”
例如:

struct FSM_node{ 
    void (*func)(char *); /*当前状态下,发生某个事件所采取的措施*/ int next_state; /*这个事件发生后,要切换的状态*/ }; 
struct { 
    int (*func)(char *); int next_state; }FSM[STATE_NUM][EVENT_NUM]= { 
    { 
   /*current state isNotSpace : 状态0*/ { 
   isNotSpace_func1,STATE_0}, /*NOT_SPACE:状态0时遇到一个非空格,打印 + 下一状态为状态0*/ { 
   isNotSpace_func2,STATE_1}, /*IS_SPACE*:状态0时遇到一个空格,打印 + 下一状态为状态1 */ }, { 
   /*current state isSpace : 状态1*/ { 
   isSpace_func1, STATE_0}, /*NOT_SPACE:状态1时遇到一个非空格,打印 + 下一状态为状态0*/ { 
   isSpace_func2, STATE_1}, /*IS_SPACE:状态1时遇到一个空格,不打印 + 下一状态为状态1*/ }, }; 

3.4 画状态变迁图

4实例

4.1实例一

问题:除去一个字符串中连续的空格,只保留一个。
状态变迁图
在这里插入图片描述
在这里插入图片描述
代码实现








#include  
     typedef enum{ 
    STATE_0 = 0, STATE_1, }state; typedef enum{ 
    NOT_SPACE= 0, IS_SPACE, }events; #define STATE_NUM 2 #define DEVENT_NUM 2 int isNotSpace_func1(char *str) { 
    putchar(*str); } int isNotSpace_func2(char *str) { 
    putchar(*str); } int isSpace_func1(char *str) { 
    putchar(*str); } int isSpace_func2(char *str) { 
    ; /*do nothing*/ } struct { 
    int (*func)(char *); int next_state; }FSM[STATE_NUM][DEVENT_NUM]= { 
    { 
   /*current state isNotSpace*/ { 
   isNotSpace_func1,STATE_0}, /*NOT_SPACE*/ { 
   isNotSpace_func2,STATE_1}, /*IS_SPACE*/ }, { 
   /*current state isSpace : 状态1*/ { 
   isSpace_func1, STATE_0}, /*NOT_SPACE*/ { 
   isSpace_func2, STATE_1}, /*IS_SPACE*/ }, }; /*根据当前状态和当前事件做索引,找到对应的处理情况;然后再获取下一状态*/ void demo1() { 
    char str[] = "h e l l o, w o r l d;"; char *p = str; int state_now = STATE_0; int _event, ret; while(*p){ 
    if(*p==' ') _event = IS_SPACE; else _event = NOT_SPACE; /* FSM[state_now][_event]: 节点对象*/ /* (FSM[state_now][_event]).func : 该对象函数指针*/ /* *((FSM[state_now][_event]).func) : 获取到函数指针指向的函数*/ ret = (*((FSM[state_now][_event]).func))(p); state_now = (FSM[state_now][_event]).next_state; p++; } } 

结果:

root# ./a.out root# h e l l o, w o r l d; 

4.2实例二

问题:除去一个字符串中连续的空格,只保留一个,但保留双引号(“ ”)内的所有字符。
状态变迁图
在这里插入图片描述
代码实现






#include  
     enum { 
    STATE_0 = 0, STATE_1, STATE_2, }FSM_STATE; enum { 
    EVENT_NOT_SPACE=0, EVENT_SPACE, EVENT_STR, }FSM_EVENTS; #define STATE_NUM 3 #define EVENT_NUM 3 void func1(char *str) { 
    putchar(*str); } void func2(char *str) { 
    putchar(*str); } void func3(char *str) { 
    putchar(*str); } void func4(char *str) { 
    putchar(*str); } void func5(char *str) { 
    ; } void func6(char *str) { 
    putchar(*str); } void func7(char *str) { 
    putchar(*str); } void func8(char *str) { 
    putchar(*str); } void func9(char *str) { 
    putchar(*str); } struct { 
    void (*func)(char *); int next_state; }FSM_test2[STATE_NUM][EVENT_NUM]= { 
    { 
   //state_0 not space { 
   func1, STATE_0}, { 
   func2, STATE_1}, { 
   func3, STATE_2}, }, { 
   //state_1 space { 
   func4, STATE_0}, { 
   func5, STATE_1}, { 
   func6, STATE_2}, }, { 
   //state_2 "" { 
   func7, STATE_2}, /* when first " is reached, the state is always STATE_2, only when the next " reached, next state is STATE_0*/ { 
   func8, STATE_2}, { 
   func9, STATE_0}, }, }; void demo2() { 
    char str[] = "h e l l o ,\"today is friday !!!\" w o r l d ."; char *p = str; int ret; int state = STATE_0; int event; while(*p){ 
    if(*p==' ') event = EVENT_SPACE; else if(*p=='"') event = EVENT_STR; else event = EVENT_NOT_SPACE; //printf("\n-----state=%d-----event=%d------\n",state, event); (*(FSM_test2[state][event].func))(p); state = FSM_test2[state][event].next_state; p++; } putchar(10); } 

结果:

root# ./a.out root# h e l l o ,"today is friday !!!" w o r l d . 

定义了很多同样的实现函数,只是为了说明每一种(状态,事件)都有各自的处理情景,这个栗子只是巧合

5结束

状态机的C语言基本实现框架就是这样,后续如果有经典的状态机实现,做更新处理。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/206387.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午3:49
下一篇 2026年3月19日 下午3:49


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号