用函数指针来实现状态机

状态机的基本实现手段是switch case语句,不过也可以用函数指针来实现。举例说明,这里有个switch case 实现的状态机。

switch case 实现的状态机

int count = 0;

typedef enum {
	STATE1,
	STATE2,
	STATE3,
}state_t;

state_t state = STATE1;

void state_machine(void) {
	switch(state) {
		case STATE1:
			if(count > 3) { 
				state = STATE2; 
			}
			break;
		case STATE2:
			if(count > 10) { 
				state = STATE3; 
			}
			break;
		case STATE3:
			if(count > 100) { 
				state = STATE1; 
			}
			break;
		default:
			break;
	}
}

int main(void) {
	for(;count < 200; count++) {
		state_machine();
	}
	return 0;
}

函数指针实现的状态机

int count = 0;

typedef void (*state_t)(void);

void STATE1(void);
void STATE2(void);
void STATE3(void);

state_t state = STATE1;

void STATE1(void) {
	if(count > 3) { 
		state = STATE2; 
	}
}

void STATE2(void) {
	if(count > 10) { 
		state = STATE3; 
	}
}

void STATE3(void) {
	if(count > 100) { 
		state = STATE1; 
	}
}

int main(void) {
	for(;count < 200; count++) {
		state();
	}
	return 0;
}

改动内容包括:

  • 状态枚举的定义变更为状态处理函数指针的定义。
  • 每一个case语句分离成为状态处理函数。
  • 调用状态机的地方直接调用状态处理函数指针。

函数指针实现状态机的好处:

  • 进入状态处理的时间是固定的,无论有几个状态。使用switch case实现时,switch case默认情况下与 if else 语句生成的代码一致,要依次进行判断,进入后面状态处理的时间要比进入前面状态处理的时间要长。
  • 每个状态一个函数,函数的块头比较小,特别是状态处理的内容比较多的时候,分离成函数比较好阅读。

函数指针实现状态机的坏处:

  • 如果状态处理的内容很少,而状态很多,那么会分离成好多很小的函数。

更多内容

可以参考设计模式中的状态模式。

处理进入、退出状态

继续改造,加入处理事件的部分,这里仅给出进入、退出状态事件:

#include 

int count;

typedef enum {
	EV_DO,
	EV_ENTER,
	EV_EXIT,
}event_t;

typedef void (*state_t)(event_t e);

void trans(state_t next);
void STATE1(event_t e);
void STATE2(event_t e);
void STATE3(event_t e);


state_t state = NULL;

void STATE1(event_t e)
{
	switch(e) {
		case EV_DO:
			if(count > 3) { 
				trans(STATE2); 
			}
			break;
		case EV_ENTER:
			count = 0;
			break;
		default:
			break;
	}
}

void STATE2(event_t e)
{
	switch(e) {
		case EV_DO:
			if(count > 10) { 
				trans(STATE3);  
			}
			break;
		case EV_EXIT:
			count = 1;
			break;
		default:
			break;
	}
}

void STATE3(event_t e)
{
	if(e == EV_DO) {
		if(count > 5) { 
			trans(STATE1); 
		}
	}
}

void trans(state_t next)
{
	if(state) {
		state(EV_EXIT);
	}
	state = next;
	state(EV_ENTER);
}

int main(void) {
	trans(STATE1);
	for(;count < 200; count++) {
		state(EV_DO);
	}
	return 0;
}

你可能感兴趣的:(嵌入式软件,状态机)