最近在学习objective-c,教程中有一段代码没弄清楚,是关于递归的,我用截图的形式发上来,给大家看看
void singTheSong(int numberOfBottles)
{
if (numberOfBottles == 0) {
printf("there are simply no more bottles of beer on the wall.\n");
} else {
printf("%d bottles of beer on the wall. %d bottles of beer.\n",
numberOfBottles, numberOfBottles);
int oneFewer = numberOfBottles - 1;
printf("Take one dowm, pass it around, %d bottles of beer on the wall.\n",
oneFewer);
singTheSong(oneFewer);
printf("put a bottle in the recycling, %d empty bottles in the bin.\n",
numberOfBottles);
}
}
int main(int argc, const char * argv[])
{
singTheSong(99);
return 0;
}
它的输出结果是这样的:
99 bottles of beer on the wall. 99 bottles of beer.
Take one dowm, pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall. 98 bottles of beer.
Take one dowm, pass it around, 97 bottles of beer on the wall.
97 bottles of beer on the wall. 97 bottles of beer.
Take one dowm, pass it around, 96 bottles of beer on the wall.
96 bottles of beer on the wall. 96 bottles of beer.
Take one dowm, pass it around, 95 bottles of beer on the wall.
......(中间重复的省略)
1 bottles of beer on the wall. 1 bottles of beer.
Take one dowm, 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, 98 empty bottles in the bin.
put a bottle in the recycling, 99 empty bottles in the bin.
Program ended with exit code: 0
这段代码,我看不懂的地方是,它如何从numberOfBottles等于0的时候,又继续运行了
printf("put a bottle in the recyling, %d empty bottles in the bin.\n",
numberOfBottles);
这段代码呢?并且numberOfBottles一直在+1
请大家帮我解惑,谢谢了~
重要な点: 関数呼び出しには
push
操作があり、再帰呼び出しが返されると、再帰の前に戻る
ことを理解する必要があります。Continue
再帰呼び出しを実行した後のコードです。压栈
操作, 递归调用返回时会回到
递归之前, 并继续
执行递归调用之后的代码.将你的
singTheSong(99);
替换成singTheSong(3);
说下吧.入参为3, 下面两行打印
3 bottles of beer on the wall. 3 bottles of beer.
Take one dowm, pass it around, 2 bottles of beer on the wall.
第一次递归调用singTheSong(2), 入参为2.
注意, 此时singTheSong(oneFewer); 之后的printf打印不会出现, 因为递归调用还没有返回;
后面你看到的 numberOfBottles一直在+1 现象的直接原因就在这.
2 bottles of beer on the wall. 2 bottles of beer.
Take one dowm, pass it around, 1 bottles of beer on the wall.
第二次递归调用singTheSong(1), 入参为1
同样, singTheSong(oneFewer) 之后的printf打印不会出现;
1 bottles of beer on the wall. 1 bottles of beer.
Take one dowm, pass it around, 0 bottles of beer on the wall.
第三次递归调用singTheSong(0), 入参为0, 直接打印下面一行, 并退出;
注意, 这里的退出是退回到第二次递归的栈. 并从singTheSong(oneFewer)之后的printf开始执行.
there are simply no more bottles of beer on the wall.
因为第二次递归入参为1, 所以这里打印下面一行
第二次递归调用退回到 第一次 递归的栈继续执行
put a bottle in the recycling, 1 empty bottles in the bin.
因为第一次递归入参为2, 所以这里打印下面一行
第一次递归调用退回到最初的singTheSong(3)继续执行
put a bottle in the recycling, 2 empty bottles in the bin.
最初的singTheSong(3)调用入参为3, 所以打印下面一行.
singTheSong(99);
をsingTheSong(3);
に置き換えて教えてください。入力パラメータは 3 で、次の 2 行が出力されます
🎜 壁にはビールが3本🎜。 ダウムを 1 つ取って、それを回して、壁にビール 2 本を置きます。🎜 🎜singTheSong(2) への最初の再帰呼び出し、入力パラメーターは 2 です。
🎜🎜この時点では、singTheSong(oneFewer); の後の printf 出力は表示されないことに注意してください。再帰呼び出しはまだReturn;
🎜🎜🎜後で表示されるnumberOfBottlesは常に+1です。これが現象の直接の原因です。
🎜🎜 壁にはビールが2本🎜 ダウムを 1 つ取り、周りに回し、壁にビール 1 本を置きます。🎜 🎜singTheSong(1) への 2 回目の再帰呼び出し、入力パラメーターは 1 です
🎜同様に、singTheSong(oneFewer) の後の printf は表示されません。
🎜 壁にはビールが1本。 ビールを 1 つ受け取って、周りに回してください。壁にはビールのボトルが 0 つあります。🎜 🎜3 番目の再帰呼び出し singTheSong(0)、入力パラメータは 0、次の行を直接出力して終了します。
🎜🎜ここでの終了は、スタックに戻ることであることに注意してください。 2 番目の再帰。そして singTheSong(oneFewer) の後の printf から実行を開始します。
🎜🎜 壁にビールの瓶がもうありません。🎜 🎜2 番目の再帰の入力パラメータは 1 であるため、次の行がここに出力されます
🎜2 番目の再帰呼び出しは最初の再帰スタックに戻り、実行を継続します
🎜 ボトルはリサイクルに出して、空のボトルはゴミ箱に捨ててください。🎜 🎜最初の再帰入力パラメータは 2 であるため、次の行がここに出力されます
🎜最初の再帰呼び出しは元の singTheSong(3) に戻って実行を継続します
🎜 ボトル1本はリサイクルに出して、空のボトル2本はゴミ箱に捨ててください。🎜 🎜最初の singTheSong(3) 呼び出しの入力パラメータは 3 なので、次の行が出力されます。
🎜 ボトル1本はリサイクルに出して、空のボトル3本はゴミ箱に捨ててください。🎜実行順序の問題です。
numberOfBottles
が常に +1 になる状況はありませんsingTheSong(99);
singTheSong(98);しかし、この時点では
singTheSong(99);
はまだ実行されていませんnumberOfBottles
一直在+1的情况singTheSong(99);
执行时需要调用singTheSong(98);
但此时singTheSong(99);
并没有执行完该段代码没有被调用,直到
このコードは、singTheSong(0);
运行完成之后,singTheSong(1);
方法体中的最下面的printf
リーリーsingTheSong(0);
の実行が終了し、singTheSong(1);
メソッド本体コードの一番下のprintf
が実行されるまで呼び出されません。 >コードが実行され、再帰的に 2、3、4... 99🎜 の実行が開始されます。