构建部分重叠的案例陈述的更好方法
Better Way to Structure Case Statements that Partially Overlap
假设案例 1 执行操作 A、B、C、D,案例 2 执行操作 E、B、C、D。有没有比下面更好的方法来构造它?
switch (id)
{
case 1:
case 2:
if (id==1) A();
if (id==2) E();
B();
C();
D();
break;
//More cases below
}
或
switch (id)
{
case 1:
A();
B();
C();
D();
break;
case 2:
E();
B();
C();
D();
break;
//More cases below
}
澄清一下:所以我想根据我拥有的对象类型分解要完成的操作。所有这些对象都不共享任何操作,除了这两个对象共享所有操作,除了一个对每个对象都是唯一的。
使用switch
构造完全看需要。
在这里而不是 switch
if else if
看起来更合适。
在您显示的第一个示例中,switch
没有任何意义,因为您要通过 if
检查并且无论 id
传递给 switch
的情况如何执行的语句都一样。
if(id == 1)
{
A();
}
else if(id == 2)
{
B();
}
else if()
{
......
/* Rest of your conditions */
}
else
{
}
没有问题的完整说明,很难知道什么是最好的。这是一个替代方案,它使用 switch case fall-through 来处理问题中的琐碎要求
// handle the two oddball objects
switch (id)
{
case 1: A(); break;
case 2: E(); break;
}
// handle all the objects
switch (id)
{
case 1:
case 2:
B();
C();
D();
break;
// other cases
}
就我个人而言,我可能会使用辅助函数,并希望编译器能够适当地内联。假设这三个共享动作形成一个有用的组合似乎是合理的,因为它被调用了不止一次。
void BCD(void) {
B();
C();
D();
}
// ...
switch (id) {
case 1: A(); BCD(); break;
case 2: E(); BCD(); break;
// ...
}
有些人(不是我)可能会说这是 goto
的合法使用,使用相同的参数但不相信编译器优化:
switch (id) {
case 1: A();
goto BCD;
case 2: E();
BCD: B();
C();
D();
break;
//...
}
作为对历史的好奇,合法但强烈反对使用不正确的嵌套条件来影响 goto。参见示例 live on ideone.
对于给定的星座,我会使用:
switch (id)
{
case 1:
A();
// add a comment why you do not break here!
case 2:
if ( id == 2 ) // the compiler might optimize this
E();
B();
C();
D();
break;
//More cases below
}
聪明的编译器可能会检测到 if
并将其转换为跳过 E();
。
但实际分组完全取决于整个序列。例如。函数参数可能会改变最佳解决方案。
(1) 也许,您可以将它们放在函数指针中 table.
void (*func[3])() = {0 /*dummy*/, A, B };
....
switch (id)
{
case 1:
case 2:
func[id]();
B();
C();
D();
break;
}
(2) 并且可能也包装其他函数:
void BCD(void){
B();
C();
D();
}
void (*func[3])() = {0 /*dummy*/, A, B };
....
switch (id)
{
case 1:
case 2:
func[id]();
BCD();
break;
}
这个 "wrap" 在这里是可以的,但如果这些功能恰好发生在 return errors/values.
上,一般来说可能并不理想
(3) 您还可以将 func[id]();
移动到包装器并将 id
传递给 BCD()
:
void (*func[3])() = {0 /*dummy*/, A, B };
void func_calls(int id){
func[id]();
B();
C();
D();
}
...
switch (id)
{
case 1:
case 2:
func_calls(id);
break;
}
以上是不是"better"取决于你对更好的定义:)
走这条路以保持概览,以防你有更多这样的情况:
switch (id)
{
case 1:
case 2:
switch(id)
{
case 1:
A();
break;
case 2:
E();
break;
default:
assert(0);
break;
}
B();
C();
D();
break;
//More cases below
default:
assert(0);
break;
}
优化由编译器完成。
假设案例 1 执行操作 A、B、C、D,案例 2 执行操作 E、B、C、D。有没有比下面更好的方法来构造它?
switch (id)
{
case 1:
case 2:
if (id==1) A();
if (id==2) E();
B();
C();
D();
break;
//More cases below
}
或
switch (id)
{
case 1:
A();
B();
C();
D();
break;
case 2:
E();
B();
C();
D();
break;
//More cases below
}
澄清一下:所以我想根据我拥有的对象类型分解要完成的操作。所有这些对象都不共享任何操作,除了这两个对象共享所有操作,除了一个对每个对象都是唯一的。
使用switch
构造完全看需要。
在这里而不是 switch
if else if
看起来更合适。
在您显示的第一个示例中,switch
没有任何意义,因为您要通过 if
检查并且无论 id
传递给 switch
的情况如何执行的语句都一样。
if(id == 1)
{
A();
}
else if(id == 2)
{
B();
}
else if()
{
......
/* Rest of your conditions */
}
else
{
}
没有问题的完整说明,很难知道什么是最好的。这是一个替代方案,它使用 switch case fall-through 来处理问题中的琐碎要求
// handle the two oddball objects
switch (id)
{
case 1: A(); break;
case 2: E(); break;
}
// handle all the objects
switch (id)
{
case 1:
case 2:
B();
C();
D();
break;
// other cases
}
就我个人而言,我可能会使用辅助函数,并希望编译器能够适当地内联。假设这三个共享动作形成一个有用的组合似乎是合理的,因为它被调用了不止一次。
void BCD(void) {
B();
C();
D();
}
// ...
switch (id) {
case 1: A(); BCD(); break;
case 2: E(); BCD(); break;
// ...
}
有些人(不是我)可能会说这是 goto
的合法使用,使用相同的参数但不相信编译器优化:
switch (id) {
case 1: A();
goto BCD;
case 2: E();
BCD: B();
C();
D();
break;
//...
}
作为对历史的好奇,合法但强烈反对使用不正确的嵌套条件来影响 goto。参见示例 live on ideone.
对于给定的星座,我会使用:
switch (id)
{
case 1:
A();
// add a comment why you do not break here!
case 2:
if ( id == 2 ) // the compiler might optimize this
E();
B();
C();
D();
break;
//More cases below
}
聪明的编译器可能会检测到 if
并将其转换为跳过 E();
。
但实际分组完全取决于整个序列。例如。函数参数可能会改变最佳解决方案。
(1) 也许,您可以将它们放在函数指针中 table.
void (*func[3])() = {0 /*dummy*/, A, B };
....
switch (id)
{
case 1:
case 2:
func[id]();
B();
C();
D();
break;
}
(2) 并且可能也包装其他函数:
void BCD(void){
B();
C();
D();
}
void (*func[3])() = {0 /*dummy*/, A, B };
....
switch (id)
{
case 1:
case 2:
func[id]();
BCD();
break;
}
这个 "wrap" 在这里是可以的,但如果这些功能恰好发生在 return errors/values.
上,一般来说可能并不理想(3) 您还可以将 func[id]();
移动到包装器并将 id
传递给 BCD()
:
void (*func[3])() = {0 /*dummy*/, A, B };
void func_calls(int id){
func[id]();
B();
C();
D();
}
...
switch (id)
{
case 1:
case 2:
func_calls(id);
break;
}
以上是不是"better"取决于你对更好的定义:)
走这条路以保持概览,以防你有更多这样的情况:
switch (id)
{
case 1:
case 2:
switch(id)
{
case 1:
A();
break;
case 2:
E();
break;
default:
assert(0);
break;
}
B();
C();
D();
break;
//More cases below
default:
assert(0);
break;
}
优化由编译器完成。