【学习笔记】状态机编程

使用状态机来实现状态切换,备忘。

#include <stdio.h>
#include <conio.h>
#pragma warning(disable:4996)
/*
四要素
state      状态
event      事件
action     动作
transition 变换
*/


typedef enum
{
	sta_go = 0,
	sta_down,
	sta_right,
	sta_light,
	sta_stop
}state;
state now_state = sta_stop;//初始化目前状态为前进
state last_state = sta_stop;//初始化上一次状态为停止
typedef enum
{
	evt_rl =0,
	evt_yl,
	evt_gl,
	evt_people_pass,
	evt_turn_right,
	evt_turn_light
}eventid;

typedef  void (*CallBack)(void);

typedef struct {
	state curState;//当前状态
	eventid eventId;//事件ID
	state nextState;//下个状态
	CallBack action;//回调函数,事件发生后,调用对应的回调函数
}StateTransform;

void callback_go(void)
{
	printf("向前走\n");
}
void callback_stop(void)
{
	printf("停止\n");
}
void callback_right(void)
{
	printf("右转\n");
}
void callback_light(void)
{
	printf("左转\n");
}
void callback_down(void)
{
	printf("倒退特殊回调触发\n");
}
StateTransform stateTran_go[]{//顺序不能变
	{sta_go,evt_rl,                    sta_stop,callback_stop},
	{sta_go,evt_yl,                    sta_stop,callback_stop},
	{sta_go,evt_gl,                    sta_stop,callback_stop},
	{sta_go,evt_people_pass,           sta_stop,callback_stop},
	{sta_go,evt_turn_right,            sta_right,callback_right},
	{sta_go,evt_turn_light,            sta_light,callback_light},
};
StateTransform stateTran_down[]{
	{sta_down,evt_rl,                    sta_stop,callback_down},
	{sta_down,evt_yl,                    sta_light,callback_down},
	{sta_down,evt_gl,                    sta_light,callback_down},
	{sta_down,evt_people_pass,           sta_stop,callback_stop},
	{sta_down,evt_turn_right,            sta_right,callback_down},
	{sta_down,evt_turn_light,            sta_light,callback_down},
};
StateTransform stateTran_stop[]{
	{sta_stop,evt_rl,                    sta_stop,callback_stop},
	{sta_stop,evt_yl,                    sta_stop,callback_stop},
	{sta_stop,evt_gl,                    sta_go,callback_go},
	{sta_stop,evt_people_pass,           sta_stop,callback_stop},
	{sta_stop,evt_turn_right,            sta_right,callback_right},
	{sta_stop,evt_turn_light,            sta_light,callback_light},
};
StateTransform stateTran_right[]{
	{sta_right,evt_rl,                    sta_stop,callback_stop},
	{sta_right,evt_yl,                    sta_right,callback_right},
	{sta_right,evt_gl,                    sta_right,callback_right},
	{sta_right,evt_people_pass,           sta_stop,callback_stop},
	{sta_right,evt_turn_right,            sta_right,callback_right},
	{sta_right,evt_turn_light,            sta_light,callback_light},
};
StateTransform stateTran_light[]{
	{sta_light,evt_rl,                    sta_stop,callback_go},
	{sta_light,evt_yl,                    sta_light,callback_light},
	{sta_light,evt_gl,                    sta_light,callback_light},
	{sta_light,evt_people_pass,           sta_stop,callback_stop},
	{sta_light,evt_turn_right,            sta_right,callback_right},
	{sta_light,evt_turn_light,            sta_light,callback_light},
};

void do_action(StateTransform* statTran)
{
	printf("last_state = % d\n now_state = % d\n", last_state, now_state);
	if (NULL == statTran)
	{
		perror("statTran is NULL\n");
		return;
	}
	last_state= statTran->curState;//更新状态
	now_state = statTran->nextState;
	if (now_state != last_state)
	{
		if (statTran->action != NULL)
		{
			statTran->action();
		}
	}
	else
	{
		printf("事件没有改变\n");
	}
}

void event_action(unsigned int event)
{
	switch (now_state)
	{
	case sta_go:
		do_action(&stateTran_go[event]);
		
		break;
	case sta_down:
		do_action(&stateTran_down[event]);
		break;
	case sta_right:
		do_action(&stateTran_right[event]);

		break;
	case sta_light:
		do_action(&stateTran_light[event]);

		break;
	case sta_stop:
		do_action(&stateTran_stop[event]);
		break;
	default:
		printf("事件不合法\n");
		break;
	}
}
void main()
{
	int key;
	printf("开始运行.....\n");
	while (1)
	{
		key = getchar();
		if (key=='r')
		{
			event_action(evt_rl);
		}
		if (key == 'y')
		{
			event_action(evt_yl);
		}
		if (key == 'g')
		{
			event_action(evt_gl);
		}
		if (key == 'p')
		{
			event_action(evt_people_pass);
		}
		if (key == 'R')
		{
			event_action(evt_turn_right);
		}
		if (key == 'L')
		{
			event_action(evt_turn_light);
		}
	}
}

运行结果
在这里插入图片描述在除正在转弯的情况下,其余所有情况遇到黄灯都停止。同时所有状态遇到行人都停止。
举例不是很恰当,重要的是思想。

2023-7-31 新增

最近发送上边的状态机使用起来过于复杂,所以参考了一下另一位大佬的代码
所有代码如下

