摘要:形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動(dòng)銷毀了。函數(shù)的調(diào)用傳值調(diào)用函數(shù)的形參和實(shí)參分別占有不同內(nèi)存塊,對(duì)形參的修改不會(huì)影響實(shí)參。函數(shù)的聲明一般出現(xiàn)在函數(shù)的使用之前。以上兩個(gè)代碼,都是對(duì)函數(shù)遞歸的使用遞歸與迭代求的階乘。
一鍵三連加關(guān)注哦(不要下次一定哦)
禿頭俠們好呀,今天我們一起學(xué)習(xí)函數(shù)!
目標(biāo): 本章主要掌握函數(shù)的基本使用和遞歸
數(shù)學(xué)中我們常見到函數(shù)的概念。但是你了解C語(yǔ)言中的函數(shù)嗎? 維基百科中對(duì)函數(shù)的定義:子程序
在計(jì)算機(jī)科學(xué)中,子程序(英語(yǔ):Subroutine, procedure, function, routine, method,subprogram, callable unit),是一個(gè)大型程序中的某部分代碼, 由一個(gè)或多個(gè)語(yǔ)句塊組成。它負(fù)責(zé)完成某項(xiàng)特定任務(wù),而且相較于其他代 碼,具備相對(duì)的獨(dú)立性。
一般會(huì)有輸入?yún)?shù)并有返回值,提供對(duì)過(guò)程的封裝和細(xì)節(jié)的隱藏。這些代碼通常被集成為軟件庫(kù)。
為什么會(huì)有庫(kù)函數(shù)?
像上面我們描述的基礎(chǔ)功能,它們不是業(yè)務(wù)性的代碼。我們?cè)陂_發(fā)的過(guò)程中每個(gè)程序員都可能用的到,為了支持可移植性和提高程序的效率,所以C語(yǔ)言的基礎(chǔ)庫(kù)中提供了一系列類似的庫(kù)函數(shù),方便程序員進(jìn)行軟件開發(fā)。
那怎么學(xué)習(xí)庫(kù)函數(shù)呢?
這里我們簡(jiǎn)單的看看:https://www.cplusplus.com
簡(jiǎn)單的總結(jié),C語(yǔ)言常用的庫(kù)函數(shù)都有:
- IO函數(shù)
- 字符串操作函數(shù)
- 字符操作函數(shù)
- 內(nèi)存操作函數(shù)
- 時(shí)間/日期函數(shù)
- 數(shù)學(xué)函數(shù)
- 其他庫(kù)函數(shù)
注: 但是庫(kù)函數(shù)必須知道的一個(gè)秘密就是:使用庫(kù)函數(shù),必須包含 #include 對(duì)應(yīng)的頭文件。
庫(kù)函數(shù)不用全部記憶,需要的時(shí)候在此網(wǎng)址查找即可https://www.cplusplus.com
(所以看懂英文很重要,當(dāng)然你也可以選擇翻譯軟件)
如果庫(kù)函數(shù)能干所有的事情,那還要程序員干什么?
所以更加重要的是自定義函數(shù)。
自定義函數(shù)和庫(kù)函數(shù)一樣,有函數(shù)名,返回值類型和函數(shù)參數(shù)。 但是不一樣的是這些都是我們自己來(lái)設(shè) 計(jì)。這給程序員一個(gè)很大的發(fā)揮空間
函數(shù)的組成:
ret_type fun_name(para1, * ){statement;//語(yǔ)句項(xiàng)}ret_type 返回類型fun_name 函數(shù)名para1 函數(shù)參數(shù)
這里我們來(lái)舉一個(gè)例子:
寫一個(gè)函數(shù)可以找出兩個(gè)整數(shù)中的最大值
#include //get_max函數(shù)的設(shè)計(jì)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);printf("max = %d/n", max);return 0;}
return (x>y)?(x):(y);
此語(yǔ)句的意思是判斷X
是否大于Y
,如果X>Y
則選擇:
左邊的X
值,否則選擇:
右邊的Y
值。
實(shí)際參數(shù)(實(shí)參):
真實(shí)傳給函數(shù)的參數(shù),叫實(shí)參。實(shí)參可以是:常量、變量、表達(dá)式、函數(shù)等。無(wú)論實(shí)參是何種類型的量,在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須有確定的值,以便把這些值傳送給形參。
形式參數(shù)(形參):
形式參數(shù)是指函數(shù)名后括號(hào)中的變量,因?yàn)樾问絽?shù)只有在函數(shù)被調(diào)用的過(guò)程中才實(shí)例化(分配內(nèi)存單元),所以叫形式參數(shù)。形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動(dòng)銷毀了。因此形式參數(shù)只在函數(shù)中有效。
—————————————————————————
寫一個(gè)函數(shù)可以交換兩個(gè)整形變量的內(nèi)容
#include void Swap1(int x, int y){int tmp = 0;tmp = x;x = y;y = tmp;}void Swap2(int *px, int *py){int tmp = 0;tmp = *px;*px = *py;*py = tmp;}int main(){int num1 = 1;int num2 = 2;Swap1(num1, num2);printf("Swap1::num1 = %d num2 = %d/n", num1, num2);Swap2(&num1, &num2);printf("Swap2::num1 = %d num2 = %d/n", num1, num2);return 0;}
上面代碼Swap1
和Swap2
函數(shù)中的參數(shù) x,y,px,py
都是形式參數(shù)。在main
函數(shù)中傳給Swap1
的num1,num2
和傳給Swap2
函數(shù)的&num1,&num2
是實(shí)際參數(shù)。
經(jīng)分析:
這里可看到Swap1
函數(shù)在調(diào)用時(shí),x,y
擁有自己的空間,同時(shí)擁有了和實(shí)參一樣的內(nèi)容。所以我們可以簡(jiǎn)單的認(rèn)為:形參實(shí)例化之后其實(shí)相當(dāng)于實(shí)參的一份臨時(shí)拷貝
而Swap2
函數(shù)在調(diào)用時(shí),px,py
沒(méi)有再開辟空間,而就是num1,num2
的地址。
傳值調(diào)用
函數(shù)的形參和實(shí)參分別占有不同內(nèi)存塊,對(duì)形參的修改不會(huì)影響實(shí)參。
傳址調(diào)用
傳址調(diào)用是把函數(shù)外部創(chuàng)建變量的內(nèi)存地址傳遞給函數(shù)參數(shù)的一種調(diào)用函數(shù)的方式。
這種傳參方式可以讓函數(shù)和函數(shù)外邊的變量建立起正真的聯(lián)系,也就是函數(shù)內(nèi)部可以直接操作函數(shù)外部的變量
函數(shù)和函數(shù)之間可以有機(jī)的組合的。
#include void 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;}
把一個(gè)函數(shù)的返回值作為另外一個(gè)函數(shù)的參數(shù)
#include #include int main(){ char arr[20] = "hello"; int ret = strlen(strcat(arr, "bit")); printf("%d/n", ret); return 0;}
自己按照前面說(shuō)的網(wǎng)址去學(xué)習(xí)一下 strlen
和 strcat
看看這題答案是多少
這個(gè)結(jié)果又是多少呢?
#include int main(){printf("%d", printf("%d", printf("%d", 43)));return 0;}
這里需要知道printf
函數(shù)的返回值是多少
printf
函數(shù)的返回值是打印的字符數(shù)
此題從最里面一層看printf("%d", 43)
先打印出來(lái)43
因?yàn)槭?code>2個(gè)字符,所以返回值為2
,
printf("%d", printf("%d", 43))
相當(dāng)于printf("%d", 2)
然后打印2
,因?yàn)槭?code>1個(gè)字符,所以返回1
printf("%d", printf("%d", printf("%d", 43)))
相當(dāng)于printf("%d", 1)
所以最終打印4321
函數(shù)聲明:
- 告訴編譯器有一個(gè)函數(shù)叫什么,參數(shù)是什么,返回類型是什么。但是具體是不是存在,無(wú)關(guān)緊要。
- 函數(shù)的聲明一般出現(xiàn)在函數(shù)的使用之前。要滿足先聲明后使用。
- 函數(shù)的聲明一般要放在頭文件中的。
函數(shù)定義:
函數(shù)的定義是指函數(shù)的具體實(shí)現(xiàn),交待函數(shù)的功能實(shí)現(xiàn)。
所以可以在比如test.h
里放函數(shù)的聲明
在test.c
中放函數(shù)的定義實(shí)現(xiàn)
程序調(diào)用自身的編程技巧稱為遞歸( recursion)。 遞歸做為一種算法在程序設(shè)計(jì)語(yǔ)言中廣泛應(yīng)用。一個(gè)過(guò)程或函數(shù)在其定義或說(shuō)明中有直接或間接調(diào)用自身的一種方法,它通常把一個(gè)大型復(fù)雜的問(wèn)題層層轉(zhuǎn)化為一個(gè)與原問(wèn)題相似的規(guī)模較小的問(wèn)題來(lái)求解,遞歸策略只需少量的程序就可描述出解題過(guò)程所需要的多次重復(fù)計(jì)算,大大地減少了程序的代碼量。 遞歸的主要思考方式在于:把大事化小
接受一個(gè)整型值(無(wú)符號(hào)),按照順序打印它的每一位。 例如: 輸入:1234,輸出 1 2 3 4
#include #include void print(int n){ if (n > 9) { print(n / 10); } printf("%d ", n % 10);}int main(){ int num = 1234; print(num); return 0;}
編寫函數(shù)不允許創(chuàng)建臨時(shí)變量,求字符串的長(zhǎng)度。
#include int Strlen(const char* str){ if (*str == "/0") return 0; else return 1 + Strlen(str + 1);}int main(){ char* p = "abcdef"; int len = Strlen(p); printf("%d/n", len); return 0;}
以上兩個(gè)代碼,都是對(duì)函數(shù)遞歸的使用
求n的階乘。(不考慮溢出)
int factorial(int n){ if (n <= 1) return 1; else return n * factorial(n - 1);}int main(){ int n = 0; scanf("%d", &n); int ret = factorial(n); printf("%d/n", ret); return 0;}
求第n個(gè)斐波那契數(shù)。(不考慮溢出)
首先什么是斐波那契數(shù)?
就是前兩數(shù)之和等于第三個(gè)數(shù)
int fib(int n){if (n <= 2)return 1;elsereturn fib(n - 1) + fib(n - 2);}
運(yùn)行結(jié)果需要很長(zhǎng)時(shí)間才顯示出來(lái)為什么?
我們發(fā)現(xiàn)出現(xiàn)了問(wèn)題
我們發(fā)現(xiàn) fib 函數(shù)在調(diào)用的過(guò)程中很多計(jì)算其實(shí)在一直重復(fù)
int count = 0;//全局變量int fib(int n){if(n == 3)count++;if (n <= 2)return 1;elsereturn fib(n - 1) + fib(n - 2);}
我們用一段代碼來(lái)看一下,結(jié)果發(fā)現(xiàn)count
是一個(gè)很大的值,說(shuō)明代碼重復(fù)計(jì)算了很多次
在調(diào)試 factorial
函數(shù)的時(shí)候,如果你的參數(shù)比較大,那就會(huì)報(bào)錯(cuò): stack overflow
(棧溢出) 這樣的信息。 系統(tǒng)分配給程序的??臻g是有限的,但是如果出現(xiàn)了死循環(huán),或者(死遞歸),這樣有可能導(dǎo)致一直開辟棧空間,最終產(chǎn)生??臻g耗盡的情況,這樣的現(xiàn)象我們稱為棧溢出。
所以有時(shí)使用遞歸可以簡(jiǎn)化問(wèn)題,有時(shí)反而把問(wèn)題復(fù)雜了
調(diào)整后:
//求n的階乘int factorial(int n){ int tmp = 1; while (n > 1) { tmp *= n; n -= 1; } return tmp;}
//求第n個(gè)斐波那契數(shù)#include int Fib(int n){ int a = 1, b = 1, c = 1; while (n > 2) { c = a + b; a = b; b = c; n--; } return c;}int main(){ int n = 0; scanf("%d", &n); int ret = Fib(n); printf("%d/n", ret); return 0;}
所以要根據(jù)不同的情況使用不同的方法,才能使得問(wèn)題更高效地解決!
這期就到這里啦,我們下期再見
如有錯(cuò) 歡迎提出一起交流
后面會(huì)持續(xù)輸出,持續(xù)關(guān)注周周汪哦
記得關(guān)注三連哦么么么噠
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/119294.html
摘要:語(yǔ)言在設(shè)計(jì)中考慮了函數(shù)的高效性和易用性兩個(gè)原則。在語(yǔ)言中,最常見的當(dāng)屬函數(shù)了。以上就是一個(gè)函數(shù),它被稱為語(yǔ)言的入口函數(shù),或者主函數(shù)。例如和都是函數(shù)名。形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動(dòng)銷毀了。 ...
摘要:所以,遞歸在編程中同樣是很重要的一個(gè)知識(shí)點(diǎn)。舉個(gè)例子用遞歸實(shí)現(xiàn)求第個(gè)斐波那契數(shù)??偨Y(jié)起來(lái)四個(gè)字大事化小繼續(xù)舉斐波那契數(shù)的例子三遞歸是怎樣運(yùn)行的我們通過(guò)一道題目來(lái)講解。 ...
摘要:零預(yù)備知識(shí)字符編碼計(jì)算機(jī)只能處理數(shù)字,所以為文本需要轉(zhuǎn)化為數(shù)字才能被計(jì)算機(jī)處理,計(jì)算機(jī)里八個(gè)比特作為一個(gè)字節(jié),這是數(shù)據(jù)的存儲(chǔ)基礎(chǔ)單位。 零、預(yù)備知識(shí) 0.1 字符編碼計(jì)算機(jī)只能處理數(shù)字,所以為文本需要轉(zhuǎn)化為數(shù)字才能被計(jì)算機(jī)處理,計(jì)算機(jī)里八個(gè)比特(bit)作為一個(gè)字節(jié)(byte),這是數(shù)據(jù)的存儲(chǔ)基礎(chǔ)單位。計(jì)算機(jī)為了處理文本,有以下三種編碼方式: ASCII碼:只有大小寫英文字母,數(shù)字...
閱讀 2858·2021-11-23 09:51
閱讀 2476·2021-09-30 09:48
閱讀 2125·2021-09-22 15:24
閱讀 1098·2021-09-06 15:02
閱讀 3437·2021-08-17 10:14
閱讀 2009·2021-07-30 18:50
閱讀 2040·2019-08-30 15:53
閱讀 3259·2019-08-29 18:43