C語言自學攻略-函式

更新於 發佈於 閱讀時間約 12 分鐘

函式

將特定功能或常用的程式碼獨立成一個程式模組,稱為函式。

函式的優點為:

  1. 可重複使用。
  2. 可簡化程式複雜度,提升可讀性。
  3. 易於除錯與維護。

函式分為兩種:公用函式以及自訂函式。

公用函式

常見的標頭檔如下,只要在程式中引入(#include<標頭檔>),即可呼叫公用函式:

  1. <math.h>
  2. <time.h>
  3. <stdlib.h>

常見的數值類公用函式如下表:

raw-image
  • 備註:使用三角函數時,角度需轉為弧度,公式如下:

角度A → 弧度:A×π/180

時間、日期類函式如下表:

raw-image

使用範例:

#include <stdio.h>
#include <time.h>

int main() {
time_t t = time(&t);
printf("現在時間:%s\n", ctime(&t));

int j;
printf("執行加法運算5億次需要");
clock_t st =clock();
for(int i=0; i<500000000; i++)
{
j+=1;
}
clock_t et =clock();
printf("%.3lf秒",(double)(et-st)/CLOCKS_PER_SEC);

return 0;
}
  • 說明:
    • 迴圈前使用 clock() 函式獲取程式開始執行的時間(st)。
    • 迴圈後使用 clock() 函式獲取程式結束執行的時間(et)。
    • 將開始的時間與結束的時間相減除以CLOCKS_PER_SEC(代表CPU時鐘的每秒執行次數),即可得到所需的秒數。
    • 另外,由於参與計算的數值都是整數,所以須以(double)先強制轉換資料型態。

亂數函式如下:

raw-image

使用範例:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
srand(time(NULL)); // 設定亂數種子,如果沒有設定,會造成下一次程式執行的輸出結果與前一次相同
for (int i = 0; i < 5; i++) {
printf("亂數%d: %d\n", i + 1, rand() % 100); // 產生 0-99 的亂數
}
for (int i = 0; i < 5; i++) {
printf("亂數%d: %d\n", i + 1, rand() % 100 + 1); // 產生 1-100 的亂數
}
return 0;
}

自訂函式

自訂函式是由開發者自己定義的函式,用於執行特定需求。它可以提升程式的可讀性、模組化和重複使用性。

函式定義:

返回值型別 函式名稱(參數型別 參數名稱, ...) {
// 函式內部的程式碼
return 返回值; // (如果函式需要回傳值)
}

若不需要傳入參數以及回傳變數值,則函式宣告如下:

void 函式名稱(參數型別 參數名稱, ...) {
// 函式內部的程式碼
}

簡單的自訂函式例子:

#include <stdio.h>

// 函式宣告
int add(int a, int b);

int main() {
int x = 5, y = 10;
// 呼叫函式
int result = add(x, y); //result用來接收x+y的結果
printf("兩數的總和為:%d\n", result);
return 0;
}

// 函式定義
int add(int a, int b) {
return a + b; // 傳回兩數的和,傳回int型別
}

當然,你也可以宣告後直接定義:

#include <stdio.h>

// 函式宣告並定義
int add(int a, int b){
return a + b; // 傳回兩數的和
}

int main() {
int x = 5, y = 10;
// 呼叫函式
int result = add(x, y);
printf("兩數的總和為:%d\n", result);
return 0;
}

請注意,當我們呼叫函式並傳入數值時,函式接收的是變數值的副本,而不是原變數本身。這種方式不會影響原始變數的內容。以下為簡單示範:

#include <stdio.h>

// 函式宣告
void modifyValue(int a);

int main() {
int a = 10;
printf("呼叫函式前,a = %d\n", a);

// 呼叫函式,傳遞 x 的值
modifyValue(a);

printf("呼叫函式後,a = %d\n", a);
return 0;
}

// 函式定義
void modifyValue(int a) {
a = 20; // 修改參數的副本
printf("函式內,a = %d\n", a);
}

從上面的程式碼,我們可以學到,函式中的a是你傳入數值的一個副本(傳入的數值複製給函式中的a變數),並且這個副本變數允許和主程式中的變數a同名,不過他們本質上並不一樣,所以修改函式中的a並不會影響主程式中的變數a

接下來我想要講解變數的生命週期:

變數的生命週期

#include <stdio.h>

// 全域變數
int globalVar = 100; // 生命週期:程式開始 → 程式結束

void testFunction() {
// 區域變數
int localVar = 10; // 生命週期:進入函式 → 函式結束
printf("函式內區域變數 localVar = %d\n", localVar);

// 靜態區域變數
static int staticVar = 0; // 生命週期:第一次進入函式 → 程式結束
staticVar++;
printf("函式內靜態區域變數 staticVar = %d\n", staticVar);
}

int main() {
// main 函式內的區域變數
int mainVar = 50; // 生命週期:進入 main() → main() 結束
printf("main 函式內區域變數 mainVar = %d\n", mainVar);

// 迴圈內的區域變數
for (int i = 0; i < 3; i++) {
int loopVar = i * 10; // 生命週期:每次進入迴圈 → 該次迴圈結束
printf("迴圈內區域變數 loopVar = %d\n", loopVar);
}

// 呼叫函式多次
testFunction(); // 第一次呼叫
testFunction(); // 第二次呼叫

// 使用全域變數
printf("全域變數 globalVar = %d\n", globalVar);

return 0;
}

