C语言最优状态机规范

前言

近来思绪有点停不下来,构思了一个GUI的框架(用在Cotex-M平台上,很小),期待以后有时间去实现,里面有一个对触摸屏的检测,自然想到使用状态机进行消息的生成和分发,于是想着实现一个状态机实现的模型,以后再其他项目上应用也方便。

状态机的好处不用多说,自己百度去,但传统的编程模式,无论是C语言,或是硬件FPGA的Verilog都是采用switch-case结构,硬件的还好说,是并行的,但如果是C语言实现状态机则可能需要对每个case进行判断,状态少比如几个可能没什么效率之类的问题,但状态多几十个上百个呢,那么就需要进行上百次的判断是否匹配,毫无疑问效率很低,切每次的状态==切换时间==也不确定。那么有没有一种好的实现模式不用switch-case结构呢?下面我来为C语言状态机的实现建立一个最优规范。

实现

前面说了一堆装bi的废话,下面进入正题,前段时间研究了下函数式编程,发现C语言的循环结构完全可以用尾递归(不懂百度)实现,最后C就只剩下唯有if和switch还不能用函数式编程实现,而今天要讲的状态机模式就是用函数式编程实现switch-case,那么switch-case其实可以看做一种查找的跳转,我们知道C语言中goto可以实现跳转,那么还有什么可以实现跳转呢,答案是函数调用,但是又需要如何实现指定的函数调用呢,难道要用if判断,显然没什么意义,那么又没有比if判断(如果上百次判断)更高效的东西呢?有人已经想到是查表,如果将查表和函数调用结合,那么就是函数指针数组的应用了!

上代码!首先定义一个函数指针类型,为什么要带void *的参数后面会说:

typedef unsigned char State; typedef State(*Procedure)(void *);

这样就可以方便地定义一个函数指针数组:

ProcedureSteps[] ={ step_init, step_count, step_done, step_default };

step_init,step_count等是函数名,再定义状态:

enumstates{ s_init, s_count, s_done, s_default };

枚举定义对应着{0,1,2,3},有了这些再状态机联系那么可以想到,数组的索引就是状态定义,上核心代码,两行(简单吧!关键是想到):

voidBestStateMachine(void* invar) {

staticState NS = s_init;//定义下一状态

NS = Steps[NS](invar);

}

static的变量NS在每次BestStateMachine调用会得到维护,我们只需再每Steps返回下一个状态并保存到NS中可以实现状态的保存和切换。再说说为什么要加个void*的参数,状态机一般有很多自身变量的维护,而且对于mealy状态机还需根据输入判断,因为函数调用返回是不保留局部变量的,那么就需要将变量传递来实现更改和保存,之所以只用了一个void*参数是因为,如果需要保存和传递的变量很多,直接传递会在调用函数是浪费大量的栈空间,且效率低下,采用这种模式,你可以将变量用一个结构体封装,然后将结构体指针传递给void *的形参,再函数内部再强制转换即可使用结构体内部的变量。现在你已经在嘀咕这作者真啰嗦,好上实例代码,就是一个简单的计数器(以前学状态机都从计数器开始),在计数完成打印信息:

#include

typedef unsigned char State;

typedef State(*Procedure)(void *);

enum states{ s_init, s_count, s_done, s_default };//状态定义

typedef struct _SM_VAR //对状态机参数封装

{

int cnt;

}SM_VAR;

State step_init(void * arg)//初始化

{

SM_VAR *p = (SM_VAR *)arg;

p->cnt = 0;

printf("CS:init ;cnt=%d;NS:count\n", p->cnt);

return s_count;

}

State step_count(void * arg)//计数

{

SM_VAR *p = (SM_VAR *)arg;

if (p->cnt < 3){

p->cnt+=1;

printf("CS:count;cnt=%d;NS:count\n", p->cnt);

return s_count;

}

else{

printf("CS:count;cnt=%d;NS:done\n", p->cnt);

return s_done;

}

}

State step_done(void * arg)//计数完成

{

SM_VAR *p = (SM_VAR *)arg;

printf("CS:done ;cnt=%d;NS:init\n", p->cnt);

return s_init;

}

State step_default(void * arg)//错误过程

{

SM_VAR *p = (SM_VAR *)arg;

printf("Wrong State\n");

return s_init;

}

Procedure Steps[] = { step_init, step_count, step_done, step_default };

void BestStateMachine(void * invar)

{

static State NS = s_init; //定义下一状态

NS = Steps[NS](invar);

}

int main(void)

{

SM_VAR var;

int i;

for (i = 0; i <8; i++){//给状态机8个周期的时钟驱动

BestStateMachine(&var);

}

return 0;

}

最后在VS2013上调试如下:

CS:init ;cnt=0;NS:count

CS:count;cnt=1;NS:count

CS:count;cnt=2;NS:count

CS:count;cnt=3;NS:count

CS:count;cnt=3;NS:done

CS:done ;cnt=3;NS:init

CS:init ;cnt=0;NS:count

CS:count;cnt=1;NS:count

请按任意键继续. . .

总结

以这种模式不仅可以实现上面的Moore型状态机,还可根据实际实现Mealy型状态机,结构清晰易懂,在这里我敢说最优,是因为这是C函数式编程的极限了,如果你有更好的想法联系我,邮箱:869119842@qq.com,唐童鞋。如果你对嵌入式GUI感兴趣,我们可以一起探讨写出我们自己的GUI。