#include <stdio.h>
#include <conio.h> //获取键盘建值状态
enum SEvent {//所有事件的集合
	event1 = 0x31,
	event2,
	event3,
	event4,
	event5,
	event6,
	event7,
	event8
};
enum CState {//所有状态的集合
	state1 = 1,
	state2,
	state3,
	state4,
	state5
};
typedef struct {
	int Event;//触发的事件
	int Curstate;//当前状态
	void (*CallBack)();//触发之后的回调函数
	int Nextstate;//下一个状态
}State_table;//状态表
typedef struct {
	int Curstate;//当前状态
	State_table* Stable;//状态表
	int Stable_size;//状态表的项数
}FSM;//实际操作的状态机对象

/*状态机注册,给它一个状态表
pFsm 新建的状态机
pTable 传入的状态机对应表
state 初始默认状态
*/
void FSM_Regist(FSM* pFsm, State_table *pTable, CState state,int TableSize)
{
	pFsm->Stable = pTable;//传入所给的状态表
	pFsm->Stable_size= TableSize;//所给状态表的大小
	pFsm->Curstate = state;//当前的默认状态
}
void FSM_EventHandle(FSM *pFsm, SEvent event) {//注意这里要传入的pFsm必须是一个指针,不然改不了状态

	void (*ActionCallBack)();
	ActionCallBack = 0;//默认置空
	for (int i = 0; i < pFsm->Stable_size; i++) {
		if (pFsm->Curstate == pFsm->Stable[i].Curstate && event == pFsm->Stable[i].Event) {
			ActionCallBack = pFsm->Stable[i].CallBack;//找出要执行的函数
			pFsm->Curstate = pFsm->Stable[i].Nextstate;//更改状态
		}
	}
	if (ActionCallBack != 0) {

		ActionCallBack();//动作执行
	}
	else
		return;
}

void thing1() {
	printf("这里是执行函数1  \r\n");
}
void thing2() {
	printf("这里是执行函数2  \r\n");
}
void thing3() {
	printf("这里是执行函数3  \r\n");
}
void thing4() {
	printf("这里是执行函数4  \r\n");
}
void thing5() {
	printf("这里是执行函数5  \r\n");
}
State_table STranTable[] = {
	 { event1,  state1, thing1,  state2 },
	 { event2,  state2, thing2,  state3 },
	 { event3,  state3, thing3,  state4 },
	 { event4,  state4, thing4,  state5 },
	 { event5,  state5, thing5,  state5 },
	 { event1,  state5, thing1,  state1 },
};
int main(void) {
	FSM Mfsm;
	FSM_Regist(&Mfsm, STranTable, state1,sizeof(STranTable)/sizeof(State_table));
	while (1) {
		while (_kbhit()) {
			SEvent key = (SEvent)_getch();
			FSM_EventHandle(&Mfsm, key);
		}
	}
}

使用方法:
1 定义所有事件的集合

enum SEvent {//所有事件的集合
	event1 = 0x31,
	event2,
	event3,
	event4,
	event5,
	event6,
	event7,
	event8
};

2 定义所有状态的集合

enum CState {//所有状态的集合
	state1 = 1,
	state2,
	state3,
	state4,
	state5
};

3 初始化所有的回调函数和状态迁移表


void thing1() {
	printf("这里是执行函数1  \r\n");
}
void thing2() {
	printf("这里是执行函数2  \r\n");
}
void thing3() {
	printf("这里是执行函数3  \r\n");
}
void thing4() {
	printf("这里是执行函数4  \r\n");
}
void thing5() {
	printf("这里是执行函数5  \r\n");
}
State_table STranTable[] = {//分别对应 触发的事件 当前状态  要触发的回调函数 下一个状态
	 { event1,  state1, thing1,  state2 },
	 { event2,  state2, thing2,  state3 },
	 { event3,  state3, thing3,  state4 },
	 { event4,  state4, thing4,  state5 },
	 { event5,  state5, thing5,  state5 },
	 { event1,  state5, thing1,  state1 },
};

4 开始使用

FSM Mfsm;//初始化一个状态机对象
FSM_Regist(&Mfsm, STranTable, state1,sizeof(STranTable)/sizeof(State_table));//注册状态机对象的状态迁移表


FSM_EventHandle(&Mfsm, key);//调用此函数和实现一次状态切换
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嗨!很高兴回答你关于Java并发编程的问题。请问你想知道什么方面的内容呢?我可以分享一些学习笔记和建议给你。 1. 并发编程基础:了解并发编程的基本概念,如线程、进程、锁、同步等。学习Java中的并发编程模型以及相关的API,如Thread、Runnable、Lock、Condition等。 2. 线程安全性:学习如何保证多线程环境下的数据安全性,了解共享资源的问题以及如何使用同步机制来防止数据竞争和并发问题。 3. 线程间的通信:掌握线程间的通信方式,如使用wait/notify机制、Lock/Condition等来实现线程的协调与通信。 4. 并发容器:学习并发容器的使用,如ConcurrentHashMap、ConcurrentLinkedQueue等。了解它们的实现原理以及在多线程环境下的性能特点。 5. 并发工具类:熟悉Java提供的并发工具类,如CountDownLatch、CyclicBarrier、Semaphore等,它们可以帮助你更方便地实现线程间的协作。 6. 并发编程模式:学习一些常见的并发编程模式,如生产者-消费者模式、读者-写者模式、线程池模式等。了解这些模式的应用场景和实现方式。 7. 性能优化与调试:学习如何分析和调试多线程程序的性能问题,了解一些性能优化的技巧和工具,如使用线程池、减少锁竞争、避免死锁等。 这些只是一些基本的学习笔记和建议,Java并发编程是一个庞大而复杂的领域,需要不断的实践和深入学习才能掌握。希望对你有所帮助!如果你有更具体的问题,欢迎继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值