變數生命週期與範圍解釋:

  1. 全域變數 (globalVar)
    • 生命週期:從程式啟動到結束。
    • 作用範圍:程式中的所有函式。
  2. main 函式內的區域變數 (mainVar)
    • 生命週期:進入 main() 時分配記憶體,退出 main() 時釋放。
    • 作用範圍:僅限於 main()
  3. 函式內的區域變數 (localVar)
    • 生命週期:每次進入函式時分配記憶體,函式結束時釋放。
    • 作用範圍:僅限於函式內。
  4. 靜態區域變數 (staticVar)
    • 生命週期:程式執行期間,且僅初始化一次,直到程式結束後釋放。
    • 作用範圍:僅限於該函式內,但值在函式多次呼叫間保留。
  5. 迴圈內的區域變數 (loopVar)
    • 生命週期:每次進入迴圈時分配記憶體,該次迴圈結束後釋放。
    • 作用範圍:僅限於迴圈內。

讀者目前應該瞭解了上述的概念。

前面有提到,單純傳數值進去(傳值),並不會影響原本的數值,哪有沒有甚麼方法是能夠直接修改到原本傳進來的變數呢?

這個方法叫做"傳址函式",不傳數值而改成傳入變數的位址,如此,在函式內就能直接對傳入的變數進行存取與修改。

下面我們示範一個數值交換函式:

#include <stdio.h>

// 函式宣告
void swap(int *a, int *b);

int main() {
int x = 5, y = 10;

printf("交換前:x = %d, y = %d\n", x, y);

// 傳址呼叫
swap(&x, &y);

printf("交換後:x = %d, y = %d\n", x, y);

return 0;
}

// 函式定義
void swap(int *a, int *b) {
int temp = *a; // 使用指標解參考,取得 a 指向的值
*a = *b; // 修改 a 指向的值
*b = temp; // 修改 b 指向的值
}

如此,就達到了直接修改傳入變數內容的目的了。(關於指標的觀念可以去觀看指標的那一章節)。


好,接著我必須再介紹一個不得不知道的函式觀念:遞迴。

遞迴

遞迴是甚麼呢? 遞迴是函式在執行過程中呼叫函式本身的一種技術。遞迴可以用來解決問題,特別是那些可以分解成較小規模的同類型問題的情況。 使用遞迴有兩個條件:

  • 結束條件
    • 遞迴需要有停止條件,用來避免無限遞迴。
    • 當滿足結束條件時,函式將不再呼叫自身,直接返回一個結果。
  • 遞迴條件
    • 將問題簡化並呼叫自身解決問題。
    • 通常將問題拆解成較小的子問題,直到達到結束條件。
返回值型別 函式名稱(參數) {
if (結束條件) {
return 結果; // 遞迴結束條件
} else {
遞迴呼叫; // 繼續呼叫自身
}
}

簡單觀念如下:

今天我們想要計算階乘,例如5!等於5X4X3X2X1,我們可以有以下的想法:

factorial(5) = 5 * factorial(4)
factorial(4) = 4 * factorial(3) //上面的factorial(4) = 4 * factorial(3),接著以此類推
factorial(3) = 3 * factorial(2)
factorial(2) = 2 * factorial(1)
factorial(1) = 1 (結束條件)
  • 可以注意到我們把問題一一分解成較小規模的同類型問題了。

最後我們依序把值帶回,求出數值

factorial(2) = 2 * 1 = 2
factorial(3) = 3 * 2 = 6
factorial(4) = 4 * 6 = 24
factorial(5) = 5 * 24 = 120 //最後得到答案的步驟
  • 所以最後數值就是5X(4X(3X(2X(1)))) = 1X2X3X4X5 = 120

程式範例:

#include <stdio.h>

// 遞迴函式定義
int factorial(int n) {
if (n == 0 || n == 1) {
return 1; // 結束條件:也要考慮0!得情況 : 0! = 1! = 1
} else {
return n * factorial(n - 1); // 繼續遞迴:n! = n * factorial(n-1)!
}
}

