-1

Help me understand how the program works.

I take it from the book of Steven Pratt “Program language C” I find on page № 289 exercise №6.

It's a program, her code here:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int i = 0;
    while (i<3) {
        switch (i++) {
            case 0 : printf ("fat ");
            case 1 : printf ("hat ");
            case 2 : printf ("cat ");
            default : printf ("Oh no ");
        }
        putchar('\n');
    }
    return 0;
}

Please correct me if I am not right at all. Right now, I would like to explain how it works. Firstly to work the function “while” three times.

The variable “i” has first time value 0. Then during the function "while" work, the variable has to be added three times three times.

As a result of program work, I had this result:

fat hat cat oh no
hat cat oh no
cat oh no

But I can't understand how I've got such a result. I am used to IDE CodeBlock, and my compiler works well. I changed the program code many times to understand how it worked at all. I changed the operatore "case".

Right now I changed the program kode so:

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

int main(void)
{
  int i = 0;
  while (i<2) {
    switch (i++) {
    case 1 : printf ("fat ");
    case 2 : printf ("hat ");
    case 3 : printf ("cat ");
    default : printf ("Oh no ");
  }
  putchar('\n');
  }
  return 0;
}

After I got such a result:

oh no
fat hat cat oh no

But I can’t understand why the program works so? In my opinion the program must give such a result at all:

fat
Oh no

I think result or program work, must be only so. Why the program work so?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Mikhail
  • 1
  • 1
  • Read up on how the post-increment operator works! (It returns the *original* value and then does the increment.) – Adrian Mole Apr 05 '22 at 12:19
  • 5
    Have you seen the `break` statement in any of the example code? – ryyker Apr 05 '22 at 12:19
  • 1
    That's a great opportunity to start learning to use your debugger. Also read about the `break` statement, I'm sure Steven Pratt talks about this in his book. Once you understand how the `break` statement works with switch/case, you'll understand what the _absence_ of the `break` statement does. – Jabberwocky Apr 05 '22 at 12:28
  • The best way to understand your program would be to run your program line by line in a [debugger](https://stackoverflow.com/q/25385173/12149471), while monitoring the control flow and the values of all variables. – Andreas Wenzel Apr 05 '22 at 12:42

2 Answers2

2

Your code should look like this:

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

int main(void)
{
  int i = 0;
  while (i<2) {
    switch (i++) {
     case 1 : printf ("fat "); 
              break;  // notice the "break" instruction after each "case" instruction block inside the switch.
     case 2 : printf ("hat "); 
              break; // each "break" lets the program know where the instructions end for each "case" block.
     case 3 : printf ("cat "); 
              break; 
     default : printf ("Oh no "); 
              break;
    }
    putchar('\n');
  }
 return 0;
}
SimpForJS
  • 88
  • 9
  • 4
    Instead of providing a code-only answer, you may want to add a bit of text which explains what was wrong and how your solution fixes it. – Andreas Wenzel Apr 05 '22 at 12:38
  • @AndreasWenzel Thanks for the suggestion. I added some comments to the code. Hope it is much more clear now. – SimpForJS Apr 20 '22 at 14:27
2

"Why the program work so?"

In short it is because of the way a post-increment variable works, and that the book's implementation of the switch statement, although legal is non-typical, failing to limit execution flow to one case per iteration.

First, the form of the switch statement out of the book is not typical. I would expect that some of the text in that section of the book should eventually include use of the break statement placed between each of the case lines

In the book's original example, when switch is called on the first loop, i == 0, resulting in this execution flow:

starts at `case 0:` then increments `i` to `1`, then outputs `fat`,   
falls through to `case 1:` outputs `hat`,   
falls through to `case 2:` outputs `cat`,  
falls through to `default` outputs `Oh no`    

The 2nd iteration of the while loop, with i == 1, again post-incremented, starts at the 2nd case

starts at `case 1:` `i` is incremented to `2`, then outputs `hat`,   
falls through to `case 2:` outputs `cat`,   
falls through to `default` outputs `Oh no`  

With i == 2 the third iteration follows:

starts at `case 2:` i is incremented to `3` outputs `cat`,   
falls through to `default` outputs `Oh no`   

In your modified code, the 0 case is removed. Because i is initialized to 0 execution flow jumps immediately to the default case. And you can follow the rest.

Note, in the text of your book you will likely learn that the switch statement is commonly used in conjunction with the break statement, ensuring only one case is executed per swtich selection:

int main(void)
{
    int i = 0;
    while (i<3) {
        switch (i++) {
            case 0 : printf ("fat ");
              break;// execution flow jumps directly to closing }
            case 1 : printf ("hat ");
              break;// execution flow jumps directly to closing }
            case 2 : printf ("cat ");
              break;// execution flow jumps directly to closing }
            default : printf ("Oh no ");
        }
        putchar('\n');
    }
    getchar();
    return 0;
}
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Re “Only then does the variable `i` increment to `1`.”: The side effects of the post-increment operator must be complete by the sequence point following the full expression in the `i++` of `switch (i++)`. That is prior to executing any of the `printf` calls. – Eric Postpischil Apr 05 '22 at 12:59
  • @EricPostpischil - Yes. I have re-written to correct. Thanks. – ryyker Apr 05 '22 at 13:19