在數(shù)學(xué)中,函數(shù)是一種一一對應(yīng)的映射關(guān)系
在程序中,函數(shù)稱為子程序。
子程序是是一個大型程序中的某部分代碼, 由一個或多個語句塊組
成。它負(fù)責(zé)完成某項特定任務(wù),而且相較于其他代碼,具備相對的獨立性。
一般會有輸入?yún)?shù)并有返回值,==提供對過程的封裝和細(xì)節(jié)的隱藏。==這些代碼通常被集成為軟件庫。
為什么會有庫函數(shù)?
當(dāng)我們編寫代碼時,有時候需要做很多重復(fù)性的功能,比如在屏幕上打印一個東西,或者從鍵盤上輸入一個數(shù)據(jù),這種功能一開始是需要程序員自己實現(xiàn)的,但是每個人編寫的函數(shù)可能有差別,所以會導(dǎo)致標(biāo)準(zhǔn)不統(tǒng)一,于是C語言規(guī)定將常用的函數(shù)封裝在一起,這些函數(shù)叫做庫函數(shù)。
我們可以通過一些網(wǎng)站學(xué)習(xí)需要的庫函數(shù)
通常情況下,我們只需要學(xué)會常用的庫函數(shù)即可
- IO函數(shù)
- 字符串操作函數(shù)
- 字符操作函數(shù)
- 內(nèi)存操作函數(shù)
- 時間/日期函數(shù)
- 數(shù)學(xué)函數(shù)
- 其他庫函數(shù)
2.2 自定義函數(shù)只有庫函數(shù)是不夠的,比如我們自己需要重復(fù)的做求階乘這個動作,我們可以自己封裝一個函數(shù)專門用來求階乘,在我們需要用到的地方直接調(diào)用這個函數(shù)即可,自己定義的函數(shù)稱為自定義函數(shù)。
定義函數(shù)之前,我們需要了解一個函數(shù)長什么樣子
ret_type fun_name(paral_list)
{statement
}
//ret_type 函數(shù)返回值類型
//fun_name 函數(shù)名
//paral_list 函數(shù)參數(shù)列表
//statement 函數(shù)體
寫一個函數(shù)找出兩個數(shù)的大小值
#include//get_max函數(shù)的設(shè)計
int get_max(int x, int y) {return (x>y)?(x):(y);
}
int main()
{int num1 = 10;
int num2 = 20;
int max = get_max(num1, num2); //函數(shù)的返回值用max存起來
printf("max = %d\n", max);
return 0;
}
3. 函數(shù)參數(shù)
3.1 實際參數(shù)真實傳給函數(shù)的參數(shù),叫實參。
實參可以是:常量、變量、表達式、函數(shù)等。
無論實參是何種類型的量,在進行函數(shù)調(diào)用時,它們都必須有確定的值,以便把這些值傳送給形
參。
形式參數(shù)是指函數(shù)名后括號中的變量,因為形式參數(shù)只有在函數(shù)被調(diào)用的過程中才實例化(分配內(nèi)存單元),所以叫形式參數(shù)。形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動銷毀了。因此形式參數(shù)只在函數(shù)中有
效。
函數(shù)的參數(shù)是通過傳值的方式進行傳遞的,它實際所傳遞的是實參的一份拷貝,因此函數(shù)可以修改它的形參(也就是實參的拷貝)而不會修改調(diào)用程序世紀(jì)傳遞的參數(shù)
寫交換兩個數(shù)的函數(shù)
swap 函數(shù)
void swap1(int a, int b)
{int tmp;
tmp = a;
a = b;
b = tmp;
}
void swap2(int* pa, int* pb)
{int* tmp;
tmp = pa;
pa = pb;
pb = tmp;
}
void swap3(int* pa, int* pb)
{int tmp;
tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{int a = 1;
int b = 3;
swap1(a, b);
swap2(&a, &b);
swap3(&a, &b);
return 0;
}
上述三個函數(shù)只有第三個能完成交換任務(wù)
形參和實參所處不同的內(nèi)存
對于swap1,函數(shù)體只交換了地址3和地址4的兩個數(shù),對主函數(shù)的a,b無影響
對于swap2,pa,pb的值原本是地址1,地址2,交換后變成地址2,地址1.
并沒有交換a,b
對于swap3,pa,pb原本值是地址1,地址2,對pa,pb解引用找到主函數(shù)中的a,b
4. 函數(shù)調(diào)用
4.1 傳值調(diào)用傳值調(diào)用不能通過形參改變實參或與實參相關(guān)的數(shù)據(jù)
4.2 傳址調(diào)用寫一個函數(shù)每次調(diào)用這個函數(shù),讓num++
//Method1
#includeint num = 0;
void fun(int n)
{num++;
}
int main()
{for (int i = 0; i< 5; i++)
{fun(i);
printf("%d ", num);
}
return 0;
}
//Method2
int fun(int n)
{return n + 1;
}
int main()
{ int num = 0;
for (int i = 1; i<= 5; i++)
{num = fun(num);
printf("%d ", num);
}
return 0;
}
//Method3
void fun(int* p)
{(*p)++;
}
int main()
{int num = 0;
for (int i = 0; i< 5; i++)
{fun(&num);
printf("%d ", num);
}
return 0;
}
5. 函數(shù)的嵌套調(diào)用和鏈?zhǔn)皆L問函數(shù)和函數(shù)之間可以根據(jù)實際的需求進行組合的,也就是互相調(diào)用的。
5.1 嵌套調(diào)用#includevoid new_line()
{printf("hehe\n");
}
void three_line()
{int i = 0;
for(i=0; i<3; i++)
{new_line();
}
}
int main()
{three_line();
return 0; }
main函數(shù)中調(diào)用了three_line函數(shù)
three_line函數(shù)調(diào)用了new_line函數(shù)
實現(xiàn)了函數(shù)的嵌套調(diào)用
函數(shù)可以嵌套調(diào)用,但是不能嵌套定義。
嵌套定義會提示需要在內(nèi)層函數(shù)頭加上分號,編譯器只能認(rèn)為這是一句函數(shù)聲明,進而說明了C語言無法實現(xiàn)函數(shù)的嵌套定義
把一個函數(shù)的返回值作為另外一個函數(shù)的參數(shù)。
#include#includeint main()
{int ret = strlen("abcdef");//strlen用來求字符串中字符的長度
printf("%d\n", ret);//ret 是printf函數(shù)的參數(shù);
printf("%d\n", strlen("abcdef"));//strlen函數(shù)的返回值是printf函數(shù)的參數(shù)
return 0;
}
我們來看一個鏈?zhǔn)皆L問的例子
#includeint main()
{printf("%d", printf("%d", printf("%d", 43)));//結(jié)果是1
}
注:printf函數(shù)的返回值是打印在屏幕上的字符個數(shù),scanf函數(shù)的返回值是賦值成功變量的個數(shù)
從內(nèi)往外算
1. printf("%d", 43)打印出來的是4 3兩個字符,返回值是2
2. printf("%d", 2)打印出來的是2 一個字符,返回值是1
3. printf("%d", 1)打印出來的是1
6. 函數(shù)的聲明和定義
6.1 函數(shù)聲明對于全局變量,我們在源文件外面定義的變量,若想在源文件內(nèi)部使用該變量,我們需要在源文件內(nèi)部聲明一下
如果在源文件內(nèi)部定義的全局變量,我們沒有在定義變量之前就使用了它,則需要先聲明再使用
注:局部變量不存在聲明,所以局部變量只能先定義后使用,而全局變量可以先聲明(或定義)后使用。
函數(shù)和全局變量相似,必須先聲明(或定義)后使用
函數(shù)的定義是指函數(shù)的具體實現(xiàn),交待函數(shù)的功能實現(xiàn)。
//函數(shù)聲明
int Add(int a, int b);
int main()
{ //函數(shù)調(diào)用
int ret = Add(10, 20);
return 0;
}
//函數(shù)定義
int Add(int a, int b)
{return a + b;
}
//函數(shù)定義
int Add(int a, int b)
{return a + b;
}
int main()
{//函數(shù)調(diào)用
int ret = Add(10, 20);
return 0;
}
上述2種寫法都是正確的
當(dāng)程序中有函數(shù)聲明,函數(shù)定義可以放在任何函數(shù)的外部
當(dāng)程序中無函數(shù)聲明,函數(shù)定義必須放在調(diào)用該函數(shù)位置的前面
注:當(dāng)函數(shù)定義沒有返回值類型時,編譯器默認(rèn)為int型,若無返回值,則寫void,若函數(shù)明確沒有參數(shù),則參數(shù)列表應(yīng)該寫void,不要空著不寫?。?!
聲明時若函數(shù)沒有參數(shù)為什么不能空著呢?
注:在實現(xiàn)一些較大規(guī)模的程序時,函數(shù)聲明通常放在一個頭文件中,不同的函數(shù)定義通常封裝在不同的源文件中,在主函數(shù)所在的源文件加上#incldue"頭文件"即可在主函數(shù)中調(diào)用自定義函數(shù)
總結(jié):
1. 聲明是告訴編譯器有一個函數(shù)叫什么,參數(shù)是什么,返回類型是什么。但是具體是不是存在,函數(shù)聲明決定不了,由函數(shù)定義決定
2. 若函數(shù)定義出現(xiàn)在調(diào)用函數(shù)后面時,函數(shù)的聲明一般出現(xiàn)在函數(shù)的使用之前。要滿足先聲明后使用。
3. 函數(shù)的聲明一般要放在頭文件中
序調(diào)用自身的編程技巧稱為遞歸( recursion)。
遞歸做為一種算法在程序設(shè)計語言中廣泛應(yīng)用。 一個過程或函數(shù)在其定義或說明中有直接或間接調(diào)用自身的一種方法,它通常把一個大型復(fù)雜的問題層層轉(zhuǎn)化為一個與原問題相似的規(guī)模較小的問題來求解,
遞歸策略
只需少量的程序就可描述出解題過程所需要的多次重復(fù)計算,大大地減少了程序的代碼量。
遞歸的主要思考方式在于:把大事化小
舉個例子:
求N!可以求N * (N - 1)!,而N我們不需要求,所以只需要求(N-1)!
原來求N!,經(jīng)過遞歸后求(N_-1)!,將大事化小
7.2 練習(xí)1.接受一個整型值(無符號),按照順序打印它的每一位。
例如:
輸入:1234,輸出 1 2 3 4
分析:由1234打印最終變成1 2 3 4,我們可以知道打印123最終變成1 2 3,所以我們可以先對123進行打印 再打印4,打印4很容易,只需要另打印的數(shù)為1234對10取模, 打印123可以先打印12,再另打印的數(shù)為123取模10,打印12 可以先打印1,再另打印的數(shù)為12取模10,打印1很容易
void Print(int n)
{if (n< 10)
printf("%d ", n);
else if (n >= 10)
{Print(n / 10);
printf("%d ", n % 10);
}
}
int main()
{Print(1234);
return 0;
}
具體操作
注:綠線代表遞推,紅線代表回歸
2.編寫函數(shù)不允許創(chuàng)建臨時變量,求字符串的長度
分析:strlen(“abc”)=1+strlen(“bc”)
strlen(“bc”)=1+strlen(“c”)
strlen(“c”) =1+strlen(“”)
已知條件strlen(“”)=0
int my_strlen(char* str)
{if (*str == 0)
return 0;
else return 1 + my_strlen(str + 1);
}
int main()
{printf("%d ", my_strlen("abc"));
return 0;
}
具體操作
注:紅線代表地推,藍線代表回歸
1.用遞歸來求解斐波那契數(shù)
因為這里進行了多次重復(fù)的計算
計算f(30)時重復(fù)計算f(3)317811遍,效率是相當(dāng)?shù)牡?/p>
2.迭代求斐波那契數(shù)
迭代可以很快的算出來,這里算錯的原因是因為50!超過了int所能表示的范圍
總結(jié):
1. 許多問題是以遞歸的形式進行解釋的,這只是因為它比非遞歸的形式更為清晰。
2. 但是這些問題的迭代實現(xiàn)往往比遞歸實現(xiàn)效率更高,雖然代碼的可讀性稍微差些。
3. 當(dāng)一個問題相當(dāng)復(fù)雜,難以用迭代實現(xiàn)時,此時遞歸實現(xiàn)的簡潔性便可以補償它所帶來的運行時開
銷。
想要對遞歸有更深刻的印象可以去看這兩道題
青蛙跳臺階
漢諾塔
font color=red>看到最后,如果您覺得對您有幫助,請不要吝嗇手中的贊,這對我來說很重要,也是我創(chuàng)作的動力,如果您覺得哪里說的不清楚或者有問題,歡迎評論區(qū)留言
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
文章題目:【從0到1手把手帶你學(xué)C語言】詳解函數(shù)-創(chuàng)新互聯(lián)
URL標(biāo)題:http://jinyejixie.com/article14/dpdpge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、定制網(wǎng)站、Google、網(wǎng)站營銷、標(biāo)簽優(yōu)化、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容