03-C語言函數(shù)

函數(shù)

函數(shù)的分類

  • 在C語言中可從不同的角度對函數(shù)分類

  • 從函數(shù)定義的角度看,函數(shù)可分為庫函數(shù)和用戶定義函數(shù)兩種

    • 庫函數(shù): 由C語言系統(tǒng)提供,用戶無須定義
    • 用戶定義函數(shù):由用戶按需編寫的函數(shù)。
  • 從函數(shù)執(zhí)行結(jié)果的角度來看, 函數(shù)可分為有返回值函數(shù)和無返回值函數(shù)兩種

    • 有返回值函數(shù): 此類函數(shù)被調(diào)用執(zhí)行完后將向調(diào)用者返回一個執(zhí)行結(jié)果,稱為函數(shù)返回值唆垃。(必須指定返回值類型和使用return關鍵字返回對應數(shù)據(jù))
    • 無返回值函數(shù): 此類函數(shù)用于完成某項特定的處理任務,執(zhí)行完成后不向調(diào)用者返回函數(shù)值五芝。(返回值類型為void, 不用使用return關鍵字返回對應數(shù)據(jù))
  • 從主調(diào)函數(shù)和被調(diào)函數(shù)之間數(shù)據(jù)傳送的角度看,又可分為無參函數(shù)和有參函數(shù)兩種

    • 無參函數(shù): 在函數(shù)定義及函數(shù)說明及函數(shù)調(diào)用中均不帶參數(shù)。主調(diào)函數(shù)和被調(diào)函數(shù)之間不進行參數(shù)傳送辕万。
    • 有參函數(shù): 在函數(shù)定義及函數(shù)說明時都有參數(shù),稱為形式參數(shù)(簡稱為形參)枢步。在函數(shù)調(diào)用時也必須給出參數(shù),稱為實際參數(shù)(簡稱為實參)
  • 為什么要定義函數(shù)?

    • 首先,如果不定義函數(shù):
      • 重復代碼冗余代碼過多;
      • 需求發(fā)生改變時;需要修改很多代碼
    • 如果定義函數(shù)
    • 將某些代碼封裝起來,方便以后的使用;
    • 提高代碼的復用性;
    • 使代碼更加簡潔;
    • 便于維護;

函數(shù)的定義

  • 格式:
// 標注  有參數(shù)有返回值函數(shù)的定義
返回值類型 函數(shù)名稱(形參列表){
    被封裝的函數(shù);
    返回值;
}
例子:

int main(){
    printf("hello world");
    return 0;
}

// 獲取最大值
int getMax(int num1, int num2){
    int max = num1 > num2 ? num1 : num2;
    return max;
}


// 無參數(shù)無返回值的函數(shù)定義:
void 函數(shù)名(){
    函數(shù)體;
}

// 無參有返回值函數(shù)定義
返回值類型 函數(shù)名(){
    函數(shù)體;
    return 值;
}

// 有參無返回值函數(shù)定義
void 函數(shù)名(參數(shù)類型 形式參數(shù)1, 參數(shù)類型 形式參數(shù)2, ...){
    函數(shù)體;
}


  • 初學者如何定義函數(shù)
    • 1.確定函數(shù)的名稱(給函數(shù)起一個有意義的名稱,讓調(diào)用者見名知意)
    • 注意點: 函數(shù)名稱也是標識符的一種,所以也需要遵守標識符的命名規(guī)則: 字母,數(shù)字,下劃線的駝峰命名;
    • 2.確定形參列表(告訴調(diào)用者,調(diào)用時是否需要傳遞一些輔助的數(shù)據(jù));
      • 注意點: 形參列表的格式 (數(shù)據(jù)類型 變量名稱, 數(shù)據(jù)類型 變量名稱, ...)
      • 數(shù)據(jù)類型 變量名稱 可以有零個或多個;
    • 3.確定函數(shù)的功能代碼(也就是要封裝的代碼)
    • 4.確定返回值和返回值的類型
    • return 的作用之一就是將后面的數(shù)據(jù)返回給函數(shù)的調(diào)用者;
#include <stdio.h>
int getAverage(int num1, int num2){
    int avg = (num1 + num2) / 2;
    return avg;
}
int main()
{
    int a = 10;
    int b = 20;
//    int res = (a + b) / 2;
    int res = getAverage(a, b);
    printf("average = %i\n", res);
    return 0;
}

// 注意點: main函數(shù)的作用域和getAverage作用域不同

image