c语言自动机的建立,C语言最优状态机规范相关推荐

  1. c语言创建文件的作用,c语言文件创建与建立

    c语言文件创建与建立 C语言是一门通用计算机编程语言,应用广泛.下面是小编分享的c语言文件创建与建立,一起来看一下吧. 今天给大家分享的是有关文件的创建与读取的语法,事实上,c语言中对于这方面的已经有 ...

  2. 赫夫曼树建立c语言源程序编译结果详细解释,哈夫曼树的建立与实现最终版(备份存档)...

    <哈夫曼树的建立与实现.doc>由会员分享,可免费在线阅读全文,更多与<哈夫曼树的建立与实现(最终版)>相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索 ...

  3. 【计算理论】确定性有穷自动机 ( 自动机组成 | 自动机语言 | 自动机等价 )

    文章目录 一.确定性有穷自动机组成 二.确定性有穷自动机计算过程 三.确定性有穷自动机定义 四.自动机 语言 与 等价 五.自动机语言 示例 一.确定性有穷自动机组成 DFA , 全称为 Determ ...

  4. c语言 宇宙自动机,沃尔夫勒姆自动机时空图输出 C语言实现

    沃尔夫勒姆自动机时空图输出 C语言实现 #include #include #include #include //行宽度 #define ROW_LEN 38 //比特位域结构 typedef st ...

  5. c语言文件构建步骤,C语言文件的创建与建立

    C语言文件的创建与建立 c语言中对于文件的创建与建立已经有相当经典且应用相当广泛的语法了.下面是小编为大家带来的C语言文件的创建与建立的知识,欢迎阅读. 首先是文件的创建: # include # i ...

  6. 优酷暗黑模式(二):如何建立设计语言标准化管理体系

    伴随着行业的成熟与竞争加剧,中国互联网产品中心化.平台化的趋势越加明显.越来越多的公司对产品的设计体系与效率提出了更高的要求.为了更高效地服务多样的业务场景,快速应对未来市场竞争的变化,需要我们跳出设 ...

  7. c语言标准输入st,ST语言中定时器转换为C语言的研究

    ⑴ 初始状态Init.表示定时器不工作,初始化定时器各参数. ⑵ 工作状态Work.表示定时器处于运行时,时钟开始计时,且在该状态下始终满足ET处于范围(0,PT). ⑶ 输出状态Tout.表示ET= ...

  8. drupal建设多语言站点之四:不同语言的站点名称

    阅读此篇文章之前请阅读以下三篇文章: durpal建立多语言站点之三:内容多语言 进入Drupal中sites/default 的目录下,编辑Settings.php文件,自文件后面添加如下两句话: ...

  9. c语言程序设计实验教学,C语言程序设计实验教学改革研究

    语言程序设计是目前各高校计算机及其相关专业的一门基础课程,也是其它工科专业学生必修的计算机基础课程之一,是学生学习程序设计的入门课程.同时,该课程是一门应用性很强的学科.随着计算机技术飞速发展,计算机 ...

最新文章

  1. 《数学之美》第6章 信息的度量和作用
  2. AMD and CMD are dead之KMD.js依赖可视化工具发布
  3. 链接生成动态二维码图片显示在页面上
  4. 懒癌晚期学图论的时候自己用C语言写了个求可达性矩阵的算法~
  5. I/O----复制文本文件
  6. linxu改网络地址。
  7. 如何将 Apple Watch 用作闹钟?
  8. php教程 TTP中GET与POST的区别
  9. db9小波包分解matlab,小波包分解 仿真 matlab
  10. PowerBuilder 部署iis报错:IIS is not acessblee Please check the server address and port number.
  11. 头痛的apk卡顿,我该从哪些方面进行优化?带你了解常见方案
  12. Linux技巧:使用Fsck命令修复损坏的分区
  13. R安装与卸载、RStudio安装
  14. android监控电话录音,Android例子源码实现电话录音监听的安卓例子
  15. 人际关系不仅要“存”,更要“激活”!
  16. 东莞群控服务器系统,群控服务器远程连接工具
  17. 我连Punk男都算不上 (一)
  18. 2022年1月5日【Jiawei_Z】昆仑通态 配方组态 设计---查询/保存/编辑/导入/导出
  19. keil5 stm32f03c8t6 printf重定向到串口和TFT 1.44 LCD屏
  20. 对专业知识和学历的一些感悟

热门文章

  1. 局部敏感哈希(Locality sensitive hash) [3]—— 代码篇
  2. html float作用,CSS float相关详解
  3. 科研杂谈 | 全球最大的数字图书馆
  4. ggplot2 图形排版:patchwork 包简单入门
  5. 专业的秘密 | 南方医科大学生物信息学专业
  6. 在线作图|2分钟绘制一张环状热图
  7. 北京、广州同时开课 | 临床基因组学数据分析实战助力解析Case,快速发表文章...
  8. 蚂蚁森林最高效的合种团队—招募有合作精神的队友云植树
  9. Nature Method:Bioconda解决生物软件安装的烦恼
  10. 比PCA更好用的监督排序—LDA分析、作图及添加置信-ggord