C 中的状态机
本文介绍了状态机在 C 编程语言中的实现。
状态机概述
使用状态机来实现代码是解决复杂工程问题的一种有价值的设计策略。 状态机采用整体设计并将其分成几个阶段,在状态机术语中称为状态。
每个州都负责履行特定职能。 另一方面,事件是导致状态机在状态之间变化的刺激。 它也被称为过渡。
刚开始编写时,大多数系统都是直截了当且组织良好的,但是当添加新功能时,会创建额外的标志和变量来跟踪事件的历史记录。
然后,添加 if 和 else 语句来测试由许多变量和标志创建的越来越复杂的逻辑表达式。
在这方面,状态机可以提供帮助。 如果使用得当,状态机可以简化在每个分支点测试的条件,并且可以更轻松地在各种程序执行模式之间切换。
事实证明,大多数实时系统的行为都可以划分为相对较少的非重叠块(状态)。
每个块内的事件响应仅取决于当前事件,它们不再依赖于过去发生的事件的顺序。
使用函数指针创建状态机
以下是用C语言构建状态机的代码示例。这个具体示例生成两个状态,在它们之间来回切换十次。
然后,它显示索引号和与该索引对应的状态。
#include <stdio.h>
struct state;
typedef void state_fn(struct state *);
struct state
{
state_fn * next;
int i;
};
state_fn off_state, on_state;
void off_state(struct state * state)
{
printf("%s %i\n", __func__, ++state->i);
state->next = on_state;
}
void on_state(struct state * state)
{
printf("%s %i\n", __func__, ++state->i);
state->next = state->i < 10 ? off_state : 0;
}
int main(void)
{
struct state state = { off_state, 0 };
while(state.next) state.next(&state);
}
输出:
off_state 1
on_state 2
off_state 3
on_state 4
off_state 5
on_state 6
off_state 7
on_state 8
off_state 9
on_state 10
使用 Switch 语句创建状态机
为了让事情有一个坚实的开始,您应该列出我们的程序可能处于的状态集以及它可以处理的事件集。
该程序可能处于以下三种状态之一:START、ITERATE 或 END。
enum states {
START,
ITERATE,
END,
} state;
它可以处理事件 START LOOPING 、SHOW_MESSAGE 和 STOP LOOPING 。 在 START 状态下收到 START LOOPING 事件后,我们的程序将进入 ITERATE 状态。
在 ITERATE 状态下,它将在收到 SHOW_MESSAGE 事件时显示消息。 最后,它会在收到 STOP LOOPING 事件后转换到 END 状态。
enum events {
START_LOOPING,
SHOW_MESSAGE,
STOP_LOOPING,
};
让我们使用一个查看当前状态并执行适当情况的 switch 语句。 我们有三种主要情况,称为开始、迭代和结束。
在 START 情况下,如果收到的事件是 START LOOPING,它会将状态更改为 ITERATE。 如果事件不是 START LOOPING,则该案例将被打破。
同样,在 ITERATE 情况下,如果收到的事件是 SHOW MESSAGE,它将显示消息; 否则,它将检查 STOP LOOPING 情况并将状态更改为 END。
如果没有收到这些事件,它将中断并继续下一个案例。 最后,END case 导致 switch 语句终止,程序退出。
void switchState(enum events event) {
switch(state) {
case START:
switch(event) {
case START_LOOPING:
state = ITERATE;
break;
default:
exit(1);
break;
}
break;
case ITERATE:
switch(event) {
case SHOW_MESSAGE:
printf("State Machine Ready!\n");
break;
case STOP_LOOPING:
state = END;
break;
default:
exit(1);
break;
}
break;
case END:
exit(1);
break;
}
}
最后,让我们调用称为 switchState()
的方法,并以参数的形式一次为它提供一个事件。
int main(void) {
switchState(START_LOOPING);
switchState(SHOW_MESSAGE);
switchState(STOP_LOOPING);
return 0;
}
以下是使用 switch 语句的完整源代码。
#include <stdio.h>
#include <stdlib.h>
enum states {
START,
ITERATE,
END,
} state;
enum events {
START_LOOPING,
SHOW_MESSAGE,
STOP_LOOPING,
};
void switchState(enum events event) {
switch(state) {
case START:
switch(event) {
case START_LOOPING:
state = ITERATE;
break;
default:
exit(1);
break;
}
break;
case ITERATE:
switch(event) {
case SHOW_MESSAGE:
printf("State Machine Ready!\n");
break;
case STOP_LOOPING:
state = END;
break;
default:
exit(1);
break;
}
break;
case END:
exit(1);
break;
}
}
int main(void) {
switchState(START_LOOPING);
switchState(SHOW_MESSAGE);
switchState(STOP_LOOPING);
return 0;
}
输出:
State Machine Ready!
相关文章
在 C 语言中使用 typedef enum
发布时间:2023/05/07 浏览次数:181 分类:C语言
-
本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。
C 语言中的 extern 关键字
发布时间:2023/05/07 浏览次数:114 分类:C语言
-
本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量
C 语言中的 #ifndef
发布时间:2023/05/07 浏览次数:186 分类:C语言
-
本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。