int main() {
int num = 5;
printf("%d 的階乘是:%d\n", num, factorial(num)); // 呼叫遞迴函式
return 0;
}
留言
avatar-img
留言分享你的想法!
avatar-img
電資鼠 - 您的學習好夥伴
8會員
206內容數
在當今數位時代,電資領域人才需求爆發式成長,不論是前端網頁設計、嵌入式開發、人工智慧、物聯網還是軟硬體整合,這些技術都在改變世界。而掌握 C/C++、Python、數位邏輯、電路學與嵌入式開發等大學電資領域的課程,正是進入這個高薪、高需求產業的關鍵!
2025/03/07
本章節將探討左下三角稀疏矩陣。
Thumbnail
2025/03/07
本章節將探討左下三角稀疏矩陣。
Thumbnail
2025/03/07
相信讀者現在對於鏈結串列有了更多的認識,所以我再進一步,示範更多關於鏈結串列的操作,這部分示範會將程式模組化。將鏈結串列的操作寫進一個標頭檔,並在主程式中引入。
Thumbnail
2025/03/07
相信讀者現在對於鏈結串列有了更多的認識,所以我再進一步,示範更多關於鏈結串列的操作,這部分示範會將程式模組化。將鏈結串列的操作寫進一個標頭檔,並在主程式中引入。
Thumbnail
2025/03/07
本章節示範透過「陣列索引」和「指標運算」兩種方式來存取同一個二維陣列 a,並印出相同的數值以及對應的位址,以說明它們其實指向的是同一塊連續的記憶體空間。本文將依序解釋各段程式碼,並示範可能的執行結果與背後原理。
Thumbnail
2025/03/07
本章節示範透過「陣列索引」和「指標運算」兩種方式來存取同一個二維陣列 a,並印出相同的數值以及對應的位址,以說明它們其實指向的是同一塊連續的記憶體空間。本文將依序解釋各段程式碼,並示範可能的執行結果與背後原理。
Thumbnail
看更多
你可能也想看
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
在這一章中,我們探討了 PHP 中的函數,包括函數的基本結構、不同的函數定義方式(如函數聲明、函數表達式、箭頭函數和匿名函數)以及如何呼叫函數。我們還討論了函數的參數處理方式,包括單個參數、多個參數、預設參數值和剩餘參數。此外,我們還介紹了函數的返回值,包括返回單個值、返回物件和返回函數的情況。
Thumbnail
在這一章中,我們探討了 PHP 中的函數,包括函數的基本結構、不同的函數定義方式(如函數聲明、函數表達式、箭頭函數和匿名函數)以及如何呼叫函數。我們還討論了函數的參數處理方式,包括單個參數、多個參數、預設參數值和剩餘參數。此外,我們還介紹了函數的返回值,包括返回單個值、返回物件和返回函數的情況。
Thumbnail
本章節主要介紹Java語言中的函數(也稱為方法)的使用,包括函數的基本結構、函數表達式(Lambda表達式)、箭頭函數、匿名函數的使用,以及如何呼叫函數、如何使用函數參數和函數的返回值等內容。通過學習本章節,讀者將能夠熟練掌握Java語言中的函數相關知識,並能夠在實際編程中靈活運用。
Thumbnail
本章節主要介紹Java語言中的函數(也稱為方法)的使用,包括函數的基本結構、函數表達式(Lambda表達式)、箭頭函數、匿名函數的使用,以及如何呼叫函數、如何使用函數參數和函數的返回值等內容。通過學習本章節,讀者將能夠熟練掌握Java語言中的函數相關知識,並能夠在實際編程中靈活運用。
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
本章節旨在介紹TypeScript中的函數,包括其基本結構、如何呼叫函數、函數的參數以及函數的返回值等相關概念。通過本章節,讀者可以學習到如何在TypeScript中使用不同的方式來定義函數,如函數聲明、函數表達式、箭頭函數和匿名函數等。
Thumbnail
本章節旨在介紹 C# 中函數的基本結構,包括訪問修飾符、返回類型、方法名稱、參數列表和方法體。同時,也介紹了函數的各種呼叫方式、參數傳遞方式和返回值類型。讀者可以通過本章節,深入理解 C# 中函數的使用和應用。
Thumbnail
本章節旨在介紹 C# 中函數的基本結構,包括訪問修飾符、返回類型、方法名稱、參數列表和方法體。同時,也介紹了函數的各種呼叫方式、參數傳遞方式和返回值類型。讀者可以通過本章節,深入理解 C# 中函數的使用和應用。
Thumbnail
C#程式由一或多個檔案組成,包含命名空間、類別、結構、介面、列舉和委派等型別。Main方法是C#應用程式的進入點。在C#中,註解用於在程式碼中添加說明,有單行和多行兩種類型。變數的定義需要指定變數的類型和名稱,可以一次為多個變數賦值。
Thumbnail
C#程式由一或多個檔案組成,包含命名空間、類別、結構、介面、列舉和委派等型別。Main方法是C#應用程式的進入點。在C#中,註解用於在程式碼中添加說明,有單行和多行兩種類型。變數的定義需要指定變數的類型和名稱,可以一次為多個變數賦值。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
Thumbnail
關於程式語言的學習,只要掌握住幾個基本特性要熟悉幾種程式語言也不困難,這三個基本特性就是…
Thumbnail
關於程式語言的學習,只要掌握住幾個基本特性要熟悉幾種程式語言也不困難,這三個基本特性就是…
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
介紹C++ 語法 資料型態,架構說明 程式語言為人類與電腦溝通的工具 程式設計流程: 定義問題 -> 問題分析 -> 撰寫演算法 ->程式撰寫 -> 程式執行及維護
Thumbnail
介紹C++ 語法 資料型態,架構說明 程式語言為人類與電腦溝通的工具 程式設計流程: 定義問題 -> 問題分析 -> 撰寫演算法 ->程式撰寫 -> 程式執行及維護
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News