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

資訊專欄INFORMATION COLUMN

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

468122151 / 4840人閱讀

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

1. 函數簡介

函數可以把大的計算任務分解成若干較小的任務,然后通過調用的方式達到代碼復用;一個邏輯不寫多遍,減少代碼維護成本。

調用函數的一方不需要了解函數的具體實現,對于它來說,這部分是一個“黑盒子”,從而使得程序結構更加清晰。

C語言在設計中考慮了函數的 高效性 和 **易用性 **兩個原則。

函數的實現應該盡量簡短,因為函數可以套函數,一個程序應該盡量由許多小的函數組成,而不是少量較大的函數組成。

函數的基本概念

在刷題的過程中,系統會給我們事先提供一個函數讓我們來實現,而它則是調用函數的一方。

在C語言中,最常見的當屬main函數了。

int main(){    printf("5201314/n");        return 0;}

以上就是一個函數,它被稱為C語言的 入口函數,或者 主函數。

所有程序執行都是從這個函數開始的,以它為例,我們引出函數的一些基本概念。

函數的基本結構

如圖:

通過這個圖,我們類比main()這個函數,它的:

返回類型int32位整型,

函數名main,

參數列表

函數體printf("5201314/n");

返回值0。

返回類型

函數的返回類型可以是任意類型;

例如:整型int,浮點型float,字符型char,自定義類型等待;

返回類型返回值 是配套的,當返回類型為void時,函數內部的返回值可以寫return;也可以省略不寫。

函數名

函數名可以類比我們自己的名字。是給函數調用方用的。

例如:mainprintf都是函數名。

參數列表

函數的參數列表必須用()括起來,參數是函數需要處理的數據;

例如:

	printf("hello/n");

這一段代碼用來輸出字符串,"hello/n"就是一個參數,參數類型是字符串。

下面會詳細解釋:printf;

函數體

函數內部就是你可以任意發揮的部分,也就是函數的核心邏輯部分,可以是各種語句的組合;當然也可以是另一個函數,也就是函數說,函數是支持嵌套的。

返回值

函數的返回值則表示:這個函數最后返回給調用方的數據;

如果返回值的類型和函數的返回類型不一致,則會進行強制類型轉換;前提是能夠強制轉換的情況下。

2. C語言中函數的分類

  • 庫函數
  • 自定義函數

庫函數