函數(shù)的參數(shù)和返回值

  • 函數(shù)的參數(shù):
    • 函數(shù)可以有參數(shù),也可以沒有參數(shù);
    • 函數(shù)的參數(shù)可以是零個或多個;
    • 函數(shù)可以有返回值;也可以沒有返回值;
    • 注意:如果函數(shù)沒有返回值,那么返回值類型寫void就行;
    • 函數(shù)的返回值類型可以是所有C語言類型
  • 形式參數(shù):
    • 定義函數(shù)時,函數(shù)名后面小括號()中定義的變量成為形式參數(shù),簡稱形參
    • 形參變量只有在被調(diào)用時才分配內(nèi)存單元,在調(diào)用結(jié)束時,即刻釋放所分配的內(nèi)存單元
    • 因此,形參只有在函數(shù)內(nèi)部有效,函數(shù)調(diào)用結(jié)束返回主調(diào)函數(shù)后則不能再使用該形參變量
int getSum(int num1, int num2){  // 形式參數(shù)
    return num1+num2;
}
  • 實際參數(shù):
    • 調(diào)用函數(shù)時,傳入的值稱為實際參數(shù),簡稱實參;
    • 實參可以是常量渐尿、變量醉途、表達式、函數(shù)等,無論實參是何種類型的量,在進行函數(shù)調(diào)用時,它們都必須具有確定的值,以便把這些值傳送給形參
    • 因此應預先用賦值,輸入等辦法使實參獲得確定值
int main(){
    int a = 99, b =100;
    int sum = getSum(a, b); // 實際參數(shù)
}
  • 返回值的注意點:
    • 如果函數(shù)沒有編寫返回值類型,那么默認就是int類型!
    • 如果函數(shù)的返回值類型和實際return返回的類型不同,那么會隱式(自動)轉(zhuǎn)換為返回值類型;
test1(){
    return 3.14;
}

// 返回值為3
//如果函數(shù)的返回值類型和實際return返回的類型不同,那么會隱式(自動)轉(zhuǎn)換為返回值類型
int test2(){
    return 3.14;  // double
}
// 返回值3

int main()
{
    double res = test1();
    printf("res = %lf",res); // 3.000000
    return 0;
}

  • 函數(shù)的注意點:
    • 1.函數(shù)的名稱不能相同;
      • 哪怕返回類型不同,函數(shù)名稱也不能相同
      • 哪怕形參列表不同,函數(shù)名臣也不能相同
    • 2.函數(shù)不能嵌套定義,哪怕編譯器允許的,也不建議這么干;
    • 3.如果是基本類型的數(shù)據(jù)作為函數(shù)的參數(shù) ,那么在函數(shù)內(nèi)修改形參, 不會影響外面實參的值;
    • 4.在函數(shù)的內(nèi)部不能定義和形參同名的變量
    void test(){
        int num = 666; // 這么定義變量會報錯
        printf("num = %i\n", num);
    }
    
    • 函數(shù)不要嵌套定義

