誰能解釋一下,為什么每行從1到h都要列印標簽。因為根據我的理解,這個函式在for回圈之前就在呼叫自己,它根本就不應該列印。如果我把函式呼叫移到for回圈下面,那么它每行就會從h列印到1。
void draw (int h)
{
if(h == 0)
{
return;
}
draw(h - 1)。
for(int i = 0; i < h; i)
{
std::cout << "#"/span>;
}
std::cout<<std::endl;
}
uj5u.com熱心網友回復:
當函式draw被呼叫時,它的資訊(變數的值、代碼段等)被推到一個堆疊中。這個堆疊隨著你的遞回呼叫而越來越大。例如,draw(5)的堆疊將是draw(5)、draw(4),以此類推,draw(5)位于遞回堆疊的底部。
現在為了避免無限的遞回呼叫,你的條件(h == 0)作為一個基本情況。
一旦達到基本情況,函式draw(0)就會終止,并從遞回堆疊的頂部彈出。現在,先前的程式以LIFO(后進先出)的順序從堆疊中彈出,并繼續執行,其中包括for回圈的列印輸出。
例如,第一個列印輸出將是一個#。這是由于遞回呼叫draw(1)在基例draw(0)終止后在堆疊中的下一個。請記住,draw(1)的引數h的值仍然是1,這導致了那個單一的#列印輸出。一旦draw(1)執行完畢,draw(2)就會接手,列印出兩個#,以此類推。
為了直觀地看到這個遞回,你可以在draw函式中利用更多的列印內容來讓你了解遞回呼叫的順序,但是我強烈建議你熟悉使用除錯器來瀏覽你的C 代碼并清楚地看到遞回。
uj5u.com熱心網友回復:
我發現 "替換法 "常常能讓人明白。
我們來看看 "替換法"。
讓我們看一個較小的例子,draw(2)。
在函式體中用2替換h,得到
if(2 ==0)
{
return;
}
draw(2 - 1) 。
for(int i = 0; i < 2; i)
{
std::cout << "#";
}
std::cout<<std::endl。
由于第一個條件是假的,我們必須先做draw(1),然后才能繼續進行回圈。
再次代入可以得到
if(1 ==0)
{
return;
}
draw(1 - 1) 。
for(int i = 0; i < 1; i)
{
std::cout << "#";
}
std::cout<<std::endl。
第一個條件仍然是假的,所以我們需要draw(0):
if(0 ==0)
{
return;
}
draw(0 - 1) 。
for(int i = 0; i < 0; i)
{
std::cout << "#"/span>;
}
std::cout<<std::endl。
現在第一個條件為真,所以我們不做任何事情就回傳,可以繼續進行draw(1)中的回圈:
for(int i = 0; i < 1; i)
{
std::cout << "#";
}
std::cout<<std::endl。
這就列印了一個字符。
然后,我們回傳到draw(2)的回圈中:
for(int i = 0; i < 2; i)
{
std::cout << "#";
}
std::cout<<std::endl。
這就列印了兩個字符,我們就完成了。
你也可以通過用專門的函式來取代遞回來幫助你的推理:
void draw_0(){}。
void draw_1() { draw_0(); std: :cout << "#
";}
void draw_2(){ draw_1(); std: :cout << "###
";}
void draw_3() { draw_2(); std: :cout << "###
";}
void draw_4() { draw_3(); std: :cout << "####
";}
void draw_5() { draw_4(); std: :cout << "#####
然后考慮draw_5()會發生什么。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/306755.html
標籤:
