函數”這個名詞是從英文function翻譯過來的,其實function的原意是“功能”。顧名思義,一個函數就是一個功能。
在實際應用的程序中,主函數寫得很簡單,它的作用就是調用各個函數,程序各部分的功能全部都是由各函數實現的。主函數相當於總調度,調動各函數依次實現各項功能。
開發商和軟件開發人員將一些常用的功能模塊編寫成函數,放在函數庫中供公共選用。程序開發人員要善於利用庫函數,以減少重復編寫程序段的工作量。
例3.1】在主函數中調用其他函數。
#includeusing namespace std; void printstar(void) //定義printstar函數 { cout<<″****************************** ″< 運行情況如下:
******************************
Welcome to C++!
******************************
從用戶使用的角度看,函數有兩種:系統函數,即庫函數。這是由編譯系統提供的,用戶不必自己定義這些函數,可以直接使用它們。用戶自己定義的函數。用以解決用戶的專門需要。
從函數的形式看,函數分兩類:無參函數。調用函數時不必給出參數。有參函數。在調用函數時,要給出參數。在主調函數和被調用函數之間有數據傳遞。
C++函數的定義和調用
定義無參函數的一般形式為:
類型標識符 函數名([void])
{
聲明部分
語句
}
例3.1中的printstar和print_message函數都是無參函數,用類型標識符指定函數的類型,即函數帶回來的值的類型。
定義有參函數的一般形式為:
類型標識符 函數名(形式參數表列)
{
聲明部分
語句
}
例如:
int max(int x,int y) //函數首部,函數值為整型,有兩個整型形參 { int z; //函數體中的聲明部分 z=x>y?x:y; //將x和y中的大者的值賦給整型變量z return (z);//將z的值作為函數值返回調用點 }
C++函數參數和返回值
形式參數和實際參數
在調用函數時,大多數情況下,函數是帶參數的。主調函數和被調用函數之間有數據傳遞關系。前面已提到:在定義函數時函數名後面括號中的變量名稱為形式參數(formal parameter,簡稱形參),在主調函數中調用一個函數時,函數名後面括號中的參數(可以是一個表達式)稱為實際參數(actual parameter,簡稱實參)。
【例3.2】調用函數時的數據傳遞。
#includeusing namespace std; int max(int x,int y) //定義有參函數max { int z; z=x>y?x:y; return(z); } int main( ) { int a,b,c; cout<<"please enter two integer numbers:"; cin>>a>>b; c=max(a,b);//調用max函數,給定實參為a,b。函數值賦給c cout<<"max="< 運行情況如下:
please enter two integer numbers:2 3↙
max=3
有關形參與實參的說明:
1) 在定義函數時指定的形參,在未出現函數調用時,它們並不占內存中的存儲單元,因此稱它們是形式參數或虛擬參數,表示它們並不是實際存在的數據,只有在發生函數調用時,函數max中的形參才被分配內存單元,以便接收從實參傳來的數據。在調用結束後,形參所占的內存單元也被釋放。
2) 實參可以是常量、變量或表達式,如max(3, a+b);但要求a和b有確定的值。以便在調用函數時將實參的值賦給形參。
3) 在定義函數時,必須在函數首部指定形參的類型(見例3.2程序第3行)。
4) 實參與形參的類型應相同或賦值兼容。例3.2中實參和形參都是整型,這是合法的、正確的。如果實參為整型而形參為實型,或者相反,則按不同類型數值的賦值規則進行轉換。例如實參a的值為3.5,而形參x為整型,則將3.5轉換成整數3,然後送到形參b。字符型與整型可以互相通用。
5) 實參變量對形參變量的數據傳遞是“值傳遞”,即單向傳遞,只由實參傳給形參,而不能由形參傳回來給實參。在調用函數時,編譯系統臨時給形參分配存儲單元。
請注意:實參單元與形參單元是不同的單元。圖3.3表示將實參a和b的值2和3傳遞給對應的形參x和y。
調用結束後,形參單元被釋放,實參單元仍保留並維持原值。因此,在執行一個被調用函數時,形參的值如果發生改變,並不會改變主調函數中實參的值。例如,若在執行max函數過程中形參x和y的值變為10和15,調用結束後,實參a和b仍為2和3,見圖4.4。函數的返回值
1) 函數的返回值是通過函數中的return語句獲得的。return語句將被調用函數中的一個確定值帶回主調函數中去。
return語句後面的括號可以要,也可以不要。return後面的值可以是一個表達式。
2) 函數值的類型。既然函數有返回值,這個值當然應屬於某一個確定的類型,應當在定義函數時指定函數值的類型。
3) 如果函數值的類型和return語句中表達式的值不一致,則以函數類型為准,即函數類型決定返回值的類型。對數值型數據,可以自動進行類型轉換。
C++函數的調用及函數原型
函數調用的一般形式
函數調用的一般形式為:
函數名([實參表列]);
如果是調用無參函數,則“實參表列”可以沒有,但括號不能省略。如果實參表列包含多個實參,則各參數間用逗號隔開。實參與形參的個數應相等,類型應匹配(相同或賦值兼容)。實參與形參按順序對應,一對一地傳遞數據。但應說明,如果實參表列包括多個實參,對實參求值的順序並不是確定的。
函數調用的方式
按函數在語句中的作用來分,可以有以下3種函數調用方式: 函數語句
把函數調用單獨作為一個語句,並不要求函數帶回一個值,只是要求函數完成一定的操作。如例3.1中的printstar( );函數表達式
函數出現在一個表達式中,這時要求函數帶回一個確定的值以參加表達式的運算。如c=2*max(a, b);函數參數
函數調用作為一個函數的實參。如:
m=max(a, max(b, c)); //max(b, c)是函數調用,其值作為外層max函數調用的一個實參
對被調用函數的聲明和函數原型
在一個函數中調用另一個函數(即被調用函數)需要具備以下條件: 首先被調用的函數必須是已經存在的函數。如果使用庫函數,一般還應該在本文件開頭用#include命令將有關頭文件“包含”到本文件中來。如果使用用戶自己定義的函數,而該函數與調用它的函數(即主調函數)在同一個程序單位中,且位置在主調函數之後,則必須在調用此函數之前對被調用的函數作聲明。
所謂函數聲明(declare),就是在函數尚在未定義的情況下,事先將該函數的有關信息通知編譯系統,以便使編譯能正常進行。
【例3.3】對被調用的函數作聲明。
#includeusing namespace std; int main( ) { float add(float x,float y); //對add函數作聲明 float a,b,c; cout<<"please enter a,b:"; cin>>a>>b; c=add(a,b); cout<<"sum="< 運行情況如下:
please enter a, b: 123.68 456.45↙
sum=580.13
注意:對函數的定義和聲明不是同一件事情。定義是指對函數功能的確立,包括指定函數名、函數類型、形參及其類型、函數體等,它是一個完整的、獨立的函數單位。而聲明的作用則是把函數的名字、函數類型以及形參的個數、類型和順序(注意,不包括函數體)通知編譯系統,以便在對包含函數調用的語句進行編譯時,據此對其進行對照檢查(例如函數名是否正確,實參與形參的類型和個數是否一致)。
其實,在函數聲明中也可以不寫形參名,而只寫形參的類型,如
float add(float, float);
這種函數聲明稱為函數原型(function prototype)。使用函數原型是C和C++的一個重要特點。它的作用主要是: 根據函數原型在程序編譯階段對調用函數的合法性進行全面檢查。如果發現與函數原型不匹配的函數調用就報告編譯出錯。它屬於語法錯誤。用戶根據屏幕顯示的出錯信息很容易發現和糾正錯誤。
函數原型的一般形式為:
函數類型 函數名(參數類型1, 參數類型2…);
或
函數類型 函數名(參數類型1 參數名1, 參數類型2 參數名2…);
第(1)種形式是基本的形式。為了便於閱讀程序,也允許在函數原型中加上參數名,就成了第(2)種形式。但編譯系統並不檢查參數名。因此參數名是什麼都無所謂。上面程序中的聲明也可以寫成
float add(float a, float b); //參數名不用x、y,而用a、b
效果完全相同。
應當保證函數原型與函數首部寫法上的一致,即函數類型、函數名、參數個數、參數類型和參數順序必須相同。在函數調用時函數名、實參類型和實參個數應與函數原型一致。
兩點說明:
1) 前面已說明,如果被調用函數的定義出現在主調函數之前,可以不必加以聲明。因為編譯系統已經事先知道了已定義的函數類型,會根據函數首部提供的信息對函數的調用作正確性檢查。
有經驗的程序編制人員一般都把main函數寫在最前面,這樣對整個程序的結構和作用一目了然,統覽全局,然後再具體了解各函數的細節。此外,用函數原型來聲明函數,還能減少編寫程序時可能出現的錯誤。由於函數聲明的位置與函數調用語句的位置比較近,因此在寫程序時便於就近參照函數原型來書寫函數調用,不易出錯。所以應養成對所有用到的函數作聲明的習慣。這是保證程序正確性和可讀性的重要環節。
2) 函數聲明的位置可以在調用函數所在的函數中,也可以在函數之外。如果函數聲明放在函數的外部,在所有函數定義之前,則在各個主調函數中不必對所調用的函數再作聲明。例如:
char letter(char, char); //本行和以下兩行函數聲明在所有函數之前且在函數外部
float f(float, float); //因而作用域是整個文件
int i(float, float);
int main( )
{…}//在main函數中不必對它所調用的函數作聲明
char letter(char c1, char c2) //定義letter函數
{…}
float f(float x, float y)//定義f函數
{…}
int i(float j, float k) //定義i函數
{…}
如果一個函數被多個函數所調用,用這種方法比較好,不必在每個主調函數中重復聲明。C++內置函數(內嵌函數,內聯函數)
調用函數時需要一定的時間和空間的開銷。
C++提供一種提高效率的方法,即在編譯時將所調用函數的代碼直接嵌入到主調函數中,而不是將流程轉出去。這種嵌入到主調函數中的函數稱為內置函數(inline function),又稱內嵌函數。在有些書中把它譯成內聯函數。
指定內置函數的方法很簡單,只需在函數首行的左端加一個關鍵字inline即可。
【例3.4】函數指定為內置函數。
#includeusing namespace std; inline int max(int, int, int); //聲明函數, 注意左端有inline int main( ) { int i=10, j=20, k=30, m; m=max(i, j, k); cout<<"max="< a) a=b;//求a, b, c中的最大者 if(c>a) a=c; return a; }
由於在定義函數時指定它為內置函數,因此編譯系統在遇到函數調用“max(i, j, k)”時,就用max函數體的代碼代替“max(i,j, k)”,同時將實參代替形參。這樣,程序第6行 “m=max(i, j, k);”就被置換成
if (j>i) i=j;
if(k>i) i=k;
m=i;
注意:可以在聲明函數和定義函數時同時寫inline,也可以只在其中一處聲明inline,效果相同,都能按內置函數處理。
使用內置函數可以節省運行時間,但卻增加了目標程序的長度。因此一般只將規模很小(一般為5個語句以下)而使用頻繁的函數(如定時采集數據的函數)聲明為內置函數。
內置函數中不能包括復雜的控制語句,如循環語句和switch語句。
應當說明:對函數作inline聲明,只是程序設計者對編譯系統提出的一個建議,也就是說它是建議性的,而不是指令性的。並非一經指定為inline,編譯系統就必須這樣做。編譯系統會根據具體情況決定是否這樣做。
歸納起來,只有那些規模較小而又被頻繁調用的簡單函數,才適合於聲明為inline函數。
C++函數重載
在編程時,有時我們要實現的是同一類的功能,只是有些細節不同。例如希望從3個數中找出其中的最大者,而每次求最大數時數據的類型不同,可能是3個整數、3個雙精度數或3個長整數。程序設計者往往會分別設計出3個不同名的函數,其函數原型為:
int max1(int a, int b, int c); //求3個整數中的最大者
double max2(double a, double b, double c); //求3個雙精度數中最大者
long max3(long a, long b, long c); //求3個長整數中的最大者
C++允許用同一函數名定義多個函數,這些函數的參數個數和參數類型不同。這就是函數的重載(function overloading)。即對一個函數名重新賦予它新的含義,使一個函數名可以多用。
對上面求最大數的問題可以編寫如下的C++程序。
【例3.5】求3個數中最大的數(分別考慮整數、雙精度數、長整數的情況。
#includeusing namespace std; int main( ) { int max(int a,int b,int c); //函數聲明 double max(double a,double b,double c); //函數聲明 long max(long a,long b,long c);//函數聲明 int i1,i2,i3,i; cin>>i1>>i2>>i3; //輸入3個整數 i=max(i1,i2,i3); //求3個整數中的最大者 cout<<"i_max="<>d1>>d2>>d3; //輸入3個雙精度數 d=max(d1,d2,d3); //求3個雙精度數中的最大者 cout<<"d_max="< >g1>>g2>>g3; //輸入3個長整數 g=max(g1,g2,g3); //求3個長整數中的最大者 cout<<"g_max="< a) a=b; if(c>a) a=c; return a; } double max(double a,double b,double c)//定義求3個雙精度數中的最大者的函數 { if(b>a) a=b; if(c>a) a=c; return a; } long max(long a,long b,long c) //定義求3個長整數中的最大者的函數 { if(b>a) a=b; if(c>a) a=c; return a; }
運行情況如下:
185-76567↙ (輸入3個整數)
56.87 90.23 -3214.78↙ (輸入3個實數)
67854 -912456 673456↙ (輸入3個長整數)
i_max=567 (輸出3個整數的最大值)
d_max=90.23 (輸出3個雙精度數的最大值)
g_max=673456 (輸出3個長整數的最大值)
上例3個max函數的函數體是相同的。
其實重載函數並不要求函數體相同;除了允許參數類型不同以外,還允許參數的個數不同。
【例3.6】編寫一個程序,用來求兩個整數或3個整數中的最大數。如果輸入兩個整數,程序就輸出這兩個整數中的最大數,如果輸入3個整數,程序就輸出這3個整數中的最大數。
#includeusing namespace std; int main( ) { int max(int a,int b,int c); //函數聲明 int max(int a,int b); //函數聲明 int a=8,b=-12,c=27; cout<<"max(a,b,c)="< a) a=b; if(c>a) a=c; return a; } int max(int a,int b)//此max函數的作用是求兩個整數中的最大者 { if(a>b) return a; else return b; }
運行情況如下:
max(a, b, c)=27
max(a, b)=8
兩次調用max函數的參數個數不同,系統就根據參數的個數找到與之匹配的函數並調用它。
參數的個數和類型可以都不同。但不能只有函數的類型不同而參數的個數和類型相同。例如:
int f(int); //函數返回值為整型
long f(int); //函數返回值為長整型
void f(int); //函數無返回值
在函數調用時都是同一形式,如“f(10)”。編譯系統無法判別應該調用哪一個函數。重載函數的參數個數、參數類型或參數順序3者中必須至少有一種不同,函數返回值類型可以相同也可以不同。
在使用重載函數時,同名函數的功能應當相同或相近,不要用同一函數名去實現完全不相干的功能,雖然程序也能運行,但可讀性不好,使人莫名其妙。
C++函數模板
C++提供了函數模板(function template)。所謂函數模板,實際上是建立一個通用函數,其函數類型和形參類型不具體指定,用一個虛擬的類型來代表。這個通用函數就稱為函數模板。凡是函數體相同的函數都可以用這個模板來代替,不必定義多個函數,只需在模板中定義一次即可。在調用函數時系統會根據實參的類型來取代模板中的虛擬類型,從而實現了不同函數的功能。看下面的例子就清楚了。
【例3.7】將例3.6程序改為通過函數模板來實現。
#includeusing namespace std; template //模板聲明,其中T為類型參數 T max(T a,T b,T c) //定義一個通用函數,用T作虛擬的類型名 { if(b>a) a=b; if(c>a) a=c; return a; } int main( ) { int i1=185,i2=-76,i3=567,i; double d1=56.87,d2=90.23,d3=-3214.78,d; long g1=67854,g2=-912456,g3=673456,g; i=max(i1,i2,i3); //調用模板函數,此時T被int取代 d=max(d1,d2,d3); //調用模板函數,此時T被double取代 g=max(g1,g2,g3); //調用模板函數,此時T被long取代 cout<<"i_max="<運行結果與例3.5相同。為了節省篇幅,數據不用cin語句輸入,而在變量定義時初始化。程序第3~8行是定義模板。
定義函數模板的一般形式為:
template < typename T>
通用函數定義 通用函數定義
或
template
通用函數定義 通用函數定義
在建立函數模板時,只要將例3.5程序中定義的第一個函數首部的int改為T即可。即用虛擬的類型名T代替具體的數據類型。在對程序進行編譯時,遇到第13行調用函數max(i1, i2, i3),編譯系統會將函數名max與模板max相匹配,將實參的類型取代了函數模板中的虛擬類型T。此時相當於已定義了一個函數:
int max(int a, int b, int c) { if(b>a) a=b; if(c>a) a=c; return a; }然後調用它。後面兩行(14,15行)的情況類似。
類型參數可以不只一個,可以根據需要確定個數。如:
template
可以看到,用函數模板比函數重載更方便,程序更簡潔。但應注意它只適用於函數的參數個數相同而類型不同,且函數體相同的情況,如果參數的個數不同,則不能用函數模板。
C++函數的默認參數
一般情況下,在函數調用時形參從實參那裡取得值,因此實參的個數應與形參相同。有時多次調用同一函數時用同樣的實參,C++提供簡單的處理辦法,給形參一個默認值,這樣形參就不必一定要從實參取值了。如有一函數聲明:
float area(float r=6.5);
指定r的默認值為6.5,如果在調用此函數時,確認r的值為6.5,則可以不必給出實參的值,如:
area( ); //相當於area(6.5);
如果不想使形參取此默認值,則通過實參另行給出。如:
area(7.5); //形參得到的值為7.5,而不是6.5
這種方法比較靈活,可以簡化編程,提高運行效率。
如果有多個形參,可以使每個形參有一個默認值,也可以只對一部分形參指定默認值,另一部分形參不指定默認值。如有一個求圓柱體體積的函數,形參h代表圓柱體的高,r為圓柱體半徑。函數原型如下:
float volume(float h, float r=12.5); //只對形參r指定默認值12.5
函數調用可以采用以下形式:
volume(45.6); //相當於volume(45.6,12.5)
volume(34.2, 10.4); //h的值為34.2,r的值為10.4
實參與形參的結合是從左至右順序進行的。因此指定默認值的參數必須放在形參表列中的最右端,否則出錯。例如:
void f1(float a, int b=0, int c, char d=′a′); //不正確
void f2(float a, int c, int b=0, char d=′a′); //正確
如果調用上面的f2函數,可以采取下面的形式:
f2(3.5, 5, 3, ′x′) //形參的值全部從實參得到
f2(3.5, 5, 3) //最後一個形參的值取默認值′a′
f2(3.5, 5) //最後兩個形參的值取默認值,b=0,d=′a′
可以看到,在調用有默認參數的函數時,實參的個數可以與形參的個數不同,實參未給定的,從形參的默認值得到值。利用這一特性,可以使函數的使用更加靈活。例如例3.7求2個數或3個數中的最大數。也可以不用重載函數,而改用帶有默認參數的函數。
【例3.8】求2個或3個正整數中的最大數,用帶有默認參數的函數實現。
#include運行情況如下:using namespace std; int main( ) { int max(int a, int b, int c=0);//函數聲明,形參c有默認值 int a,b,c; cin>>a>>b>>c; cout<<"max(a,b,c)="< a) a=b; if(c>a) a=c; return a; }
14 -56 135↙
max(a,b,c)=135
max(a,b)=14
在使用帶有默認參數的函數時有兩點要注意: 如果函數的定義在函數調用之前,則應在函數定義中給出默認值。如果函數的定義在函數調用之後,則在函數調用之前需要有函數聲明,此時必須在函數聲明中給出默認值,在函數定義時可以不給出默認值(如例3.8)。一個函數不能既作為重載函數,又作為有默認參數的函數。因為當調用函數時如果少寫一個參數,系統無法判定是利用重載函數還是利用默認參數的函數,出現二義性,系統無法執行。C++函數的嵌套調用
C++不允許對函數作嵌套定義,也就是說在一個函數中不能完整地包含另一個函數。在一個程序中每一個函數的定義都是互相平行和獨立的。
雖然C++不能嵌套定義函數,但可以嵌套調用函數,也就是說,在調用一個函數的過程中,又調用另一個函數。
在程序中實現函數嵌套調用時,需要注意的是:在調用函數之前,需要對每一個被調用的函數作聲明(除非定義在前,調用在後)。
【例3.9】用弦截法求方程f(x)=x3-5x2+16x-80=0的根。
這是一個數值求解問題,需要先分析用弦截法求根的算法。根據數學知識,可以列出以下的解題步驟:
1) 取兩個不同點x1,x2,如果f(x1)和f(x2)符號相反,則(x1,x2)區間內必有一個根。如果f(x1)與f(x2)同符號,則應改變x1,x2,直到f(x1), f(x2)異號為止。注意x1?x2的值不應差太大,以保證(x1,x2)區間內只有一個根。
2) 連接(x1, f(x1))和(x2, f(x2))兩點,此線(即弦)交x軸於x,見圖3.7。
圖 3.7
x點坐標可用下式求出:
再從x求出f(x)。
3) 若f(x)與f(x1)同符號,則根必在(x, x2)區間內,此時將x作為新的x1。如果f(x)與f(x2)同符號,則表示根在( x1,x)區間內,將x作為新的x2。
4) 重復步驟 (2) 和 (3), 直到 |f(x)|<ξ為止, ξ為一個很小的正數, 例如10-6。此時認為 f(x)≈0。
這就是弦截法的算法,在程序中分別用以下幾個函數來實現以上有關部分功能:
1) 用函數f(x)代表x的函數:x3-5x2+16x-80。
2) 用函數xpoint (x1,x2)來求(x1,f(x1))和(x2,f(x2))的連線與x軸的交點x的坐標。
3) 用函數root(x1,x2)來求(x1,x2)區間的那個實根。顯然,執行root函數的過程中要用到xpoint函數,而執行xpoint函數的過程中要用到f函數。
根據以上算法,可以編寫出下面的程序:
#include運行情況如下:#include #include using namespace std; double f(double); //函數聲明 double xpoint(double, double); //函數聲明 double root(double, double); //函數聲明 int main( ) { double x1,x2,f1,f2,x; do { cout<<"input x1,x2:"; cin>>x1>>x2; f1=f(x1); f2=f(x2); } while(f1*f2>=0); x=root(x1,x2); cout< 0) { y1=y; x1=x; } else x2=x; }while(fabs(y)>=0.00001); return x; }
input x1, x2:2.5 6.7↙
A root of equation is 5.0000000
對程序的說明:
1) 在定義函數時,函數名為f,xpoint和root的3個函數是互相獨立的,並不互相從屬。這3個函數均定為雙精度型。
2) 3個函數的定義均出現在main函數之後,因此在main函數的前面對這3個函數作聲明。
習慣上把本程序中用到的所有函數集中放在最前面聲明。
3) 程序從main函數開始執行。
4) 在root函數中要用到求絕對值的函數fabs,它是對雙精度數求絕對值的系統函數。它屬於數學函數庫,故在文件開頭用#include把有關的頭文件包含進來。
C++函數的遞歸調用
在調用一個函數的過程中又出現直接或間接地調用該函數本身,稱為函數的遞歸(recursive)調用。C++允許函數的遞歸調用。例如:
int f(int x) { int y, z; z=f(y); //在調用函數f的過程中,又要調用f函數 return (2*z); }以上是直接調用本函數,見圖3.9。
圖3.10表示的是間接調用本函數。在調用f1函數過程中要調用f2函數,而在調用f2函數過程中又要調用f1函數。
圖 3.9
圖3.10
從圖上可以看到,這兩種遞歸調用都是無終止的自身調用。顯然,程序中不應出現這種無終止的遞歸調用,而只應出現有限次數的、有終止的遞歸調用,這可以用if語句來控制,只有在某一條件成立時才繼續執行遞歸調用,否則就不再繼續。
包含遞歸調用的函數稱為遞歸函數。
【例3.10】有5個人坐在一起,問第5個人多少歲?他說比第4個人大兩歲。問第4個人歲數,他說比第3個人大兩歲。問第3個人,又說比第2個人大兩歲。問第2個人,說比第1個人大兩歲。最後問第1個人,他說是10歲。請問第5個人多大?
每一個人的年齡都比其前1個人的年齡大兩歲。即:
age(5)=age(4)+2
age(4)=age(3)+2
age(3)=age(2)+2
age(2)=age(1)+2
age(1)=10
可以用式子表述如下:
age(n)=10 (n=1)
age(n)=age(n-1)+2 (n>1)
可以看到,當n>1時,求第n個人的年齡的公式是相同的。因此可以用一個函數表示上述關系。圖3.11表示求第5個人年齡的過程。
圖 3.11
可以寫出以下C++程序,其中的age函數用來實現上述遞歸過程。
#include運行結果如下:using namespace std; int age(int);//函數聲明 int main( )//主函數 { cout<1時,此人年齡是他前一個人的年齡加2 return c; //將年齡值帶回主函數 }
18
【例3.11】用遞歸方法求n!。
求n!可以用遞推方法,即從1開始,乘2,再乘3……一直乘到n。求n!也可以用遞歸方法,即5!=4!×5,而4!=3!×4,…,1!=1。可用下面的遞歸公式表示:
n! = 1 (n=0, 1)
n * (n-1)! (n>1)
有了例3.10的基礎,很容易寫出本題的程序:
#include運行情況如下:using namespace std; long fac(int);//函數聲明 int main( ) { int n;//n為需要求階乘的整數 long y; //y為存放n!的變量 cout<<"please input an integer :"; //輸入的提示 cin>>n; //輸入n y=fac(n);//調用fac函數以求n! cout< 1時,進行遞歸調用 return f;//將f的值作為函數值返回 }
please input an integer:10↙
10!=3628800
許多問題既可以用遞歸方法來處理,也可以用非遞歸方法來處理。在實現遞歸時,在時間和空間上的開銷比較大,但符合人們的思路,程序容易理解。