簡體   English   中英

C語言中的遞歸流程以及如何打印輸出

[英]Recursion flow in c language and how the output is printed

我的印刷價值如何?

我知道遞歸一次又一次地調用自己。 據我說,該函數應該返回空值,因為在打印之前調用了該函數。 printf如何工作?

recur(int i)
{
  if(i<0)
    return 0;
  recur(--i);
  printf("%d",i);
  recur(--i);
}

main()
{
  recur(2);
}

The output of this program is 
-1
0
1
-1

有人可以解釋它是如何工作的嗎?

要了解會發生什么,您必須了解遞歸如何工作。 每個遞歸函數都需要一個測試條件來中斷遞歸和一個遞歸調用。 您將if (i < 0)作為測試條件,然后進行兩次遞歸調用,並在它們之間進行printf調用。

那么這是如何工作的呢?

您可以考慮遞歸和結束操作,直到觸發退出條件為止-然后隨着遞歸調用的返回而放松。 讓我們在這里看看它是如何工作的。

遞歸

當您從main recur(2)開始時,邏輯采用哪種路徑結束退出狀態?

如果簡化功能並專注於滿足測試條件之前發生的情況,您將獲得類似於以下內容的信息:

void recur (int i) {
    if (i < 0)
        return;
    recur (--i);
    /* comes after return */
}

讓我們繼續進行下去。 在第一次調用, i = 2 ,以便--1 預decriment發生使i = 1recur (1)執行。 下次調用i = 0recur (0)調用recur (0) 最后, i = -1 ,並且出現第一個recur(-1) ,因此if (i < 0)執行if (i < 0)並調用return

怎么辦? -正在放松...

請看上面的簡化功能。 當您return ,您將從對recur(--i)的最后一次調用return ,因此控制權現在在第一個recur(-1)之后傳遞給下一個命令(顯示為/* comes after return */ )完整功能中的下一個命令?

    printf("%d\n", i);
    recur (--i);

第一次出現時, i的值是多少? (提示: -1 )。

所以調用了printf ,然后接下來呢? 您的第二次recur(--i) i = -2if (i < 0) return; 觸發,您退出第二個recur(-2) -沒有后續命令,並且該函數調用現已完成。

現在,控制權退回到上一個調用,其中i現在為0 ,調用printf ,並使用i = -1輸入第二個recur(--i) ,只需再次按return然后再return一個級別到i = 1從第一個recur(--i)調用再次返回,將輸出1

輸入第二個recur(--i)調用,在遞減i = 0 ,您現在又遞歸到第一個i = -1再次觸發return ,這導致contol在最終-1打印時傳遞給printf

現在,您以i = -2觸發第二個recur(--i)觸發return並完成函數調用和遞歸。

因此,如果您通過兩次遞歸調用返回到遞歸函數的控件,並查看每次到達printf ,您將輸出-1, 0, 1, -1

仍然認為具有多個遞歸調用的遞歸函數是一個好主意嗎?

(如果您是阿司匹林推銷員,則可能會出現這種情況,否則,最好避免使用它們,除非它們是您唯一合理的選擇)

進行此類操作的唯一方法是(1)與調試器交朋友,並單步執行代碼,以保留在調用時輸入了便箋的草稿,或者(2)將函數復制並粘貼到頁面下方在每個級別上跟蹤遞歸調用的狀態,並逐步進行。

始終是良好的學習經驗,但是如果有過程解決方案可用,則邏輯會更加簡單明了,並且可以避免每次遞歸調用的函數調用開銷。 遞歸函數占有一席之地,並且為某些問題提供了非常優雅的解決方案。 但是您必須注意,每次調用時都會為局部變量分配一個單獨的函數堆棧和空間,遞歸將發生多少次,這可能會導致StackOverflow。

當您調用recur(2); ,此時

recur(--i);

調用recur(1) ,然后再次到達該點時,調用recur(0); 被調用,然后再次調用recur(-1); 叫做。 recur(-1); 調用立即返回,因為if(i<0) return 0;

recur(0); 調用,其中i現在為-1 ,然后執行打印並返回(它的確recur(--i);但這時為-2 )。 接下來, recur(1)調用(現在i0 )進行打印,並且recur(1) ,該返回。

最后,原始recur(2); 調用(其中i為1)打印並調用另一個recur(0); ,如我們所見,導致-1被打印。 這將導致輸出-101-1 ,或者如果您向每個打印添加換行符,則將看到輸出。

附帶一提,我建議您將主要功能編寫為

int main()
{
    recur(2);
    return 0; // return value of 0 indicates successful program execution
}

並將recur(int i)的簽名更改為void recur(int i)return 0; return;

根據我的說法,該函數應該在打印前調用該函數時返回空值。 printf是如何工作的?

總結起來,它之所以有用,是因為並非所有的遞歸調用都在做進一步的遞歸調用。 他們僅在某些條件下執行遞歸調用,如果不執行該遞歸調用,它們將在某個時刻結束,從而允許調用它的函數繼續。

問題是您在打印出該值之前正在調用函數。

recur(int i)
{
if(i<0)
    return 0;
recur(--i);
printf("%d",i);
recur(--i);
}

您正在main函數中調用recur(2) ,因為i=2所以第一個if(i<0)不返回0。 然后使用值1 recur(1)調用函數recur

在這種情況下, if(i<0)也不會返回0,因為i=1不是函數recur(0)被調用為0。

if(i<0)仍然不返回0,因為i=0並且您的函數被recur(-1)調用。

然后,由於i=-1 if(i<0) returns 0

現在我們開始print()輸出我們之前給函數的值。 那個是print(-1)因為它是我們函數擁有的最后一個值。

然后,我們再次使用recur(-2)調用recur,並且if返回0。

然后我們print(0)因為那是我們“輸入”的第二個值是0。

然后我們用recur(-1)調用recur,而if(i<0)返回0。

接下來是下一個值。

對於將來的問題,我建議您使用調試器。 例如,GDB調試器。

這就像gdb 入門GDB Start guid

我希望這可以幫助你。

當使用參數X >=零調用該函數時,將執行以下行:

recur(X-1)
print X-1
recur(X-2)
return

當使用參數X < 0調用該函數時,僅執行以下行:

return

現在,如果您為每個調用級別編寫帶有一些縮進的函數調用,則會得到:

recur(2)
        recur(1)
                recur(0)
                        recur(-1)
                                return
                        print -1
                        recur(-2)
                                return
                        return
                print 0
                recur(-1)
                        return
                return
        print 1
        recur(0)
                recur(-1)
                        return
                print -1
                recur(-2)
                        return
                return
        return
return

除去打印件以外的所有內容,可以得到:

                        print -1
                print 0
        print 1
                print -1

所以輸出是:

-1
0
1
-1

還考慮

您正在使用的變量是自動變量,因此自動變量的值受全景模型的限制,因此程序將打印控制流當前所在的寄生模型中可用的i的值

請勿執行recur(i-1) recur(--i) ,請執行recur(i-1)

使用--i實際上會減少i ,因此在以后的printf它將(不正確)可見。

例如。 如果i0和你recur(--i) ,它會降低實際值的i-1 ,然后調用recur() 並且printf將在以后打印-1

使用recur(i-1)i0 ,將以-1作為參數調用,但i的實際值不會更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM