我正在尝试从一本书中学习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;
}
答案 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)瓶子)等。
有时候人们会谈论“尾递归”,而这就是递归的最后一步是调用函数本身。