函數(shù)的聲明

  • 函數(shù)的定義可以寫在函數(shù)調(diào)用之前,也可以寫在函數(shù)調(diào)用之后,但是要進行函數(shù)的聲明;

  • 標準的寫法:函數(shù)的聲明只需要將函數(shù)定義{前面的代碼拷貝即可;

  • 函數(shù)聲明,就是在函數(shù)調(diào)用之前告訴系統(tǒng), 該函數(shù)叫什么名稱, 該函數(shù)接收幾個參數(shù), 該函數(shù)的返回值類型是什么

  • 函數(shù)的聲明只需將函數(shù)定義{前面的代碼拷貝即可

  • 聲明函數(shù)的注意點:

    • 1.函數(shù)的聲明只要寫在調(diào)用之前

      • 也就是說,函數(shù)的聲明,可以寫在函數(shù)的外面
      • 也可以寫在函數(shù)里面
    • 2.函數(shù)聲明的時候,形參可以不用在指定名稱

    • 3.如果函數(shù)的返回值類型是整型,那么可以不用編寫函數(shù)聲明(但是還是建議寫上);

    • 由于函數(shù)聲明僅僅是為了告訴編譯器,我們有一個什么函數(shù),所以函數(shù)的聲明是可以聲明多次,但是函數(shù)的的實現(xiàn)只能一次;

    • 總結(jié):

      • 1.以后但凡函數(shù)的定義寫在函數(shù)調(diào)用之前,一定要在調(diào)用之前編寫函數(shù)的聲明;
      • 2.函數(shù)的聲明只會告訴系統(tǒng)函數(shù)叫什么,接收幾個什么類型參數(shù),返回值是什么類型即可;
      • 3.一般情況下我們會將函數(shù)的聲明寫到函數(shù)的外面,而不會寫到函數(shù)的里面;

main函數(shù)分析

  • main函數(shù)分析

    • main是函數(shù)的名稱, 和我們自定義的函數(shù)名稱一樣, 也是一個標識符
    • 只不過main這個名稱比較特殊, 程序已啟動就會自動調(diào)用它
  • return 0;的含義:

    • 告訴系統(tǒng)main函數(shù)是否正確的被執(zhí)行了
    • 如果main函數(shù)的執(zhí)行正常, 那么就返回0
    • 如果main函數(shù)執(zhí)行不正常, 那么就返回一個非0的數(shù)
  • 返回值類型:

    • 一個函數(shù)return后面寫的是什么類型, 函數(shù)的返回值類型就必須是什么類型, 所以寫int
  • 在企業(yè)開發(fā)中,我們是可以通過控制臺(cmd)在運行程序的時候給main函數(shù)傳遞參數(shù)就可以了

int main(int argc, const char *argv[])
{
    
    // 代表數(shù)組中有一個元素
    // 代表數(shù)組中有兩個元素
    // 默認情況下, 系統(tǒng)在調(diào)用main函數(shù)的時候, 會給argv這個數(shù)組中存放一個元素
    
    printf("argc = %i\n", argc);
    printf("argv[0] = %s\n", argv[0]);
    printf("argv[1] = %s\n", argv[1]);
    printf("argv[2] = %s\n", argv[2]);
    return 0;
}

遞歸函數(shù)

- 遞歸: 自己搞自己
- 遞歸可以實現(xiàn)循環(huán)的功能,但是遞歸的性能比循環(huán)差很多
- return 只能返回給調(diào)用者
// do - while 寫法:
int num = -1;
     do{
          // 提醒用戶如何輸入數(shù)據(jù)
         printf("請輸入一個正整數(shù),以回車結(jié)束;\n");
         // 接收用戶輸入的數(shù)據(jù);
         scanf("%i", &num);
     }while( num < 0);

     // 輸出
     printf("%i",num);
     
     
// 遞歸寫法

int test(){
    // 定義用戶保存的變量
    int num = -1;
    // 提示用戶如何輸入數(shù)據(jù)
    printf("請輸入一個正整數(shù),以回車結(jié)束;\n");
    // 接收用戶輸入的數(shù)據(jù)
    scanf("%i", &num);
    if(num < 0 ){
        // 用戶輸入不合法
        return test();
    }
    return num;
}
     
image
  • 循環(huán)和遞歸的區(qū)別

    • 能用循環(huán)實現(xiàn)的功能,用遞歸都可以實現(xiàn);
    • 遞歸常用于"回溯", "樹的遍歷","圖的搜索"等問題
    • 但代碼理解難度大,內(nèi)存消耗大(易導致棧溢出), 所以考慮到代碼理解難度和內(nèi)存消耗問題, 在企業(yè)開發(fā)中一般能用循環(huán)都不會使用遞歸
  • 設計一個函數(shù)用來計算B的n次方

#include <stdio.h>
int pow(int b, int n);
int main()
{
    /*
     * 編寫一個函數(shù)實現(xiàn)    B的n次方;
     * B^n
     *
     * b^0 = 1;
     * b^1 = b;
     * b^2 = b*b;
     * b^3 = b*b*b;
     *
     * b^0 = 1;
     * b^1 = b^0 * b;
     * b^2 = b^1 * b;
     *
     * 規(guī)律:  B^n = b^(n-1) * b;
     *
    */

    // 定義用戶輸入的變量
    int B = -1, n = -1;
    // 提示用戶輸入
    printf("請輸入兩個數(shù),代表B^n;以逗號隔開\n");
    // 接收用戶輸入
    scanf("%i,%i", &B, &n);
    // 接收結(jié)果
    int res = pow(B, n);
    printf("res = %i\n",res);
    return 0;
}

// 傳入格式: B^n
int pow(int b, int n){
    if(n == 0){
        return 1;
    }else{
        return pow(b, n-1) * b;
    }
}


  • 用遞歸法求N的階乘

#include <stdio.h>
int jieCheng(int n);
int main()
{
    /*
     * 利用遞歸實現(xiàn)階乘
     *
     * 3! = 3*2*1;
     * 2! = 2*1;
     * 1! = 1;
     *
     * 規(guī)律  n = (n-1)! * n;
     *
    */

    // 定義變量  n;
    int n = -1;
    // 提示輸入n
    printf("請輸入N的階乘:\n");
    // 接收用戶輸入的n
    scanf("%i", &n);
    // 保存結(jié)果
    int res = jieCheng(n);
    // 輸入結(jié)果
    printf("%i! = %i", n, res);
    return 0;
}

int jieCheng(int n){
    if(n==1){
        return 1;
    }else {
        return jieCheng(n-1) *n;
    }
    return n;
}

  • 有5個人坐在一起,問第5個人多少歲?他說比第4個人大兩歲砖茸。問 第4個人歲數(shù),他說比第3個人大兩歲隘擎。問第3個人,又說比第2個 人大兩歲。問第2個人,說比第1個人大兩歲凉夯。最后問第1個人, 他說是10歲货葬。請問第5個人多大?
#include <stdio.h>
int getAge(int n);
int main()
{
    /*
     * 有5個人坐在一起,問第5個人多少歲?他說比第4個人大兩歲。
     * 問 第4個人歲數(shù),他說比第3個人大兩歲恍涂。
     * 問第3個人,又說比第2個 人大兩歲宝惰。
     * 問第2個人,說比第1個人大兩歲。
     * 最后問第1個人, 他說是10歲再沧。
     * 請問第5個人多大?
     *
     * 第一個人:  10;
     * 第二個人:  10 + 2;
     * 第三個人:  10 + 2 + 2;
     * 第四個人:  10 + 2 + 2 + 2;
     * 第五個人:  10 + 2 + 2 + 2 + 2;
     *
     * 規(guī)律:(n -1) + 2;
     *   其中第幾個人是n, 10就是n的默認值;
     *
     *
     *
    */


    // 定義第n個用戶輸入的變量
    int n = -1;
    // 提示用戶輸入
    printf("請輸入一個整數(shù):\n");
    // 接收輸入
    scanf("%i", &n);
    // 定義歲數(shù)
    int age = getAge(n);
    // 輸出
    printf("age = %i", age);
    return 0;
}


// 遞歸實現(xiàn)年齡
int getAge(int n){
    if(n == 1){
        return 10;
    }else{
        return getAge(n-1) + 2;
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尼夺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炒瘸,更是在濱河造成了極大的恐慌淤堵,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顷扩,死亡現(xiàn)場離奇詭異拐邪,居然都是意外死亡,警方通過查閱死者的電腦和手機隘截,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門扎阶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汹胃,“玉大人,你說我怎么就攤上這事东臀∽偶ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵惰赋,是天一觀的道長宰掉。 經(jīng)常有香客問我,道長赁濒,這世上最難降的妖魔是什么轨奄? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮拒炎,結(jié)果婚禮上挪拟,老公的妹妹穿的比我還像新娘。我一直安慰自己击你,他們只是感情好舞丛,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著果漾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谷誓。 梳的紋絲不亂的頭發(fā)上绒障,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音捍歪,去河邊找鬼户辱。 笑死,一個胖子當著我的面吹牛糙臼,可吹牛的內(nèi)容都是我干的庐镐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼变逃,長吁一口氣:“原來是場噩夢啊……” “哼必逆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起揽乱,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤名眉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后凰棉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體损拢,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年撒犀,在試婚紗的時候發(fā)現(xiàn)自己被綠了福压。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掏秩。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荆姆,靈堂內(nèi)的尸體忽然破棺而出蒙幻,到底是詐尸還是另有隱情,我是刑警寧澤胞枕,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布杆煞,位于F島的核電站,受9級特大地震影響腐泻,放射性物質(zhì)發(fā)生泄漏决乎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一派桩、第九天 我趴在偏房一處隱蔽的房頂上張望构诚。 院中可真熱鬧,春花似錦铆惑、人聲如沸范嘱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丑蛤。三九已至,卻和暖如春撕阎,著一層夾襖步出監(jiān)牢的瞬間受裹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工虏束, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棉饶,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓镇匀,卻偏偏與公主長得像照藻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子汗侵,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1幸缕、c語言的函數(shù)有以下特點: (1)才源程序由函數(shù)組成,一個主函數(shù)main()+若干其他函數(shù) C程序中的函數(shù)類似文...
    滕王閣序閱讀 1,342評論 0 6
  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用晰韵。當一個函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,610評論 1 19
  • C語言函數(shù)(一) 謹記 短暫的人生中冀值,注定有很多人陪伴著你度過,陪你一起歡呼宫屠,陪你一起傷心流淚列疗,陪你一起走過一條又...
    長風留言閱讀 2,267評論 1 7
  • 函數(shù)基本概念 C源程序是由函數(shù)組成的例如: 我們前面學習的課程當中,通過main函數(shù)+scanf函數(shù)+printf...
    極客江南閱讀 1,350評論 1 14
  • 函數(shù)基本概念 C源程序是由函數(shù)組成的例如: 我們前面學習的課程當中,通過main函數(shù)+scanf函數(shù)+printf...
    極客學院凱閱讀 224評論 0 1