从有限状态机问题看C语言的解法比较

Part 1.什么是“有限状态机”

从百科词条来看,有限状态机(FSM/FSA)是为研究有限内存的计算过程和某些语言类而抽象出来的一种计算机模型,它可以表示为一个有向图。有限状态机多为Moore机与Mealy机两类,Moore机对每一个状态都附加有输出动作,而Mealy机对每一个转移都附加有输出动作。简单理解,可以认为Moore机的下一状态只由当前状态决定,而Mealy机的下一状态不仅与当前状态有关,还与当前输入值有关。恰好今天磕的两道题,一道属于Moore机的,一道属于Mealy机的。

Part 2.单键电风扇问题

单键电风扇只有一个键,比如对于风速只有高、中、低三档的单键电扇而言,调节风速时,中速就是在高速与低速之间,它的下一档与上一档关系是固定的,可见,它的下一状态只由当前状态决定,因此它属于Moore机。题目如图:大致要求是,假设单键电风扇开始处于停止状态,请模拟在各状态下按下按键所发生的事件。

一看这道题,当然可以使用数组解决。把各种状态写进字符型数组,然后使用循环依次读取数组,读到底时,再从首位读起;也可以使用int型数组,将每个状态所对应的数字排列好,然后依次用switch语句printf输出状态;甚至用if else万金油也行。不过,既然这幅图那么像链表,最终就简单粗暴用单向循环链表写了。程序如下:

#include<stdio.h>
struct FanState{
	char *state=NULL;
	struct FanState *next;
};
int main(){
	FanState A,B,C,D,*head,*p;
	char a[5]="STOP",b[4]="LOW",c[7]="MEDIUM",d[5]="HIGH";
	A.state=a;
	B.state=b;
	C.state=c;
	D.state=d;
	head=&A;
	A.next=&B;
	B.next=&C;
	C.next=&D;
	D.next=&A;
	p=head;
	char s;
	while((s=getchar())!=EOF){
		if(s=='\n')printf("%s->%s\n",p->state,p->next->state);
		else if(s=='q'||s=='Q')break;//按q或Q退出 
		p=p->next;
	}
	p=NULL;
	return 0;
} 

只需按回车健就能模拟按键的动作啦,很直观,按q或Q退出循环。

但是遇到第二题,状态与状态转移的关系就复杂多了,方法选择至关重要。

Part 3.多媒体播放器问题

这个播放器可不是按个键就能确定下一个状态的了,下一个状态不仅跟现有状态有关,还跟按键方式有关,这已经是个Mealy机了。

但乍一看,第一反应还是链表——没错,是双向链表。但是,这双向链表的好几个结点next与prior指向貌似还不止一个,比如“暂停”,那就插入吧,哦,这还不够,应该以那几个为原始结点呢?停止->播放->快速前进?停止->播放->快速后退?开始晕了,然后,万一遇到某状况,为了达到某些结点,是不是还要删掉一些结点呀,毕竟这个next与prior不能指向多处……

链表这种高级的手段本菜鸡被弄晕了,还是考虑传统点的方法吧。如果用数组表示状态与执行操作的话,那么有三种信息需要考虑:目前状态、按键操作和下一个状态。三维吗?不,二维足矣。如果以目前状态“暂停”为数组第二行,”按一下“为第2列,“按紧三秒”为第5列,假设数组名为Array,则Array[1][1]可表示“目前状态+按一下”,Array[1][4]可表示“目前状态+按紧三秒”,那么这个数组位置所对应的元素是不是就可以表示下一个状态了?当然可以,只要表示使用数字表示状态,然后再switch结构中输出对应的下一个状态即可。

#include<stdio.h>
int main(){
	int x=0,y,z=1;
	int Array[5][5]={{6,2,6,6,6},  
	                 {6,2,6,6,0},
			 {6,1,3,4,0},
			 {6,2,6,6,6},
			 {6,2,6,6,6}};
	printf("初始为停止状态:\n按一下,请输入数字1;按两下,请输入数字2;\n");
	printf("按三下,请输入数字3;按紧三秒,请输入数字4;\n退出请输入数字5.\n");
	printf("*******************************************************\n"); 
	printf("多媒体播放状态:\n停止\n");
	while(1){scanf("%d",&y);
	if(y==5)break;
	switch(Array[x][y]){
	case 0:printf("停止\n");break;
	case 1:printf("暂停\n");break;
        case 2:printf("播放\n");break;
	case 3:printf("快速前进\n");break;
	case 4:printf("快速后退\n");break;
	default:z=0;printf("输入错误,请重新输入\n");break;
	}
	if(z)x=Array[x][y];
	z=1;
	}
	return 0; 
}  

输出结果如下:

个人感觉实现程序不一定要使用高大上的方法,如果条件允许,思路简单清晰的方法才是好方法。

感谢耐心观看,如果对题目有更好的解决方法或者想法,欢迎分享~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
有限状态机(Finite State Machine,FSM)是一种描述有限个状态以及在这些状态之间转移和动作等行为的数学模型。在C语言中,可以使用结构体和函数指针实现一个简单的有限状态机,实现状态的转移和响应动作。 以下是一个简单的有限状态机的代码示例: ```c typedef enum { STATE_A, STATE_B, STATE_C, STATE_D } state_t; typedef void (*action_t)(void); typedef struct { state_t current_state; action_t action; state_t next_state; } transition_t; void action_a(void) { printf("Performing action A.\n"); } void action_b(void) { printf("Performing action B.\n"); } void action_c(void) { printf("Performing action C.\n"); } void action_d(void) { printf("Performing action D.\n"); } transition_t transitions[] = { {STATE_A, action_a, STATE_B}, {STATE_B, action_b, STATE_C}, {STATE_C, action_c, STATE_D}, {STATE_D, action_d, STATE_A} }; int main(void) { state_t current_state = STATE_A; while (1) { action_t action = NULL; state_t next_state = STATE_A; for (int i = 0; i < sizeof(transitions)/sizeof(transitions[0]); i++) { if (transitions[i].current_state == current_state) { action = transitions[i].action; next_state = transitions[i].next_state; break; } } if (action != NULL) { action(); } current_state = next_state; } return 0; } ``` 以上代码定义了一个包含四个状态和四个动作的有限状态机。在 `main` 函数中,通过循环不断地执行当前状态对应的动作,并根据状态转移表更新当前状态。在此过程中,可通过添加新的状态和动作,扩展有限状态机的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值