Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C将包含2个变量的IF语句转换为开关函数?_C_Variables_If Statement_Switch Statement - Fatal编程技术网

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

如何使用C将包含2个变量的IF语句转换为开关函数?,c,variables,if-statement,switch-statement,C,Variables,If Statement,Switch Statement,我有一个IF语句,我想转换成Switch语句。。。但它有两个变量!可以在C上做吗 这是一个石头、布、剪刀的游戏: R代表石头,p代表布,S代表剪刀 char play1, play2; printf("\nPlayer 1 - Enter your Play: "); scanf ("%c", &play1); printf("\nPlayer 2 - Enter your Play: "); scanf (" %c", &pl

我有一个IF语句,我想转换成Switch语句。。。但它有两个变量!可以在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!");}

我必须为其他选项这样做,所以最好使用switch

一般来说,答案是否定的:switch语句使用单个变量。但是,在某些情况下,您可以进行转换。例如,如果有两个变量a和b,其中a可以是0、1或2,b可以是0、1、2或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
}
可以为每个表达式嵌套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;
  ...
}
正如你所看到的,这有可能很快变得非常丑陋。如果必须基于值的组合进行分支,那么最好保持当前结构

#include <stdio.h>
#include <stdlib.h>

#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;
    }
}
但不适用于:

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

希望没有人使用它:

太聪明了一半的解决方案:

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 ((play1 << 8) + play2) {

  case 'RP':

    printf ("Paper wins!");
    break;

  case 'RS':

    printf ("Rock wins!");
    break;

  case 'RR':

    printf ("Draw!");
    break;
 }
由于开关是在单个变量上操作的,所以您必须能够以某种方式将多个输入组合成单个值。给定ASCII字符“R”、“P”和“S”的数值,将这两个字符相加将为每个配对提供唯一的和。然而,生成的代码可能比等价的if树更难读取。一般来说,这通常不是一个好的选择,因为当组合操作的基本假设(如唯一和)不再成立时,代码将很容易被破坏。随着可能输入值数量的增加,开关也变得笨拙。由于每种可能的组合都需要一个外壳,因此当您与少数输入选项一起使用时,您的交换机将变得很大且难以维护

在这种特殊情况下,开关块实际上会产生比使用if更多的代码。使用if可以一次处理多个案例。例如,您不需要三个单独版本的代码来检查是否存在平局。您也可以使用表格来查找答案,而不是开关或if。下面是一个结合了这些方法的示例:

// 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);
  }
}

表方法的最大好处是代码与数据是分开的。如果游戏规则发生了变化,或者有人正在学习游戏,想知道谁在什么情况下获胜,那么一张桌子就比翻阅大量代码更加方便用户。开关块本质上是查找表和处理代码的混合体,对于复杂的情况,它会很快变得难看。

请向我们展示您的代码。1。你为什么要这样做?2.张贴有问题的实际if语句。如果您的变量可以组合成一个,这是可能的。有点像C++多路转换器。如果超变量的可能值明确规定了原始两个变量的状态,那么它是可能的。示例:字符串连接、位屏蔽等。我越是把它挂在星上,我的头脑就越乱。@H2CO3我修正了格式,但我怀疑它是否会让我们更容易看到它:@axiom Yes:nested switch很容易在可读性上击败这个构造,它的性能可能也大致相同。不过,它会更长。请注意运算符优先级。您必须使用play1+play2@Howard好的,我明白了。我更新了答案。我用了X+yth,这真的很漂亮,有点吓人。如果你滥用预处理器,在CASEa,b之后可以有a:我会印象更深刻。@StephenCanon-sure:define CASEa,b}如果a==\u a&&b=\u b{u a!=a?0@DavidRF:如果:后面的第一个表达式是赋值,即CASEa,b:x=2;真的不能按您希望的方式进行解析,那么这将不起作用。如果_a恰好是浮点NaN,它也不会很好地工作。我认为您需要创建一个虚拟标签,使其真正正常工作。可能只是{dummylabel uuuuu线uuuuu uuuuu uuuu uuuu uuuu uuuu uuuuu uuuuuu。
switch ((play1 << 8) + play2) {

  case 'RP':

    printf ("Paper wins!");
    break;

  case 'RS':

    printf ("Rock wins!");
    break;

  case 'RR':

    printf ("Draw!");
    break;
 }
// 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);
  }
}