国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

C語言函數的基本使用和遞歸

sPeng / 1008人閱讀

摘要:形式參數當函數調用完成之后就自動銷毀了。函數的調用傳值調用函數的形參和實參分別占有不同內存塊,對形參的修改不會影響實參。函數的聲明一般出現在函數的使用之前。以上兩個代碼,都是對函數遞歸的使用遞歸與迭代求的階乘。

一鍵三連加關注哦(不要下次一定哦)

本章目標

禿頭俠們好呀,今天我們一起學習函數!

目標: 本章主要掌握函數的基本使用和遞歸

函數是什么

數學中我們常見到函數的概念。但是你了解C語言中的函數嗎? 維基百科中對函數的定義:子程序

在計算機科學中,子程序(英語:Subroutine, procedure, function, routine, method,subprogram, callable unit),是一個大型程序中的某部分代碼, 由一個或多個語句塊組成。它負責完成某項特定任務,而且相較于其他代 碼,具備相對的獨立性。
一般會有輸入參數并有返回值,提供對過程的封裝和細節的隱藏。這些代碼通常被集成為軟件庫。

C語言中函數的分類

  1. 庫函數
  2. 自定義函數

庫函數

為什么會有庫函數?

  1. 我們知道在我們學習C語言編程的時候,總是在一個代碼編寫完成之后迫不及待的想知道結果,想把這個結果打印到我們的屏幕上看看。這個時候我們會頻繁的使用一個功能:將信息按照一定的格式打印到屏幕上(printf)。
  2. 在編程的過程中我們會頻繁的做一些字符串的拷貝工作(strcpy)。
  3. 在編程是我們也計算,總是會計算n的k次方這樣的運算(pow)。

像上面我們描述的基礎功能,它們不是業務性的代碼。我們在開發的過程中每個程序員都可能用的到,為了支持可移植性和提高程序的效率,所以C語言的基礎庫中提供了一系列類似的庫函數,方便程序員進行軟件開發。

那怎么學習庫函數呢?

這里我們簡單的看看:https://www.cplusplus.com
簡單的總結,C語言常用的庫函數都有:

  • IO函數
  • 字符串操作函數
  • 字符操作函數
  • 內存操作函數
  • 時間/日期函數
  • 數學函數
  • 其他庫函數

注: 但是庫函數必須知道的一個秘密就是:使用庫函數,必須包含 #include 對應的頭文件。

如何學會使用庫函數?

庫函數不用全部記憶,需要的時候在此網址查找即可https://www.cplusplus.com
所以看懂英文很重要,當然你也可以選擇翻譯軟件

自定義函數

如果庫函數能干所有的事情,那還要程序員干什么?

所以更加重要的是自定義函數

自定義函數和庫函數一樣,有函數名,返回值類型和函數參數。 但是不一樣的是這些都是我們自己來設 計。這給程序員一個很大的發揮空間

函數的組成:

