新手在递归函数中迷失了

时间:2012-12-24 21:40:14

标签: c

我正在尝试从一本书中学习C,但有些东西对我来说不够清楚。

以下代码

1)使用递归函数将啤酒瓶从99倒数到0。 2)一旦它从瓶子里出来,就会打印出“墙上没有瓶子了” 3)将瓶子逐一放入回收中

...       #more of same above
3 bottles of beer on wall, 3 bottles of beer 
Take one down, pass around, 2 bottls of beer 
2 bottles of beer on wall, 2 bottles of beer 
Take one down, pass around, 1 bottls of beer 
1 bottles of beer on wall, 1 bottles of beer 
Take one down, pass around, 0 bottls of beer 
There are no more bottles on the wall.
Put bottle in recycling, 1 empty bottles in bin 
Put bottle in recycling, 2 empty bottles in bin 
Put bottle in recycling, 3 empty bottles in bin 
....        #pattern continues

我明白它是如何倒计时的,以及为什么它不再说啤酒瓶,但我不明白如何调用瓶子进行回收的代码(printf),因为它是在其他部分条件,并且,一旦瓶数达到0,该函数就不会返回到条件的其他部分。

问题,最终的printf(“将瓶子放回收......”)如何调用99次,如何逐个增加瓶子?

代码

void singTheSong(int numberOfBottles)

{

    if(numberOfBottles == 0){
        printf("There are no more bottles on the wall.\n");
    }else {
        printf("%d bottles of beer on wall, %d bottles of beer \n", numberOfBottles,numberOfBottles);
        int oneFewer = numberOfBottles - 1;
        printf("Take one down, pass around, %d bottls of beer \n", oneFewer);
        singTheSong(oneFewer);
        printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles);

    }
}

int main(int argc, const char * argv[])
{

    singTheSong(99);
    return 0; 
}

3 个答案:

答案 0 :(得分:3)

这三行:

printf("Take one down, pass around, %d bottls of beer \n", oneFewer);
singTheSong(oneFewer);
printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles);

打印歌曲的这些部分:

Take one down, pass around, n - 1 bottls of beer
/* The entire song for n - 1 */
Put bottle in recycling, n empty bottles in bin

singTheSong完成执行后,打印最后一行,堆栈已展开,顶级函数继续执行。如果你暂时忘记了递归调用,只看到singTheSong的调用是一个神奇地起作用的黑盒子,那么这三行代码的行为与任何其他调用的工作方式没有什么不同。

答案 1 :(得分:0)

这可能会有所帮助。考虑将第一次调用替换为函数的实际主体:

void singTheSong(int numberOfBottles)

{

    if(numberOfBottles == 0){
        printf("There are no more bottles on the wall.\n");
    }else {
        printf("%d bottles of beer on wall, %d bottles of beer \n", numberOfBottles,numberOfBottles);
        int oneFewer = numberOfBottles - 1;
        printf("Take one down, pass around, %d bottls of beer \n", oneFewer);
        singTheSong(oneFewer);
        printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles);

    }
}

int main(int argc, const char * argv[])
{
    int numberOfBottles=99;

    if(numberOfBottles == 0){
        printf("There are no more bottles on the wall.\n");
    }else {
        printf("%d bottles of beer on wall, %d bottles of beer \n", numberOfBottles,numberOfBottles);
        int oneFewer = numberOfBottles - 1;
        printf("Take one down, pass around, %d bottls of beer \n", oneFewer);
        singTheSong(oneFewer);
        printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles);

    }
    return 0; 
}

在第一次调用时,当numberOfBottles == 99时,if (numberOfBottles == 0)将失败,并且只会执行else部分。它将打印两行,调用singTheSong(98),然后打印关于回收的行。

想象一下继续做这样的替换,你可能会看到它是如何工作的。

答案 2 :(得分:0)

使用递归时,有三个阶段:  1.终止条件(在这种情况下“没有啤酒瓶”(悲惨的情况! - 但如果你从99开始,我想也没那么糟糕)。没有这个,你会得到无限的递归,这不是一件好事!  2.递归调用。  3.到目前为止的递归步骤完成后你做了什么。

所以,就像一个真正的饮酒派对,没有人会在聚会结束之前进行清理,而且没有啤酒。相反,我们从墙上取出另一个瓶子,唱一下,将瓶子绕过,当瓶子完成后,我们从墙上拿出另一个,唱歌,喝酒,取瓶,唱歌等等。一旦所有瓶子已经完成(0个靴子),我们通过返回来整理(不再唱歌和喝酒,关闭时间等)。当然,递归呼叫的“返回”从最深的呼叫级别开始(最后一瓶啤酒= 1瓶'左'),然后回落到一个级别(2瓶),然后再降低到另一个级别(3)瓶子)等。

有时候人们会谈论“尾递归”,而这就是递归的最后一步是调用函数本身。