2017-10-01 5 views
0

をデクリメント理由を知っているとC++がどのように動作するかのいくつかを知っているが、私は本当にこのコードがどのように動作するか理解していないしていない:(C++)再帰関数は - これは私がちょうど再帰関数で始まるよ

void q9_draw_triangle(int a, int b) { 

     // a is the starting point, b is the end 
     if (a > b) return; 

     // print pattern first 
     for(int i = 0; i < a; i++){ 
      std::cout << "-"; 
     } 
     std::cout << std::endl; 

     // call on triangle where a is incremented once 
     q9_draw_triangle(a+1,b); 

     // print pattern last 
     for(int i = 0; i < a; i++){ 
      std::cout << "-"; 
     } 
     std::cout << std::endl; 

    } 

q9_draw_triangle(a + 1、b)以降の上半分がどのように動作するかを確認しますが、最後のforループは取得しません。私はデバッガを使ってこのコードを踏んだところで、> bが起こったときに最後の閉じ括弧にジャンプし、最後のforループにジャンプし、三角形の後半を描画して、値を開始する値まで戻し始めました。なぜこれが起こったのか、あるいはこれを減らすためにこれを行う方法を知っているか分かりません。

EDIT:私の入力はa = 3、b = 7だったとします.q9_draw_triangle(a + 1、b)以降の最初の部分は3行、次に4,5、 6,7。次に、最後の閉じ括弧に移動し、最後のforループに移動して7を描画します。最後の閉じ括弧に戻り、forループに戻って6を描画し、次に5,4,3を繰り返します。それはなぜこれをするのですか?それは決して最後のループの上にはもう一度行きませんし、それ自体が減少し、それは私が理解していないものです。そして、それが3になると、関数から最終的に脱出します。これをどうやって知っていますか?

これを理解する助けとなることはありがたいです!

+0

ここでは、特に最適化がオンになっている場合、ここでデバッガで起こっていることに注意してください。現代のコンパイラはコードを大幅に並べ替えることができ、経験豊富なプログラマでさえも何が起こっているのかを再構築するためにはかなりの思考が必要です。最適化をオンにしている場合はオフにしてください。この場合は、余分な出力を追加して呼び出しを表示し、境界を戻すことから始めます。'q9_draw_triangle(a + 1、b)'からの返り値によって起こった減分を考えると、前のaの束縛を復元します。これは、内側の呼び出しの束縛から1を減算するようなものです。 –

+0

「これが減少する」とはどういう意味ですか? – melpomene

答えて

1

再帰は、関数がそれ自身を呼び出すときで、最終的には関数の階層になります。再帰関数void func(int a)を定義すると、階層は次のようになります。いくつかの条件が満たされた後

func(1) 
    - func(2) 
     - func(3) 
      - ... 

、例えばA> 5のために、この関数は、初期返し、それを呼び出した関数(親関数)に戻ります。次に、親関数はコードが返るまでそのコードを実行し、親関数に戻ります。

再帰の動作の例については、グーグルで試してみてください。これは私が何が起こっているのかを説明するためのコードをコメントしました

https://www.codeproject.com/Articles/32873/Recursion-made-simple

を開始するには良い場所のように見えます。それは私にとって理にかなっていますが、あなたにもそれが意味をなされることを願っています。

void q9_draw_triangle(int a, int b) { 

    // this is our condition; this states when to stop the recursion 
    if (a > b) return; 

    // print current line 
    // this loop draws the horizontal lines 
    // if a = 3, then it will draw --- 
    for(int i = 0; i < a; i++){ 
     std::cout << "-"; 
    } 
    std::cout << std::endl; 

    // now that the current line was drawn, draw the next line 
    // so if a = 3, now in the next function a will be 4 
    // so the next function will print ----, which gives us an output of 
    // --- 
    // ---- 
    q9_draw_triangle(a+1,b); // this jumps back up to the top of the function and reruns the function with a+1 until a > b. 

    // once a > b, the functions return one by one and the follwoing loop is run 
    // in our example, a was 3 and then 4. If b was 4, then in our next iteration a would be 5, 
    // and the recursive function would simply return because a > b. 
    // this code is run once the child function returns. So a would be 4 again, printing ---- 
    // this gives an output of 
    // --- 
    // ---- 
    // ---- 
    for(int i = 0; i < a; i++){ 
     std::cout << "-"; 
    } 
    std::cout << std::endl; 
    // here the function retunrs again, so the we get back to the second loop 
    // and a will be 3 again. 
    // so the total output is 
    // --- 
    // ---- 
    // ---- 
    // --- 
} 
1

のは、そのため、各再帰レベル「sandwitches」の連続なもの。この構造はなり

print_block(a) 
     recursive_call(a+1, b) 
print_block(a) 

として、この関数の構造を見てみましょう。我々はa=1, b=2結果の呼び出しシーケンスを持っている場合、再帰が最も内側のコール任意の印刷または他の呼び出しなしa=3リターンを停止すると例えば

print_block(1) 
     print_block(2) 
       recursion stops: 3>2 
     print_block(2) 
print_block(1) 

だろう。コントロールは呼び出し元に渡され、a=2が印刷されて戻り、a=1に制御が渡され、元の呼び出し元(おそらくmain)に返されます。 aが減少するように見える理由を見ることができます。逆順で再帰から外れています。