Switch / Case with multiple variables?

Ive been playing with switch / case and was wondering if there is a way to use multiple variables
something like

switch (a, b c)
{
case 1, 2, 3:
//do something
return;
}

i know that code wont compile, but is there a proper syntax for something like that or is there a different tool?

You cannot do that with case. You will have to use if / else if etc.

too bad there isnt something like switch / case for multiple variables, that would be slick

It would, but alas not.

If you tell us what it is you're trying to do, we could maybe suggest a solution.

im trying to program a wall avoiding robot, it has a ping)) sensor on a servo that gets distances from the left right and center then decides what to do. if it sees something on the left side it will turn right even if it should back up or something because this comes first in the code. I would like to write something that considers all the input before deciding but dont know what tool to use or how to format it with if, else if statements

here is my current main loop, i think most of the function names are pretty self explanitory

void loop()
{
  directionalPing();
  if(pingLeft <= 6)
    {
      turnRight(600);
      return;
    }
  if(pingRight <= 6)
    {
      turnLeft(600);
      return;
    }
  if(pingForward <= 6)
    {
      reverse(200);
      turnLeft(600);
      return;
    }
  if(pingForward > 6)
    {
      forward(500);
      reverse(50);
      return;
    }
}

Ive been playing with switch / case and was wondering if there is a way to use multiple variables
something like

switch (a, b c)
{
case 1, 2, 3:
//do something
return;
}

i know that code wont compile, but is there a proper syntax for something like that or is there a different tool?

1) you can nest switches

