我正在为我正在写的翻译添加协程支持,我想做类似以下的事情:
typedef enum {
bar_stuff,
bar_other
} Bar;
typedef enum {
foo_error=-1,
foo_none=0,
foo_again
} Foo_state;
Foo_state do_foo(Bar bar,Foo_state foo)
{
switch(foo)
{
case foo_none: //start
switch(bar)
{
case bar_stuff:
//do stuff
return foo_none;
case bar_other:
//do other stuff
return foo_again;
case foo_again: //!! this doesn't work
/* edit: this is supposed to be a case of
* switch(foo), not switch(bar)
*/
//do more other stuff
return foo_none;
default:
//stuff
return foo_none;
}
default:
//fail
return foo_error;
}
}
显然这不起作用(我得到重复的案例值,替代方案可能是未定义的行为/段错误)。我可以将switch(bar)写为if / else if / else链,但我希望有更好的方法。
如果有所作为,我正在使用gcc。
以下方法可行,但将是PITA维护:
Foo_state do_foo2(Bar bar,Foo_state foo)
{
switch(foo)
{
case foo_none: goto case_foo_none;
case foo_again: goto case_foo_again;
default:
//fail
return foo_error;
}
case_foo_none: //start
switch(bar)
{
case bar_stuff:
//do stuff
return foo_none;
case bar_other:
//do other stuff
return foo_again;
case_foo_again:
//do more other stuff
return foo_none;
default:
//stuff
return foo_none;
}
}
嗯,这似乎并没有产生上述“更好的方式”,所以我想知道是否有人预见到写这样的问题:
Foo_state do_foo3(Bar bar,Foo_state foo)
{
switch(foo)
{
case foo_none: //start
if(bar == bar_stuff)
{
printf("do stuff\n");
return foo_none;
}
else if(bar == bar_other)
{
printf("do other stuff\n");
return foo_again;
case foo_again: //continue
printf("do more other stuff\n");
return foo_none;
}
else
{
printf("stuff\n");
return foo_none;
}
default:
//fail
return foo_error;
}
}
我看到的问题是缺少bar_ *值(因为有几个这样的函数,有些枚举有几十个值),但我想这个测试脚本应该有用......
答案 0 :(得分:6)
您也可以将{}放在每个案例中:声明
如果没有它们,整个案例堆栈将被评估为一个单元,因此在一个案例中不能定义任何变量:
但是提出
case blah:
{
// do stuff
}
break;
您可以将任何想要的内容放在案例陈述中。
答案 1 :(得分:4)
嗯...使用等效的卡诺图来简化逻辑并使用
完成所有操作if (cond1 && cond2) {
doX();
return;
}
if (cond3 && cond4) {
doY();
return;
}
// Sometimes you can take shortcuts
if (cond5) {
doZ();
} else {
doW();
}
return;
此代码可读。如果可能,最好避免使用嵌套的东西。
首先检查最简单的条件会使函数更简单。
在你的情况下开始:
Foo_state do_foo2(Bar bar,Foo_state foo) {
if (foo != foo_none && foo != foo_again) {
return foo_error;
}
...
if (foo == foo_none) {
...
}
// Implicit Else
...
答案 2 :(得分:1)
一个简单的修复方法是更改bar_ enum中的值,使它们相对于foo_枚举是唯一的。但是,这并未解决您的代码令人困惑的事实。为什么要在bar_ switch语句中查找foo_值?从语法上讲,它是有效的(只要值是唯一的),但它的编码很差。
答案 3 :(得分:0)
好吧,您的代码似乎是这样做的:
bar \ foo foo_none foo_again other
bar_stuff doStuff, return foo_none do more other stuff, return foo_none return foo_error
bar_other do other stuff, return foo_again do more other stuff, return foo_none return foo_error
other stuff, return foo_none do more other stuff, return foo_none return foo_error
这就是我所说的卡诺图。现在,这是最简单的实现:
Foo_state do_foo2(Bar bar,Foo_state foo) {
if (foo == foo_again) {
// do more stuff
return foo_none;
}
if (foo != foo_none) { // other
return foo_error;
}
// foo_none
if (bar == bar_stuff) {
// do stuff
return foo_none;
}
if (bar == bar_other) {
// do other stuff
return foo_again;
}
// At this point bar = other
// stuff
return foo_none;
}
我相信这与你的代码完全相同,但不使用switch和gotos。您可以使用结果填写表格,也可以通过单元测试放置两个实现,以确保它们对所有输入执行相同的操作。