為什么會有庫函數?

  • 我們學習C語言編程的時候,總是在一個代碼編寫完成之后迫不及待的想知道結果, 把這個結果打印到我們的屏幕上看看。這個時候我們會頻繁的使用一個功能:將信息按照一定的格式打印到屏幕上(printf)。

  • 在編程的過程中我們會頻繁的做一些字符串的拷貝工作(strcpy)。

  • 編程是我們也計算,總是會計算n的k次方這樣的運算(pow

像上面我們描述的基礎功能,它們不是業務性的代碼。

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

這里推薦一個網站:cplusplus.com

簡單的總結,C語言中,我們常用的庫函數都有:

  • IO函數:輸入和輸出函數

  • 字符串操作函數:比如求字符串長度的strlen函數

  • 字符操作函數:比如判斷字符的大小寫,將小寫字母轉化為大寫字母

  • 內存操作函數:內存復制、查找等操作

  • 時間/日期函數:獲取時間等

  • 數學函數:開平方sqrt等函數

等等…

如何使用庫函數?

我們參照文檔,學習幾個庫函數;

strcpy

從上面的庫函數網站可以找到strcpy的具體用法:

其實strcpy就是字符串拷貝的意思

  • 所指向的 C 字符串復制到目標所指向的數組中,包括終止空字符(并在該點停止)。

因此在使用這個函數的時候,我們需要向函數參數傳入destination(目標數組)和source(源數組)兩個字符串,同時該函數的返回值是char* ,它會將拷貝后的destination(目標數組)起始地址返回給我們。

  • 注意使用strcpy時要引用頭文件#include

官方寫法:

char* strcpy(char* strDestination, const char* strSource);

即第一個參數是目的地地址,第二個參數源地址;

代碼示例:

#include #include int main(){	char arr1[] = "Fighting Boy";	char arr2[] = "AAA";	strcpy(arr1, arr2);//將arr2數組的內容拷貝到arr1數組中	printf("arr1 = %s/n", arr1);//arr1 = "AAA"	printf("arr2 = %s/n", arr2);	return 0;}

運行結果:

注意:

這里的復制其實并不是真正的復制,準確的說是覆蓋

即把arr2的所有內容(包括/0)都覆蓋到arr1對應位置;

也就是說,雖然打印出來arr1AAA,但是實質上arr1等于AAA/0ting Boy;

我們可以運行調試一下:

補充:

  • 源字符串必須以 /0 結束。如果源字符串沒有/0,就會一直拷貝源字符串地址后面的所有內容,直到找到0。
  • 也會將源字符串中的 /0拷貝到目標數組中。
  • 目標空間必須足夠大,以確保能存放源字符串。如果目標空間不夠大,則會導致源字符串拷貝不進去。
  • 目標空間必須可變,即目標空間沒有 const修飾

(關于const的用法后續會寫一篇博客詳解)

注意: 使用庫函數,必須包含 #include 對應的頭文件。

自定義函數

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

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

自定義函數和庫函數一樣,有函數名,返回值類型和函數參數。

但是不一樣的是這些都是我們自己來設計。

自定義函數的定義語法為:

ret_type fun_name(para1, *){	statement;//語句項    return 返回值;//該返回值與返回類型必須相同,如果是void型函數,則不需要返回值,因此可以不寫。}ret_type 返回類型fun_name 函數名para1    函數參數

在使用函數的過程中,我們用函數名(函數參數)的形式來調用自定義函數;

由于一般函數在調用完以后產生一個返回值(比如一個兩個數相加的加法函數,實現兩個數相加以后返回兩個數的和),因此我們可以用一個變量來接收這個返回值。

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

代碼示例:

int get_max(int x, int y){	return (x > y) ? (x) : (y); //三目操作符,在操作符中講過,如果x>y則返回x,反之則返回y;}int main(){	int a = 20;	int b = 10;	int max = get_max(a, b);//定義一個max變量,用來接受最大值;	printf("max=%d/n", max);}

運行結果:

在程序運行過程中,給get_max這個函數傳入a、b這兩個參數,函數調用完后會返回a和b中的最大值;

因此可以用max來接收這個返回值。當然也可以不用接收,因為在函數運行完以后,get_max(a, b)就相當于這個返回值,該返回值可以當做printf的參數直接進行打印操作。

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

void Swap(int* pa, int* pb) //我們只需要交換a和b當中的內容,不需要返回值,所以用void{	int t = 0;//定義一個臨時變量用于交換	t = *pa;	*pa = *pb;	*pb = t;}int main(){	int a = 1;	int b = 2;	printf("交換前: a=%d b=%d/n", a, b);	Swap(&a, &b);	printf("交換前: a=%d b=%d/n", a, b);	return 0;}

運行結果:

3. 函數的參數

分為:

  • 實際參數(實參)
  • 形式參數(形參)

實際參數

  • 真實傳給函數的參數,叫實參。

  • 實參可以是:常量、變量、表達式、函數等。

  • 無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。

形式參數

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

代碼示例:

void Swap1(int x, int y){	int tmp = 0;	tmp = x;	x = y;	y = tmp;}void Swap2(int* px, int* py) //我們只需要交換a和b當中的內容,不需要返回值,所以用void{	int tmp = 0;	tmp = *px;	*px = *py;	*py = tmp;}int main(){	int a = 1;	int b = 2;	Swap1(a, b);	printf("Swap1: a=%d b=%d/n", a, b);	Swap2(&a, &b);	printf("Swap2: a=%d b=%d/n", a, b);	return 0;}

運行結果:

Swap1Swap2函數中的參數 x,y,px,py 都是形式參數。

在main函數中傳給Swap1a,b和傳給Swap2函數的&a,&b是實際參數。

這里我們對函數的實參形參進行分析:

可以看出:

實參a、b形參x、y不是同一空間

&a:0x00d3fa28&b:0x00d3fa1c    &x:0x00def944&y:0x00d3f948

這里可以看到Swap1函數在調用的時候,x,y擁有自己的空間,同時擁有了和實參一模一樣的內容

簡單來說:形參實例化之后其實相當于實參的一份臨時拷貝。

4. 函數的調用

分為:

  • 傳值調用

  • 傳址調用

傳值調用

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

例題:寫一個函數來實現對兩個數的交換

void Swap1(int x, int y){	int tmp = 0;	tmp = x;	x = y;	y = tmp;}int main(){	int a = 1;	int b = 2;	Swap1(a, b);	printf("Swap1: a=%d b=%d/n", a, b);	return 0;}

運行結果:

由于形參并不影響實參,函數在調用過程中只是對形參x,y進行了交換,并沒有影響到a,b;

并且函數在調用結束以后,x,y就已經被銷毀了。

調試看一下:

從監視中就可以看出,x,y的地址和a,b不同,他們相當于一塊獨立的空間,自身的改變并不會影響a,b

傳址調用

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

還是看這個例題,只不過我們稍微做點改變

void Swap2(int* px, int* py){	int tmp = 0;	tmp = *px;	*px = *py;	*py = tmp;}int main(){	int a = 1;	int b = 2;	Swap2(&a, &b);	printf("Swap2: a=%d b=%d/n", a, b);	return 0;}

運行結果:

通過這種方式可以使得變量進行真正的交換。

還是調試看一下:

通過監視可以看出,px、py就是一個指針,其中放的就是a,b的地址,*是解引用操作符,它可以通過地址找到地址中存放的變量值

比如px就是a的指針,它的值是a的地址,對px解引用就可以找到a地址中存放的變量1,然后我們就可以對變量1進行操作了。

傳值和傳址的使用場景

函數內部的形參只需要借用函數外部實參的值的時候用傳值調用,比如求兩個數的較大值。

函數內部需要對函數外部變量進行操作時用傳址調用,比如交換兩個數。

關于函數的形參、實參和傳值、傳址,可以看我之前寫的這篇文章:重點詳解函數的形參和實參、傳值和傳址

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

函數和函數之間是可以互相調用的。

嵌套調用

代碼示例:

void fun2(){	printf("hello/n");}void fun1(){	int i = 0;	for (i = 0; i < 3; i++)	{		fun2();	}}int main(){	fun1();	return 0;}

運行結果:

我們通過main函數調用fun1,通過fun1調用三次fun2,這就是函數的嵌套調用。

注意:函數可以嵌套調用,但是不能嵌套定義。

鏈式訪問

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

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", get_max(num1, num2));}

運行結果:

下面我們看一個有趣的代碼:

int main(){    printf("%d", printf("%d", printf("%d", 43))); //結果是啥?    //注:printf函數的返回值是打印在屏幕上字符的個數    return 0;}

運行結果:

這個程序實際上就是用printf的返回值作為printf的參數;

因此想要弄明白這個程序,我們得先知道printf的返回值;

通過查找printf的用法可以知道printf返回值:

所以printf返回值是寫入的字符總數,也就是字符的個數。

  • 最內層的printf打印43;

  • 第二層的printf打印的是最內層printf的返回值,也就是43這個內容的元素個數2;

  • 最外層打印的是printf("%d",2)的返回值,返回值是其元素個數1;

  • 所以會打印出4321這四個數。

6. 函數的定義和聲明

函數的聲明

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

函數的定義

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

test.h的內容

  • 放置函數的聲明
#ifndef __TEST_H__#define __TEST_H__//函數的聲明int Add(int x, int y);

test.c的內容

  • 放置函數的實現
#include "test.h"//函數Add的實現int Add(int x, int y){	return x + y;}

這種分文件的書寫形式,在后期寫三字棋和掃雷的時候,就可以用分模塊來寫。

我之前寫過一篇三子棋的小游戲,就是用這種分模塊的方式來寫的;

游戲鏈接:升級版三子棋小游戲(棋盤界面美化+動畫演示)

7. 函數遞歸

什么是遞歸?

  • 遞歸就是程序自己調用自己的過程
  • 它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解;
  • 遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復計算,大大地減少了程序的代碼量。

遞歸的條件

  • 存在限制條件;當滿足這個限制條件的時候,遞歸便不再繼續,否則遞歸會不斷進行,直到程序崩潰。
  • 每次遞歸調用之后越來越接近這個限制條件。

函數的遞歸

  • 函數的遞歸就是函數自己調用自己的過程。

這里我們通過代碼來詳解函數的遞歸

例題一

接受一個整型值(無符號),按照順序打印它的每一位。

例如: 輸入:1234,輸出 1 2 3 4.

思考一下:

我們想要從高位向低位輸出,就必須要依次獲?。鹤罡呶坏阶畹臀坏臄底郑?/p>

因此我們可以這1234每次除以10,并把1234 / 10的結果進行判斷,看其是否小于10;

如果小于10不再進行除以10的操作,這樣我們就可以得到最高位1了;

為了獲取其他位的數字,我們可以在每次除以10之前進行取模10的操作,得到剩下的位。

代碼示例:

void print(int n){	if (n > 9)	{		print(n / 10);	}	printf("%d ", n % 10);}int main(){	int num = 1234;	print(num); //這里的print是我們自己定義的函數,不是庫函數printf	return 0;}

運行結果:

關于這道題,我之前也做過詳解,并且畫了圖,可以去看下:深入理解C語言中函數的遞歸算法

遞歸與迭代

  • 迭代就是重復反饋過程的活動,每一次迭代的結果會作為下一次迭代的初始值。

函數遞歸和迭代的區別與優勢

  • 有些問題是以遞歸的形式進行解釋的,這只是因為它比非遞歸的形式更為清晰。

  • 但是這些問題的迭代實現往往比遞歸實現效率更高,雖然代碼的可讀性稍微差些。

  • 當一個問題相當復雜,難以用迭代實現時,此時遞歸實現的簡潔性便可以補償它所帶來的運行時開銷

8. 結語

其實后面關于函數的嵌套、遞歸、迭代都只是寫了一些知識點,所以還是打算通過例題的方式來詳解。

更多的一些重點函數(比如strlen,strcmp,strcat等)的實現,我會在之后多帶帶拿出來說明。

函數這一章的很多東西都需要練題+深刻理解,為后續的知識打下基礎!

等例題剖析完了,會附上鏈接!

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

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

相關文章

  • 怒肝1.5萬字——史上最全C語言文件操作詳解

    摘要:二什么是文件磁盤上的文件就是文件。文件指針變量定義是一個指向類型數據的指針變量。表示向何種流中輸出,可以是標準輸出流,也可以是文件流。文件結構體指針,將要讀取的文件流。 ...

    Alfred 評論0 收藏0
  • PHPer書單

    摘要:想提升自己,還得多看書多看書多看書下面是我收集到的一些程序員應該看得書單及在線教程,自己也沒有全部看完。共勉吧當然,如果你有好的書想分享給大家的或者覺得書單不合理,可以去通過進行提交。講師溫銘,軟件基金會主席,最佳實踐作者。 想提升自己,還得多看書!多看書!多看書!下面是我收集到的一些PHP程序員應該看得書單及在線教程,自己也沒有全部看完。共勉吧!當然,如果你有好的書想分享給大家的或者...

    jimhs 評論0 收藏0
  • 從小白程序員一路晉升為大廠高級技術專家我看過哪些書籍?(建議收藏)

    摘要:大家好,我是冰河有句話叫做投資啥都不如投資自己的回報率高。馬上就十一國慶假期了,給小伙伴們分享下,從小白程序員到大廠高級技術專家我看過哪些技術類書籍。 大家好,我是...

    sf_wangchong 評論0 收藏0
  • ??整理2萬字帶你走進C語言(詳細講解+代碼演示+圖解)??(強烈建議收藏!!?。?/b>

    目錄 一、什么是C語言? 二、第一個C語言程序 代碼 程序分析 ?程序運行 一個工程中出現兩個及以上的main函數 代碼 運行結果 分析 三、數據類型 數據各種類型 為什么會有這么多的數據類型? 計算機單位 ?各個數據類型的大小 ?注意事項 數據類型的使用 四、變量和常量 變量的分類 變量的使用 變量的作用域和生命周期 ?常量 五、字符串+轉義字符+注釋 字符串 ?轉義字符 注釋 六、選擇語句 ?...

    邱勇 評論0 收藏0

發表評論

0條評論

468122151

|高級講師

TA的文章

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