Search code examples
crecursionprocedural

Understanding recursion in the beer bottle example


I am practicing recursion in C on my own and I found this example online. However there is one thing I don't understand.

void singSongFor(int numberOfBottles)
{
if (numberOfBottles == 0) {
    printf("There are simply no more bottles of beer on the wall.\n\n");
} 
else {
    printf("%d bottles of beer on the wall. %d bottles of beer.\n",
           numberOfBottles, numberOfBottles);
    int oneFewer = numberOfBottles - 1;
    printf("Take one down, pass it around, %d bottles of beer on the wall.\n\n",
           oneFewer);
    singSongFor(oneFewer); // This function calls itself!

    // Print a message just before the function ends
    printf("Put a bottle in the recycling, %d empty bottles in the bin.\n",
             numberOfBottles);
   }
}    

Then I use a main method as such:

 int main(int argc, const char * argv[])
{
  singSongFor(4);
  return 0;
}

And the output is as such:

4 bottles of beer on the wall. 4 bottles of beer. Take one down, pass it around, 3 bottles of beer on the wall.

3 bottles of beer on the wall. 3 bottles of beer. Take one down, pass it around, 2 bottles of beer on the wall.

2 bottles of beer on the wall. 2 bottles of beer. Take one down, pass it around, 1 bottles of beer on the wall.

1 bottles of beer on the wall. 1 bottles of beer. Take one down, pass it around, 0 bottles of beer on the wall.

There are simply no more bottles of beer on the wall.

Put a bottle in the recycling, 1 empty bottles in the bin.

Put a bottle in the recycling, 2 empty bottles in the bin.

Put a bottle in the recycling, 3 empty bottles in the bin.

Put a bottle in the recycling, 4 empty bottles in the bin.

I understand the first part very well until I come to "There are simply no more bottles of beer on the wall. I don't understand afterwards how the variable number of bottles is incremented from 1 till 4.


Solution

  • Note that the last printf uses the numberOfBottles variable, and that is never modified. So upon returning from printing oneFewer bottles, it will print the recycling text with numberOfBottles. Remember that there is one different incarnation of the local variables per each call to the function.

    It can be seen easier if you indent the calls to the functions:

    4 bottles of beer on the wall...
      3 bottles of beer on the wall...
        2 bottles of beer on the wall...
          1 bottles of beer on the wall...
            There are simply no more bottles of beer on the wall.
          Put a bottle in the recycling, 1 empty bottles in the bin.
        Put a bottle in the recycling, 2 empty bottles in the bin.
      Put a bottle in the recycling, 3 empty bottles in the bin.
    Put a bottle in the recycling, 4 empty bottles in the bin.
    

    Now, each line that begins in the same column is written from the same call of the function. Do you see how the number of bottles and recycling coindice? That's because both use the same variable: numberOfBottles.