如何使用C将带有2个变量的IF语句转换为开关函数?

我有一个IF语句,我想转换成一个Switch语句……但它有2个变量! 是否可以在C上进行?

这是一个摇滚,纸,剪刀游戏:

(R代表岩石,P代表纸张,S代表剪刀)

char play1, play2; printf("\nPlayer 1 - Enter your Play: "); scanf ("%c", &play1); printf("\nPlayer 2 - Enter your Play: "); scanf (" %c", &play2); if (play1 == 'R' && play2 == 'P') { printf ("Paper wins!"); } else if (play1 == 'R' && play2 == 'S') { printf ("Rock wins!");} else if (play1 == 'R' && play2 == 'R) { printf ("Draw!");} 

我必须为其他选项做这个,所以最好使用开关!

 #include  #define SWITCH(a, b) char _a = a; char _b = b; if (0) #define CASE(a, b) } else if ((a == _a) && (b == _b)) { int main(void) { char play1, play2; printf("\nPlayer 1 - Enter your Play:"); scanf ("%c", &play1); getchar(); printf("\nPlayer 2 - Enter your Play:"); scanf ("%c", &play2); getchar(); SWITCH(play1, play2) { CASE('R','P') printf ("Paper wins!"); CASE('R','S') printf ("Rock wins!"); CASE('R','R') printf ("Draw!"); } return 0; } 

这是一个笑话:P

编辑:案例支持“:”

 #define PASTE(a, b) a##b #define LABEL(a, b) PASTE(a, b) #define SWITCH(a, b) char _a = a; char _b = b; if (0) #define CASE(a, b) } else if ((a == _a) && (b == _b)) { LABEL(LBL, __LINE__) 

但不适用于:

 CASE('R','R'): printf ("Draw a!"); CASE('S','R'): printf ("Draw!"); 

两个案例在同一行

解决了使用:

 #define SWITCH(a, b) char _a = a; char _b = b; if (0) #define CASE(a, b) } else if ((a == _a) && (b == _b)) {switch(1) case 1 

希望没人用它:)

通常,答案是“否”: switch语句使用单个变量。 但是,在某些情况下,您可以进行转换。 例如,如果您有两个变量ab ,其中a可以是0,1或2, b可以是0, 1, 2, or 3 ,则可以执行如下切换:

 switch (a*10+b) { case 0: break; // a == 0, b == 0 case 10: break; // a == 1, b == 0 case 20: break; // a == 2, b == 0 case 1: break; // a == 0, b == 1 case 11: break; // a == 1, b == 1 case 21: break; // a == 2, b == 1 case 2: break; // a == 0, b == 2 case 12: break; // a == 1, b == 2 case 22: break; // a == 2, b == 2 case 3: break; // a == 0, b == 3 case 13: break; // a == 1, b == 3 case 23: break; // a == 2, b == 3 } 
 #include  #include  #define PAIR(X,Y) (X<<8)|Y int main() { char play1, play2; printf("\nPlayer 1 - Enter your Play: "); scanf ("%c", &play1); printf("\nPlayer 2 - Enter your play: "); scanf (" %c", &play2); switch (PAIR(play1, play2)) { case PAIR('R','P'): printf ("Paper wins!\n"); break; case PAIR('R','S'): printf ("Rock wins!\n"); break; case PAIR('R','R'): printf ("Draw!\n"); break; default: //any thing else printf ("Default!\n"); break; } } 

我会建议多字符字符常量以简洁的方式实现这一点:

 switch ((play1 << 8) + play2) { case 'RP': printf ("Paper wins!"); break; case 'RS': printf ("Rock wins!"); break; case 'RR': printf ("Draw!"); break; } 

您可以为每个表达式嵌套switch语句,例如

 switch(a) { case 'A': switch(b) { case 0: // do something with A0 break; case 1: // do something with A1 break; ... } break; case 'B': switch(b) { case 0: // do something with B0 break; ... } break; ... } 

如你所见,这有可能很快变得非常丑陋。 如果你必须根据值的组合进行分支,那么你最好保持当前的结构。

太聪明的解决方案:

 enum Play { Rock = 0, Paper = 1, Scissors = 2 }; enum Outcome { Tie = 0, P1Win = 1, P2Win = 2 }; enum Play parseMove(char input) { switch (input) { case 'R': return Rock; case 'P': return Paper; case 'S': return Scissors; default: /* invalid input */; } } enum Outcome gameResult(enum Play p1, enum Play p2) { return (3 + p1 - p2)%3; } ... switch(gameResult(parseMove(play1), parseMove(play2))) { case Tie: printf("Tie!\n"); case P1Win: printf("Player 1 wins!\n"); case P2Win: printf("Player 2 wins!\n"); } 

由于switch对单个变量进行操作,因此您必须能够以某种方式将多个输入组合成单个值。 给定ASCII字符“R”,“P”和“S”的数值,将两个字符加在一起将为每个配对提供唯一的总和。 但是,生成的代码可能比等效的if树更难阅读。 通常,这通常不是一个好的选择,因为当添加新的输入选项并且“组合”操作的基本假设(例如唯一总和)不再成立时,您的代码将非常容易中断。 随着可能的输入值的数量增加, switch也变得难以处理。 由于每个可能的组合都需要一个case ,因此当使用多个输入选项时,您的switch会变得很大并且难以维护。

对于这种特殊情况, switch块实际上会产生比使用if更多的代码。 使用if让您同时处理多个案例。 例如,您不需要三个单独的代码版本来检查绑定。 您还可以使用表来查找答案而不是switchif 。 以下是结合这些方法的示例:

 // Table of outcomes. The option in the second // column wins over the option in the first column. char matchup[3][2] = { {'P', 'S'}, // paper is cut and destroyed {'S', 'R'}, // scissors are smashed and destroyed {'R', 'P'}, // rock is ... covered up? }; void announce_winner(char player1, char player2) { int i; if (player1 == player2) { printf("Draw\n"); return; } for (i=0; i<3; ++i) { if (player1 == matchup[i][0]) printf("%c wins\n", (player2 == matchup[i][1]) ? player2 : player1); } } 

表格方法的最大好处是您的代码与数据分开。 如果游戏规则发生变化,或者有人正在学习游戏,并想知道谁在什么情况下获胜,那么表格变得更加用户友好,而不是必须挖掘大量代码。 switch块本质上是查找表和处理代码全部混合在一起,对于复杂的情况,它变得很难看。