ret_type fun_name(para1, * ){statement;//語句項}ret_type 返回類型fun_name 函數名para1 函數參數

這里我們來舉一個例子:

寫一個函數可以找出兩個整數中的最大值

#include //get_max函數的設計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);此語句的意思是判斷X是否大于Y,如果X>Y則選擇左邊的X值,否則選擇右邊的Y值。

函數的參數

實際參數(實參):

真實傳給函數的參數,叫實參。實參可以是:常量、變量、表達式、函數等。無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。

形式參數(形參):

形式參數是指函數名后括號中的變量,因為形式參數只有在函數被調用的過程中才實例化(分配內存單元),所以叫形式參數。形式參數當函數調用完成之后就自動銷毀了。因此形式參數只在函數中有效。

—————————————————————————

寫一個函數可以交換兩個整形變量的內容

#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;}

上面代碼Swap1Swap2函數中的參數 x,y,px,py 都是形式參數。在main函數中傳給Swap1num1,num2和傳給Swap2函數的&num1,&num2實際參數

經分析:

這里可看到Swap1函數在調用時,x,y擁有自己的空間,同時擁有了和實參一樣的內容。所以我們可以簡單的認為:形參實例化之后其實相當于實參的一份臨時拷貝
Swap2函數在調用時,px,py沒有再開辟空間,而就是num1,num2的地址。

函數的調用:

傳值調用

函數的形參和實參分別占有不同內存塊,對形參的修改不會影響實參。

傳址調用

傳址調用是把函數外部創建變量的內存地址傳遞給函數參數的一種調用函數的方式。
這種傳參方式可以讓函數和函數外邊的變量建立起正真的聯系,也就是函數內部可以直接操作函數外部的變量

函數的嵌套調用和鏈式訪問

函數和函數之間可以有機的組合的。

嵌套調用

#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;}

鏈式訪問

把一個函數的返回值作為另外一個函數的參數

#include#includeint main(){	char arr[20] = "hello";	int ret = strlen(strcat(arr, "bit"));	printf("%d/n", ret);	return 0;}

自己按照前面說的網址去學習一下 strlenstrcat 看看這題答案是多少

這個結果又是多少呢?

#include int main(){printf("%d", printf("%d", printf("%d", 43)));return 0;}

這里需要知道printf函數的返回值是多少
printf函數的返回值是打印的字符數
此題從最里面一層看printf("%d", 43)先打印出來43
因為是2個字符,所以返回值為2
printf("%d", printf("%d", 43))相當于printf("%d", 2)
然后打印2,因為是1個字符,所以返回1
printf("%d", printf("%d", printf("%d", 43)))相當于printf("%d", 1)
所以最終打印4321

函數的聲明和定義

函數聲明:

  1. 告訴編譯器有一個函數叫什么,參數是什么,返回類型是什么。但是具體是不是存在,無關緊要。
  2. 函數的聲明一般出現在函數的使用之前。要滿足先聲明后使用。
  3. 函數的聲明一般要放在頭文件中的。

函數定義:

函數的定義是指函數的具體實現,交待函數的功能實現。

所以可以在比如test.h里放函數的聲明
test.c中放函數的定義實現

函數遞歸

什么是遞歸?

程序調用自身的編程技巧稱為遞歸( recursion)。 遞歸做為一種算法在程序設計語言中廣泛應用。一個過程或函數在其定義或說明中有直接或間接調用自身的一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復計算,大大地減少了程序的代碼量。 遞歸的主要思考方式在于:把大事化小

遞歸的兩個必要條件

  • 存在限制條件,當滿足這個限制條件的時候,遞歸便不再繼續。
  • 每次遞歸調用之后越來越接近這個限制條件

接受一個整型值(無符號),按照順序打印它的每一位。 例如: 輸入:1234,輸出 1 2 3 4

#include#includevoid print(int n){	if (n > 9)	{		print(n / 10);	}	printf("%d ", n % 10);}int main(){	int num = 1234;	print(num);	return 0;}

編寫函數不允許創建臨時變量,求字符串的長度。

#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;}

以上兩個代碼,都是對函數遞歸的使用

遞歸與迭代

求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個斐波那契數。(不考慮溢出)

首先什么是斐波那契數?

就是前兩數之和等于第三個數

int fib(int n){if (n <= 2)return 1;elsereturn fib(n - 1) + fib(n - 2);}

運行結果需要很長時間才顯示出來為什么?

我們發現出現了問題

  • 在使用 fib 這個函數的時候如果我們要計算第50個斐波那契數字的時候特別耗費時間。
  • 使用factorial函數求10000的階乘(不考慮結果的正確性),程序會崩潰

我們發現 fib 函數在調用的過程中很多計算其實在一直重復

int count = 0;//全局變量int fib(int n){if(n == 3)count++;if (n <= 2)return 1;elsereturn fib(n - 1) + fib(n - 2);}

我們用一段代碼來看一下,結果發現count是一個很大的值,說明代碼重復計算了很多次

在調試 factorial 函數的時候,如果你的參數比較大,那就會報錯: stack overflow(棧溢出) 這樣的信息。 系統分配給程序的棧空間是有限的,但是如果出現了死循環,或者(死遞歸),這樣有可能導致一直開辟棧空間,最終產生棧空間耗盡的情況,這樣的現象我們稱為棧溢出。

所以有時使用遞歸可以簡化問題,有時反而把問題復雜了

調整后:

//求n的階乘int factorial(int n){	int tmp = 1;	while (n > 1)	{		tmp *= n;		n -= 1;	}	return tmp;}
//求第n個斐波那契數#includeint 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;}

所以要根據不同的情況使用不同的方法,才能使得問題更高效地解決!

這期就到這里啦,我們下期再見
如有錯 歡迎提出一起交流
后面會持續輸出,持續關注周周汪

記得關注三連哦么么么噠

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119294.html

相關文章

  • 【零基礎趣學C語言】- 史上最全C語言函數詳解(萬字圖文+代碼演示+圖解)

    摘要:語言在設計中考慮了函數的高效性和易用性兩個原則。在語言中,最常見的當屬函數了。以上就是一個函數,它被稱為語言的入口函數,或者主函數。例如和都是函數名。形式參數當函數調用完成之后就自動銷毀了。 ...

    468122151 評論0 收藏0
  • C語言】玩轉遞歸——學好遞歸,你需要掌握知識!

    摘要:所以,遞歸在編程中同樣是很重要的一個知識點。舉個例子用遞歸實現求第個斐波那契數。總結起來四個字大事化小繼續舉斐波那契數的例子三遞歸是怎樣運行的我們通過一道題目來講解。 ...

    Donne 評論0 收藏0
  • python入門

    摘要:零預備知識字符編碼計算機只能處理數字,所以為文本需要轉化為數字才能被計算機處理,計算機里八個比特作為一個字節,這是數據的存儲基礎單位。 零、預備知識 0.1 字符編碼計算機只能處理數字,所以為文本需要轉化為數字才能被計算機處理,計算機里八個比特(bit)作為一個字節(byte),這是數據的存儲基礎單位。計算機為了處理文本,有以下三種編碼方式: ASCII碼:只有大小寫英文字母,數字...

    xeblog 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<