C语言另一种编码方式开发状态机(无switch)

news2024/12/25 9:20:40

目录

概述

一、开发环境

二、coding

三、运行结果

四、总结


概述

       状态机编码思想,在很多领域都随处可见,传统的coding方式使用switch + case来实现,状态跳转可读性差,咋们换一种思路来实现状态机开发,该方式 拓展好、编写复杂的场景等优点。

一、开发环境

visual studio 22

二、coding

#include <iostream>

typedef struct FsmHandle
{
    int state_id; //< 状态ID定义

    
}Fsm;

enum {
    FS_StatusA = 0, //< 状态A 
    FS_StatusB,     //< 状态B 
    FS_StatusC,     //< 状态C 
    FS_StatusD,     //< 状态D 
    FS_StatusMax,
}FsmStatus;

typedef void (*FsmHandler)(Fsm* fsm);

static void handler_status_a(Fsm* fsm)
{
    printf("process status A... \n");
    // 执行相关的逻辑

    // do something...

    // 切换状态
    fsm->state_id = FS_StatusB;
}

static void handler_status_b(Fsm* fsm)
{
    printf("process status B... \n");
    // 执行相关的逻辑

    // do something...

    // 切换状态
    fsm->state_id = FS_StatusC;
}

static void handler_status_c(Fsm* fsm)
{
    printf("process status C... \n");
    // 执行相关的逻辑

    // do something...

    // 切换状态
    fsm->state_id = FS_StatusB;
}

static void handler_status_d(Fsm* fsm)
{
    printf("process status D... \n");
    // 执行相关的逻辑

    // do something...

    // 切换状态
    fsm->state_id = FS_StatusA;
}

/**
 * breif 定义状态处理表
 */
static const FsmHandler c_status_handler[FS_StatusMax] = {
    handler_status_a,
    handler_status_b,
    handler_status_c,
    handler_status_d,
};

int FsmInit(Fsm* fsm)
{
    // 安全检查 

    // 初始化逻辑

    fsm->state_id = FS_StatusA;
    return 0;
}

int FsmDeInit(Fsm* fsm)
{
    // 安全检查 
    return 0;
}

void FsmRunOnce(Fsm* fsm)
{
    // 安全检查 
    c_status_handler[fsm->state_id](fsm);
}

bool g_is_working = true;

static Fsm m_fsm = { 0 };

int main()
{

    int result = -1;

    result = FsmInit(&m_fsm);
    // 执行结果检查
    if (result) {
        return 0;
    }

    while (g_is_working) {
        FsmRunOnce(&m_fsm);
    }

    FsmDeInit(&m_fsm);
    return 0;
}

三、运行结果

四、总结

        好了,就介绍到此为止,希望能帮助到需要的人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2231423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

录屏天花板,录课新玩法,人像+一切,PPT/PDF/视频/网页,也可即可录

上新啦 &#x1f4f1;&#x1f4bb; 录屏也能录课的万能神器——超级推荐&#xff01; 你是不是也在找一款能高效录屏、录课、轻松剪辑的小工具&#xff1f;作为一名需要频繁录制屏幕和课程内容的老师&#xff08;或内容创作者&#xff09;&#xff0c;我找到了这个宝藏App&…

vscode php Launch built-in server and debug, PHP内置服务xdebug调试,自定义启动参数配置使用示例

在vscode中&#xff0c;当我们安装了插件 PHP Debug&#xff08;xdebug.php-debug&#xff09;或者 xdebug.php-pack 后 我们通过内置默认的 php xdebug配置启动php项目后&#xff0c;默认情况下我们在vscode中设置断点是不会生效的&#xff0c;因为我们的内置php服务默认启动时…

Linux入门(2)

林纳斯托瓦兹 Linux之父 1. echo echo是向指定文件打印内容 ehco要打印的内容&#xff0c;不加任何操作就默认打印到显示器文件上。 知识点 在Linux下&#xff0c;一切皆文件。 打印到显示器&#xff0c;显示器也是文件。 2.重定向 >重定向操作&#xff0c;>指向的…

Java实战项目-基于 SpringBoot+Vue 的医院管理系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

代码随想录 | Day36 | 动态规划 :整数拆分不同的二叉搜索树

代码随想录 | Day36 | 动态规划 &#xff1a;整数拆分&不同的二叉搜索树 动态规划应该如何学习&#xff1f;-CSDN博客 动态规划学习&#xff1a; 1.思考回溯法&#xff08;深度优先遍历&#xff09;怎么写 注意要画树形结构图 2.转成记忆化搜索 看哪些地方是重复计算…

【书生.浦语实战营】——入门岛

【书生.浦语实战营】——入门岛_第一关_Linux基础 任务分布1. 本地vscode远程连接并进行端口映射端口映射What——何为端口映射How——怎么进行端口映射 2. Linux基础命令touch &#xff1a;创建文件mkdir &#xff1a;创建目录cd:进入 退出 目录pwd :确定当前所在目录cat:可以…

【Pytorch】Pytorch的安装

目录 一、介绍 1.相关要素 二、NVIDIA显卡安装pytorch 1、官网安装 2、清华源下载 一、介绍 1.相关要素 &#xff08;1&#xff09;nvidia-driver&#xff08;也叫做 cuda driver&#xff09;&#xff1a;英伟达GPU驱动&#xff0c;命令&#xff1a;nvidia-smi &#xf…

