bta*_*bta 36
没有什么本质上的错误goto.它们通常被认为是"禁忌"的原因是因为一些程序员(通常来自汇编世界)使用它们来创建几乎无法理解的"意大利面条"代码.如果您可以goto在保持代码清洁,可读和无错误的同时使用语句,那么您将获得更多权力.
goto为每个状态使用语句和一段代码绝对是编写状态机的一种方法.另一种方法是创建一个变量,该变量将保持当前状态并使用switch语句(或类似)来根据状态变量的值选择要执行的代码块.请参阅Aidan Cully使用第二种方法获得良好模板的答案.
实际上,这两种方法非常相似.如果使用状态变量方法编写状态机并对其进行编译,则生成的程序集可能非常类似于使用该goto方法编写的代码(取决于编译器的优化级别).该goto方法可以看作是从状态变量方法优化额外变量和循环.你使用哪种方法是个人选择的问题,只要你正在编写工作的,可读的代码,我希望你的老板不会认为你使用一种方法而不是另一种方法.
如果要将此代码添加到已包含状态机的现有代码库中,我建议您遵循已使用的任何约定.
Jer*_*fin 19
使用a goto来实现状态机通常很有意义.如果您真的担心使用goto,合理的替代方法通常state是使用您修改的变量,以及switch基于此的声明:
typedef enum {s0,s1,s2,s3,s4,...,sn,sexit} state;
state nextstate;
int done = 0;
nextstate = s0; /* set up to start with the first state */
while(!done)
switch(nextstate)
{
case s0:
nextstate = do_state_0();
break;
case s1:
nextstate = do_state_1();
break;
case s2:
nextstate = do_state_2();
break;
case s3:
.
.
.
.
case sn:
nextstate = do_state_n();
break;
case sexit:
done = TRUE;
break;
default:
/* some sort of unknown state */
break;
}
Run Code Online (Sandbox Code Playgroud)
Vin*_*vic 15
如果我想给老板留下好印象,我会像Ragel一样使用FSM发生器.
这种方法的主要好处是,您可以在更高的抽象级别描述您的状态机,而不需要关心是否使用goto或switch.更不用说在Ragel的特定情况下,您可以自动获得FSM的漂亮图表,在任何点插入操作,自动最小化状态量和各种其他好处.我是否提到生成的FSM也非常快?
缺点是它们更难调试(自动可视化在这里有很多帮助)并且你需要学习一个新工具(如果你有一台简单的机器并且你不太可能经常编写机器,这可能是不值得的. )
R S*_*hko 10
我会使用一个跟踪你所处状态的变量和一个处理它们的开关:
fsm_ctx_t ctx = ...;
state_t state = INITIAL_STATE;
while (state != DONE)
{
switch (state)
{
case INITIAL_STATE:
case SOME_STATE:
state = handle_some_state(ctx)
break;
case OTHER_STATE:
state = handle_other_state(ctx);
break;
}
}
Run Code Online (Sandbox Code Playgroud)
Goto不是必要的邪恶,我不得不强烈反对Denis,是的,在大多数情况下goto可能是一个坏主意,但有一些用途.goto最大的恐惧是所谓的"spagetti-code",无法追踪的代码路径.如果你可以避免这种情况,如果它总是很清楚代码的行为方式,并且你没有用goto跳出函数,那就没有什么可以反对goto了.请谨慎使用它,如果您想要使用它,请真正评估情况并找到更好的解决方案.如果您不能这样做,可以使用goto.
避免goto,除非增加的复杂性(避免)较为混乱.
在实际的工程问题中,可以非常谨慎地使用goto.学者和非工程师不必要地用手指敲打他们goto.也就是说,如果你把自己描绘成一个实现角落,其中很多goto是唯一的出路,重新考虑解决方案.
正确工作的解决方案通常是主要目标.使其正确和可维护(通过最小化复杂性)具有许多生命周期益处.首先使其工作,然后逐渐清理,最好通过简化和去除丑陋.
| 归档时间: |
|
| 查看次数: |
4032 次 |
| 最近记录: |