C語言-第36課 - 函數遞歸與函數設計技巧
第36課 - 函數遞歸與函數設計技巧
一. 遞歸
- 遞歸概述
(1) 遞歸是數學領域中的概念在程序設計中的應用。
(2) 遞歸是一種強有力的程序設計的方法。
(3) 遞歸的本質為函數內部在適當的時候調用自身。
- 組成部分
(1)遞歸點:以不同參數調用自身。
(2)出口:不在遞歸調用
下面就是求一個數的階乘的函數:
#include <stdio.h>
int func(int x)
{
if( x > 1 )
{
return x * func(x - 1); //遞歸點
}
else
{
return 1; //出口
}
}
int main()
{
printf("x! = %d\n", func(4));
return 0;
}
運行結果:4!= 24
雖說調用了一次,卻創建了4次活動記錄。所以說我們的遞歸函數不能遞歸太多的層次。
小結:
C語言中的遞歸函數必然會使用判斷語句。
遞歸函數在需要編寫的時候定義函數的出口,否則棧會溢出。
遞歸函數是一種分而治之的思想。
思考題:編寫一個函數打印一個字符數組的全排列。
void Permutation(char *pStr,char *pBegin)
{
assert(pStr&&pBegin);
if(*pBegin == ‘\0‘)
printf("%s\n",pStr);
else
{
for(char *pCh=pBegin; *pCh !=‘\0‘; pCh++)
{
char temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
Permutation(pStr, pBegin+1);
temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
}
}
}
二. 函數的設計技巧
- 不要在函數中使用全局變量,盡量讓函數從意義上是一個獨立的功能模塊。
- 參數名要能夠體現參數的意義。
void str_copy(char *str1, char *str2);
void str_copy(char *str_dest, char *str_src);
- 如果函數是指針,且僅作為輸入參數用,則應在類型前加const,以防止該指針在函數體內被意外修改。
void str_copy(char *str_dest, const char *str_src);
- 不要省略返回值的類型,如果函數沒有返回值,那麽應該聲明為void類型。
- 在函數體的“入口處”,對參數的有效性進行檢查,對指針的檢查尤為重要。
- 語句不可返回指向“棧內存”的“指針”,因為該內存在函數體結束時被自動銷毀。
- 函數體的規模小,盡量要控制在80行代碼之內。
- 相同的輸入應當產生相同的輸出,盡量避免函數帶有“記憶”功能。
- 避免函數有太多的參數,參數的個數盡量控制在4個以內。
- 有時候函數不需要返回值,但是為了增加靈活性,加支持鏈式表達,可以附加返回值:
char s[64];
int len = strlen(strcpy(s,”android”));
- 函數名與返回值類型在語義上不可以沖突
char c;
c = getchar(); //getchar的返回值是int不是char。
if(EOF==c) //會出錯,永遠不會進入。
{ //... }
C語言-第36課 - 函數遞歸與函數設計技巧