Help understanding Switch Statement: Case within another case

Discussion in 'Programmer's Corner' started by integral, Sep 20, 2011.

  1. integral

    Thread Starter New Member

    Aug 19, 2010
    Hello ,

    I need help understanding what is going on in the program below. I got this program from “example 2” towards the bottom of the page from the following c++ tutorial:

    If someone can explain in words exactly what is happening I will appreciate it. I understand switch statements however this is the first time that I have come across a switch statement that contains a case within another case. I dont understand why I end up with the results I get for the case that contains another case. For example, when the line in green is executed what happens that "Mystery" is not outputted but Novel and Fiction get outputted?

    Here is the code:
    Code ( (Unknown Language)):
    1. #include <iostream>
    3. enum EBookType { keMystery,
    4.                  keNovel,
    5.                  keFiction,
    6.                  keNonFiction};
    9. void PrintBookType( EBookType eType)
    10. {
    11.     using namespace std;
    12.     switch (eType) {
    13. [COLOR=Red]        case keMystery:
    14.         {
    15.             cout << "Mystery" << endl;
    16.             case keNovel:
    17.             {
    18.                 cout << "Novel" << endl;
    19.                 case keFiction:
    20.                 {
    21.                     cout << "Fiction" << endl;
    22.                     break;
    23.                 }
    24.             }
    25.         }[/COLOR]
    27.         case keNonFiction:
    28.         {
    29.             cout << "Non-fiction" << endl;
    30.             break;
    31.         }
    32.         default:
    33.         {
    34.             cout << "unknown type" << endl;
    35.             break;
    36.         }
    37.     }
    38. }
    41. int main()
    42. {
    43.     using namespace std;
    44.     EBookType eAtlasShrugged = keMystery;
    45.     EBookType eLionWitchWardrobe = keNovel;
    46.     EBookType eTheRepublic = keNonFiction;
    48.     PrintBookType(eAtlasShrugged);
    49.     cout << endl;
    50.     [COLOR=SeaGreen]PrintBookType(eLionWitchWardrobe);[/COLOR]
    51.     cout << endl;
    52.     PrintBookType(eTheRepublic);
    53.     cout << endl;
    54.     PrintBookType( (EBookType) 85 );
    56.     return EXIT_SUCCESS;
    58. }
    Here is the program output:
    Code ( (Unknown Language)):
    1. Mystery
    2. Novel
    3. Fiction
    5. Novel
    6. Fiction
    8. Non-fiction
    10. unknown type
    11. Press any key to continue . . .
  2. someonesdad

    Senior Member

    Jul 7, 2009
    I could tell you a straight answer, but you won't learn much. Instead, I'll suggest two things you can do to learn more. First, step through the curious code with a debugger and examine the values of all the variables and understand how they are changing. In particular, watch how the switch statement behaves when you give it the green line's value. A hint in doing debugging is to remove all the code that isn't relevant to the problem so you can focus on the key operations.

    The real learning will come when you dump the assembly output of your code. This will let you see how a switch statement works. You don't need any real training in the assembly language of the platform you're on -- you should be able to puzzle things out by their names and looking things up on the web.

    By the way, nice job on submitting a compilable and working chunk of code along with output. Many of the questions are tautologically equivalent to "I have a piece of rope. How long is it?" :p
  3. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    It may be clearer to rewrite the case statement without the brackets, as they have no effect (as you have seen):

    Code ( (Unknown Language)):
    1. void PrintBookType( EBookType eType)
    2. {
    3.     using namespace std;
    4.     switch (eType) {
    5.         case keMystery:
    6.             cout << "Mystery" << endl;
    8.         case keNovel:
    9.             cout << "Novel" << endl;
    11.         case keFiction:
    12.             cout << "Fiction" << endl;
    13.             [B]break;[/B]
    15.         case keNonFiction:
    16.             cout << "Non-fiction" << endl;
    17.             [B]break;[/B]
    19.        default:
    20.             cout << "unknown type" << endl;
    21.             [B]break;[/B]
    22.     }
    23. }
    To explain the unexpected results, consider when passed eType = keNovel. The switch statement jumps down to case keNovel where it starts executing code until it sees a break statement. Hence it prints both "Novel" and "Fiction".

    Note I disagree with viewing the assembly dump. Avoiding messing with assembly is the main reason for going to a high level language, though reading it is not as error prone as writing it. However, single stepping thru any code should be your first step after getting it to compile.
  4. someonesdad

    Senior Member

    Jul 7, 2009
    Where I used to work, we'd have the newbie firmware engineers do this because it would teach them a little about how compilers work and how to think like a compiler (of course, if they were CS-types, they should have taken a class on compiler construction and have known this). It's just another tool in the toolbox -- and it will become useful someday.
  5. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    Sure it's a good tool, but currently I'm doing PIC32's and I'm completely clueless as to what that assembly could possibly mean.

    The past few days I was tracking down a linker problem leading to a malloc() call fault where malloc would never return. My lib for malloc doesn't include the C source so no C tracing is possible. I discovered the problem by single stepping thru program memory looking at God knows what as statements, but did notice the statements were all in a few dozen instructions of each other, hence knew it was stuck in a loop.

    I don't know PIC32 assembly and I have no intentions of ever learning it.
  6. integral

    Thread Starter New Member

    Aug 19, 2010
    Thanks for this. Rewriting it withouth the braces really cleared things up. The braces confused me - I was comparing each "embedded" case statement to "embedded" if statements.