switch (a, b c)
{
case 1:
switch(b)
{
case 2:
etc

will result is a forest of code.

2) combine abc to one state (bit stuffing)

depending on the range of the values a,b,c you can pack these three vars in one .
suppose a = 0-3 (needs 2 bits) and b = 0-31 (5 bits) and c = 0-8, (3 bits)
then you can make

int val = a + b << 2 + c << 7 // val = [0000 00CC CBBB BBAA] bit pattern

and do the same for all relevant values.
As this is quite error prone you can "macrofy" this, see the sample sketch below (IDE 0.22)

//
//    FILE: MultiSwitch.pde
//  AUTHOR: Rob Tillaart
//    DATE: 09-06-2012
//
// PUPROSE: macrofying a multiple switch
//

#define SWITCH(a,b,c) switch(a + b<<2 + c<<7)
#define CASE(a,b,c) case(a + b<<2 + c<<7)

void setup()
{
  Serial.begin(9600);
  Serial.println("start...");
}

void loop()
{
  int a=2, b=3, c=4;
  int x = 5;

  SWITCH(a,b,c)
  {
    CASE(1,2,3):
    x=4;
    break;
    CASE(2,3,4):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

  a=1, b=2, c=3;

  SWITCH(a,b,c)
  {
    CASE(1,2,3):
    x=4;
    break;
    CASE(2,3,4):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);
  
  a++;
  
  SWITCH(a,b,c)
  {
    CASE(1,2,3):
    x=4;
    break;
    CASE(2,3,4):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);
}

notes:

  • all warnings about using macros apply,
  • there are limitations how long the bitpattern can be => use a long for var a to maximise the trick.
  • multiple multicase switches need additional macros

append.

instead of a macro one could think of using a function, but that doesn't work as the case is expecting a const value compile time. However one could do with just one macro mimicing the function. (coffee really clears up the mind :wink:

So here is the code with a normal switch and only one macro

//
//    FILE: MultiSwitch.pde
//  AUTHOR: Rob Tillaart
//    DATE: 09-06-2012
//
// PUPROSE: macrofying a multiple switch
//

#define H(a,b,c) (a + b<<2 + c<<7)

void setup()
{
  Serial.begin(9600);
  Serial.println("start...");
}

void loop()
{
  int a=2, b=3, c=4;
  int x = 5;

  switch(H(a,b,c))
  {
    case(H(1,2,3)):
    x=4;
    break;
    case(H(2,3,4)):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

  a=1, b=2, c=3;

  switch(H(a,b,c))
  {
    case(H(1,2,3)):
    x=4;
    break;
    case(H(2,3,4)):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

  
  a++;
  
  switch(H(a,b,c))
  {
    case(H(1,2,3)):
    x=4;
    break;
    case(H(2,3,4)):
    x=3;
    break;
  default:
    x=6;
    break;
  }
  Serial.println(x);
  delay(500);

}

Thank you robtillaart, Im working on using that technique in my code now.

I would like to write something that considers all the input before deciding but dont know what tool to use or how to format it with if, else if statements

I know I pointed you down this road, but what's the requirement here? Once you have all the various ping measures, what's your algorithm for deciding how to move?

I don't quite know how to go about developing an algorithm for the movement (im still pretty new at programming anything). I would like to start with something like if pingLeft pingRight and pingForward all revieve <6 then it backs up until it registers a longer distance on one of the sides and then turns that way.

but on a more general programming question:
what are various ways people use to imagine and or visualize different algorithms?

so this is kinda what i had in mind for the possible decisions - indicates a reading greater than 12" + indicates a reading of either 6 or between 6 and 12 depending on situation but im still not quite sure how to implement it into code that checks all 3 reading before making a decision


  1. L- F- R+ | x<6: hard turn left
    | 6> x >12 gentle turn left

  1. L- F+ R- | reverse measure again turn towards greatest distance

  1. L+ F- R= | y<6: hard turn right
    | 6> y >12 gentle turn right

  1. L- F+ R+ | hard turn left

  1. L+ F+ R- | hard turn right

  1. L+ F+ R+ | reverse, check L & R turn towards greater distance

  1. L+ F- R+ | if distance between objects is greater than width of robot continue forward
    | if distance between objects is smaller than robot reverse and turn towards
    | greatest reading

EDIT: does anyone know of somewhere i could go on them tharr interwebs to learn about such a thing? (somewhere or something free)

What you're trying to do would make sense if you were trying to create a compound finite state machine - although there are better ways to do it.

But it seems to me that is not what you need here. As I see it, you have a couple of algorithms to decide what action to take, and there is some precedence between them. If there is a wall in front then back up; otherwise if there is an obstruction to the left then steer right, and so on.

In that case I'd suggest using simple if/else style logic to decide what action to take and then have a separate chunk of code that carries it out. If there are lots of actions you might find it convenient to define them as enumerated values and then use a switch statement to execute the chosen action.

What you're trying to do would make sense if you were trying to create a compound finite state machine - although there are better ways to do it.

what sort of better ways? I dont really care so much about building the robot, but learning to program in general, the tools of problem solving used to write code.

when I recieve UDP command, I use switch in following way to join several possibilities to one result:

    if(packetBuffer[0] == 'R' || packetBuffer[0] == 'r') switch_value = 0; //reset
    if(packetBuffer[0] == 'W' || packetBuffer[0] == 'w') switch_value = 1; //speed up
    if(packetBuffer[0] == 'S' || packetBuffer[0] == 's') switch_value = 2; //speed down

    switch (switch_value) {
    case 0:
      servoPos = 90;           // tell servo to go to position servoPos
      servoMove(servoPos);
      led_blink();
      break;
    case 1:
      if( servoPos >= 10 && servoPos <= 165) {
      servoPos = servoPos+5;           // tell servo to go to position servoPos
      servoMove(servoPos);
      }
      led_blink();
      break;
    case 2:
      if( servoPos >= 15 && servoPos <= 165) {
      servoPos = servoPos-5;           // tell servo to go to position servoPos
      servoMove(servoPos);
      }
      led_blink();
      break;
    default: 
      // if nothing else matches, do the default
      // default is optional

I use switch in following way to join several possibilities to one result:

In the example you've posted, the switch is redundant - you could just as well have done the work in the "if" conditional clauses.

You can use have both CASE statements as follows.

case text1: 
  case text4:{
            //blah
            break;
        }

Mobdro App