2017-10-01 9 views
0

dekrementiert Ich bin nur mit rekursiven Funktionen starten und wissen eine einige, wie C++ funktioniert, aber ich verstehe wirklich nicht, wie dieser Code funktioniert:(C++) rekursive Funktion - weiß nicht, warum diese

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; 

    } 

Ich bekomme, wie die obere Hälfte funktioniert, von q9_draw_triangle (a + 1, b) und höher, aber nicht die letzte für die Schleife. Als ich mit Hilfe eines Debuggers diesen Code durchging, sprang er nach dem Auftreten von a> b zur letzten schließenden Klammer, dann zur letzten for-Schleife und zeichnete dann die zweite Hälfte des Dreiecks und dekrementierte sich wieder auf den Anfangswert . Ich habe keine Ahnung, warum das passiert ist oder wie man dies zu dekrementieren wusste.

EDIT: Nur für den Fall, dass weitere Klärung erforderlich ist, sagen meine Eingaben waren a = 3 und b = 7. Der erste Teil von q9_draw_triangle (a + 1, b) und oben würde 3 Linien zeichnen, dann 4,5, 6,7. Dann geht es zur letzten schließenden Klammer und dann zur letzten Schleife und zieht 7; zurück zur letzten schließenden Klammer, zurück zur for-Schleife und ziehe 6, dann wiederhole für 5,4,3. Warum macht es das? Es geht nie wieder über die letzte for-Schleife hinaus und dekrementiert sich selbst, und das verstehe ich nicht. Wenn es dann zu a = 3 kommt, tritt es schließlich aus der Funktion heraus, woher weiß es das zu tun?

Jede Hilfe zum Verständnis wird geschätzt!

+0

Ich würde vorsichtig sein, was hier im Debugger passiert, vor allem, wenn die Optimierung eingeschaltet ist. Moderne Compiler können Code erheblich neu anordnen und es kann ein gutes Stück Nachdenken erfordern, um zu rekonstruieren, was selbst erfahrenen Programmierern passiert. Wenn Sie die Optimierung aktiviert haben, versuchen Sie, sie auszuschalten, aber für diesen Fall würde ich mit einer zusätzlichen Ausgabe beginnen, um den Anruf anzuzeigen und die Grenzen zurückzugeben.Sie können sich das Dekrement vorstellen, das durch die Rückkehr von 'q9_draw_triangle (a + 1, b)' entsteht, wobei die vorherige Bindung von a wiederhergestellt wird, was dem Subtrahieren von 1 von der Bindung des inneren Aufrufs entspricht. –

+0

Was meinst du mit "das dekrementiert"? – melpomene

Antwort

1

Rekursion ist, wenn eine Funktion sich selbst aufruft, so dass Sie mit einer Hierarchie von Funktionen enden. Wenn ich eine rekursive Funktion void func (int a) definieren würde, würde die Hierarchie so aussehen.

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

Nach einiger Bedingung erfüllt ist, zum Beispiel a> 5, dann gibt der Funktion vorzeitig und kehrt zu der Funktion, die sie (die übergeordnete Funktion) genannt. Dann führt die Elternfunktion ihren Code aus, bis sie zurückkehrt, wodurch sie zu ihrer Elternfunktion zurückkehrt, und so weiter.

Für Beispiele, wie Rekursion funktioniert, googlen Sie es. Das sieht aus wie ein guter Anfang

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

Ich habe den Code kommentiert zu erklären, was los ist. Es macht Sinn für mich, aber ich hoffe, es wird auch für Sie Sinn machen.

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

Lasst uns die Struktur dieser Funktion als

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

Diese Struktur sehen macht, so dass jede Rekursionstiefe „Sandwichs“, die aufeinander. Zum Beispiel, wenn wir a=1, b=2 die resultierende Aufrufsequenz haben

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

werden, wenn die Rekursion den innersten Anruf a=3 kehrt ohne Druck oder andere Anrufe beendet. Das Steuerelement wird dann an seinen Aufrufer übergeben, der a=2 ist, der drucken und zurückgeben wird, Steuerelement an a=1 übergibt, das druckt und zu dem ursprünglichen Aufrufer (wahrscheinlich main) zurückkehrt. Sie können dann sehen, warum a zu sinken scheint: Wir durchlaufen jetzt die Rekursion in umgekehrter Reihenfolge.

Verwandte Themen