2

本から C を学ぼうとしていますが、明確に説明されていないことがあります。

次のコード

1) 再帰関数を使用して、ビールのボトルを 99 から 0 までカウントダウンします。2) ボトルがなくなると、「壁にもうボトルはありません」と表示され、3) ボトルを 1 つずつリサイクルに入れます。

...       #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 に達すると、関数は条件の else 部分に戻ることはありません。

質問、最終的な printf (「ボトルをリサイクルに入れます...」) はどのようにして 99 回呼び出され、どのようにしてボトルを 1 つずつインクリメントできるのでしょうか?

コード

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

これらの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魔法のように機能するブラックボックスと見なした場合、これらの3行のコードの動作は、他の呼び出しの動作と同じです。

于 2012-12-24T21:44:39.297 に答える
0

再帰を使用する場合、次の3つのフェーズがあります。1。終了条件(この場合は「ビールのボトルがない」(悲しい状況です!-99から始めた場合はそれほど悪くないと思います)。これがないと、無限の再帰が発生します。 、これは良いことではありません!2.再帰呼び出し。3。これまでの再帰ステップが終了した後に行うこと。

ですから、本物の飲み会のように、パーティーが終わり、ビールがなくなるまで、誰も片付けをしません。代わりに、壁から別のボトルを取り出して少し歌い、ボトルを回します。そのボトルが完成したら、壁から別のボトルを取り出し、歌い、飲み、ボトルを取り出し、歌います。ボトルが完成し(0ボトル)、戻って片付けます(歌ったり飲んだりする必要がなくなり、閉店時間など)。そしてもちろん、再帰呼び出しからの「リターン」は、最も深い呼び出しレベル(ビールの最後のボトル= 1ボトル「左」)で始まり、レベルを下げて(2ボトル)、次に別のレベルを下げます(3ボトル)など。

時々人々は「末尾再帰」について話します、そしてそれは再帰の最後のステップが関数自体を呼び出すことであるときです。

于 2012-12-24T22:09:26.513 に答える
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部分のみが実行されます。2行を印刷し、singTheSong(98)を呼び出してから、リサイクルに関する行を印刷します。

このような置換を継続することを想像してみてください。そうすれば、それがどのように機能するかがわかるでしょう。

于 2012-12-24T21:44:34.950 に答える