HTML+CSS科技感时钟(附源码!!!)

预览效果 源码(直接复制使用) <!DOCTYPE html> <html lang"zh-Hans"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>科技感时钟</…

vue3中跨层传递provide、inject

前置说明 在 Vue 3 中&#xff0c;provide 和 inject 是一对用于跨组件树传递数据的 API。它们允许你在祖先组件中使用 provide 提供数据或服务&#xff0c;然后在后代组件中使用 inject 来获取这些数据或服务。这种方式特别适用于跨多个层级的组件传递数据&#xff0c;而不需要…

Zig 语言通用代码生成器:逻辑,发布冒烟测试版二之二

Zig 语言通用代码生成器&#xff1a;逻辑&#xff0c;发布冒烟测试版二之二 Zig 语言通用代码生成器&#xff1a;逻辑&#xff0c;已发布冒烟测试版二。此版本完善了代码生成物。支持多对多关系。修复了所有单域动词。并有更多缺陷修复。暂时不支持图片类型。暂时不支持日期和…

获取Hive表备注

DESCRIBE EXTENDED 表名;先获取Detailed Table Information这行的data_type字段数据&#xff0c;进行正则匹配&#xff0c;拿到表备注&#xff0c;如下&#xff1a; String str ReUtil.get("parameters:\\{(?!.*?\\().*transient_lastDdlTime.*?comment(.*?)\\}&quo…

前端请求后端接口报错(blocked:mixed-content),以及解决办法

报错原因&#xff1a;被浏览器拦截了&#xff0c;因为接口地址不是https的。 什么是混合内容&#xff08;Mixed Content&#xff09; 混合内容是指在同一页面中同时包含安全&#xff08;HTTPS&#xff09;和非安全&#xff08;HTTP&#xff09;资源的情况。当浏览器试图加载非…

TCP是怎样工作的网络拥塞控制理论和算法部分记录

参考资料 https://github.com/ituring/tcp-book 流量控制、窗口控制和拥塞控制的关系 流量控制、窗口控制和拥塞控制的关系如图所示 窗口控制是上层的概念&#xff0c;核心思路是基于滑动窗口技术传输数据。而确定发送窗口大小的方法有流量控制和拥塞控制两种 流量控制&…

python eval() 怎么用

eval函数的使用方法 函数的作用&#xff1a; 计算指定表达式的值。也就是说它要执行的Python代码只能是单个运算表达式&#xff08;注意eval不支持任意形式的赋值操作&#xff09;&#xff0c;而不能是复杂的代码逻辑&#xff0c;这一点和lambda表达式比较相似。 函数定义&a…

WPF+MVVM案例实战(十二)- 3D数字翻牌计时实现

文章目录 1、运行效果2、功能实现1、文件创建2、控件代码实现3、控件引用与菜单实现1.引用用户控件2.按钮菜单3、计时器界面实现4、源代码获取1、运行效果 3D数字翻牌计时 2、功能实现 1、文件创建 打开项目 Wpf_Examples ,在用户控件 UserControlLib 中创建 NumberFoldi…

Redis 下载安装(Windows11)

目录 Redis工具下载安装 Redis 工具 系统&#xff1a;Windows 11 下载 Windows版本安装包&#xff1a;通过百度网盘分享的文件&#xff1a;Redis-x64-3.0.504.msi 链接&#xff1a;https://pan.baidu.com/s/1qxq0AZJe5bXeCPzm1-RBCg?pwdc14j 提取码&#xff1a;c14j 安装…

ArcGIS软件之“新建中学最适合地址”地图制作

目录 最终效果图(全文图中的颜色类似即可&#xff0c;形状一样为标准&#xff09;第一步、设置现有中学的欧式距离第二步、将计算好的欧式距离 进行重分类第三步、进行核密度分析第四步、进行人口密度的重分类第五步、进行土地使用的要素转栅格第六步、对上一步进行重分类第七步…

K 临近算法

机器学习中的 K 临近算法&#xff0c;计算输入数据与训练集中数据的距离&#xff0c;选取 k 个最近的数据&#xff0c;选中的数据中&#xff0c;那个分类多&#xff0c;那个分类就是最终结果。特征空间的距离有多重测量方法&#xff0c;最常用的就是欧氏距离&#xff0c;公式如…

聪明的你能从千门八将108局学到什么,对你的未来人生有哪些深远的影响?

千门八将108局&#xff1a;智慧的启迪与人生指引 在古老智慧的宝库中&#xff0c;千门八将108局犹如璀璨星辰&#xff0c;闪耀着神秘而深邃的光芒。那些认真钻研过这些局的人&#xff0c;仿佛经历了一场穿越时空的智慧洗礼&#xff0c;从中收获了无价的人生财富。 一、从千门八…

【前端】CSS知识梳理

基础&#xff1a;标签选择器、类选择器、id选择器和通配符选择器 font:font-style(normal) font-weight(400) font-size(16px) /line-height(0) font-family(宋体&#xff09; 复合&#xff1a; 后代选择器&#xff08; &#xff09;、子选择器&#xff08;>)、并集选择器(…