2

我正在尝试从一本书中学习 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)是如何被调用的,因为它在条件的 else 部分,并且,一旦瓶子的数量达到 0,该函数就永远不会返回到条件的 else 部分。

问题,最终的 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; 
}
4

3 回答 3

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视为一个神奇地工作的黑盒子,那么这三行代码的行为与任何其他调用的工作方式没有什么不同。

于 2012-12-24T21:44:39.297 回答
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 时,Theif (numberOfBottles == 0)会失败,只会执行 else 部分。它将打印两行,调用 singTheSong(98),然后打印关于回收的行。

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

于 2012-12-24T21:44:34.950 回答
0

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

因此,就像真正的饮酒派对一样,在派对结束并且没有啤酒之前,没有人会打扫卫生。取而代之的是,我们从墙上再拿一瓶,唱歌,把瓶子传过来,当那瓶用完后,我们从墙上再拿一瓶,唱歌,喝酒,拿瓶子,唱歌,等等。一旦所有的瓶子用完了(0 个靴子),我们回来收拾东西(不再唱歌和喝酒,关门时间等)。当然,递归调用的“返回”从最深的调用级别开始(最后一瓶啤酒 = 1 瓶“左”),然后返回一个级别(2 瓶),然后再下降一个级别(3瓶)等。

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

于 2012-12-24T22:09:26.513 回答