Nested Switch/Case duplicate Default cases problem

Hello all,
I have read through what seems to be all the Nested Switch topics here, plus a few on other C/C++ forums and nobody seems to address the situation of trying to have a "default" case in both the main and nested switch. My main outer switch has too many possible cases to code each one so a default is a must. The same possible input values are available to the inner case, so another default case is a must.

MAIN QUESTION: It seems that only one "default" is allowed no matter how many nested cases you have?

If I comment out either default case the code will compile but it won't act as desired.

GENERIC CONCEPT:

outer switch( first command ); // send some command via Serial Monitor
{
case A:
{
do thing;
inner switch( second command )
{
case a:
do stuff;
break;
case b:
do other stuff;
break;
default:
Serial.println("invalid second command");
break;
} //end inner switch
} //end case A. Extra bracket set around case A code did not help.
break;
case B:
do other thing;
break;
// default:
// Serial.println("invalid first command");
// break;
}

BEHAVIOR:

  • if 'first command' doesn't match 'A', 'B', 'a', or 'b' the inner default will execute.
  • if 'first command' matches any of the cases that case will execute.
  • For example, first command == a then case A "do thing" does NOT happen but inner case a "do stuff" does happen.

I assume the answer is going to be change the inner switch to If Else statements but maybe there's something special to properly using nested switches so they don't act like one big switch and have duplicate case conflicts?

Thanks

post c++ code that you have trouble with

...in code tags.

/*Program tracks and changes currentPosition.*/

int incomingByte = 0;   // for incoming serial data
int x = 1;              // for incoming numeric data
int currentPosition = 0;  //assume current position starts at zero
int secondByte = 0;     /*The up and down doesn't work. parseInt always returns 0 and x gets turned to 0. 
                        making this variable to try something else.*/

void setup() {
       Serial.begin(115200);     // opens serial port, sets data rate to 115200 bps
}

void loop() 
{
        // take action only on receiving data:
        if (Serial.available() > 0) 
        {
                // read the first incoming byte:
                incomingByte = Serial.read();
                Serial.print("incomingByte = ");
                Serial.println(incomingByte);

                // take action based on the first byte received
                switch (incomingByte) 
                {
                   case 73: // ASCII I - "Idle" command
                        Serial.println("executing case 73 Idle command");
                        Serial.print("currentPosition = ");
                        Serial.println(currentPosition);
                        break;
  
                  case 85:  // ASCII U - "Up" command
                  /*based on Labview code the U and D commands would have a numeric added to the string before that
                  message is sent to the Arduino. So the U command would get the number of positions to move added and become for example
                  U1 or U4 or whatever before being turned into a message.*/
                        Serial.println("executing case 85 Up command"); 
                        if (Serial.available() > 0)
                        {
                          secondByte = Serial.read();
                          Serial.print("secondByte = ");
                          Serial.println(secondByte);
                          switch (secondByte); 
                          {
                            case 49: // ASCII 1
                              Serial.println("executing Up subcase 49: move position up 1");                     
                              currentPosition = currentPosition + 1;
                              Serial.print("currentPosition = ");
                              Serial.println(currentPosition);
                              break;
                            case 50: // ASCII 2
                              Serial.println("executing Up subcase 50: move position up 2");                     
                              currentPosition = currentPosition + 2;
                              Serial.print("currentPosition = ");
                              Serial.println(currentPosition);
                              break;
                              
                            default:
                              Serial.println("invalid up command, currentPosition unchanged"); 
                              break;
                          } //end subcase  
                        }
                        else {
                          Serial.println("No serial data avalable to parse");
                        }
                   
                       break;

                  case 68:  // ASCII D - "Down" command                  
                        Serial.println("executing case 68 Down command");
                        x = Serial.parseInt();  //from original code, always makes x = 0
                        currentPosition = currentPosition - x;
                        Serial.print("currentPosition = ");
                        Serial.println(currentPosition);
                        break;
 
                  case 83:  // ASCII S - "Set Current Position to Zero" command
                        Serial.println("executing case 83 Set command");
                        currentPosition = 0;
                        Serial.print("currentPosition = ");
                        Serial.println(currentPosition);
                        break;

                  /*default:  // for any other input
                       Serial.println("executing case Default - Invalid command");
                       Serial.println("printing a blank space on next line.");
                       Serial.println("");
                       break;
                  */

                }//end case
                Serial.println("Outer case ended"); 
                Serial.println("----------");       

        }//end if
     
}//end void loop

Why not

case 'I':

?
Then you wouldn't need the dumb comment?
(Note: I have absolutely no idea if decimal 73 is an ASCII capital I )

Serial.println("executing case 85 Up command"); 
                        if (Serial.available() > 0)

The only reason you're likely to have a character available is because of the delay caused by the print.

This code is what I have done to a sketch that was written by someone else along with a Labview program that was meant to be an example of interacting with an arduino via Labview. The example didn't work and I've been messing with it ever since.
mostly I added a lot of Serial.print() to help me see what the code was doing, but the switch in Case 85 is my way of getting around the problem that Serial.parseInt() always returned 0

The commands I send from the Serial Monitor right now with no line ending to avoid any Labview issues.
The commands are I, U, D, and S which of course translate to their ASCII value for the switch.
But the Labview code for a U or D converts a numeric to string and appends it to the U or the D
The D case still shows how that is supposed to work
but when I write a command of "U1" it does not read the U then parse the 1. Things on that front are getting more complex than I understand.
the Serial.read() gets the first part of the command and leaves a value in the serial bus so it loops back around and Serial.read() reads the rest of the data on the bus and usually that results in triggering the default case.
for instance: command of U1 equals 85 then another loop that sees an ASCII value of 204.

EDIT: With the code as is I should say that a command of "D1" does not read the D as ASCII value 68 then go to that case and parse a value of 1 into the variable x. It would go to case 68, put a 0 in variable x, resulting in no change of currentPosition, then it would finish the loop go back to the top and find that Serial.available() is still true and get some nonsense value from the next Serial.read().

There is nothing to say about this
The inner defaults apply to the second switch and the outer default to the main switch

I’m not sure what’s the issue you think there is

I believe I stated the issue, but I'll repeat it: If both the inner and outer switch functions have a "default" case, the code will not compile.
The error message is "multiple default labels in one switch".
You can see in the code I shared that the outer default case is commented out. I can comment out that default case or the inner one and the code will compile. If I have both I will get the error.
EDIT: I believed wrong, I did not actually state that with both defaults the code would not compile. Apologies.

The message is 100% correct, you have the second default statement in the same switch. You ended your second switch with semicolon as soon as you introduced it.

*facepalm
That is why I put amateur right in the name!

Thanks everyone for taking a peak, and thanks killzone for seeing the typo problem.

I have a lot of stuff to learn about commands via the Serial Monitor and ASCII characters and what is going on with all that, but I'll keep grinding away at that issue myself for a while.
Thanks to TheMemberFormelyKnownAsAWOL I started trying out char variables for the Serial.read() so that's a whole new realm of stuff to mess with instead of checking ASCII values for everything.

Regarding Serial, I would suggest to study Serial Input Basics

1 Like

"peek"

1 Like