owned this note
owned this note
Published
Linked with GitHub
# Ch09 函式與遞迴
> 上一章: [Ch08 字串處理](https://hackmd.io/@sunfrancis12/ryI9bAsfa)
> 下一章: [Ch10 指標](https://hackmd.io/@sunfrancis12/B19JXRjGT)
> 回目錄: [NTCU程式戰鬥營C講義](https://hackmd.io/@sunfrancis12/ByfdXdjG6)
## Function 函式
函式在C語言中,有相當重要的地位,他可以避面許多繁瑣的步驟,並將自己的程式變得淺顯易懂。
像我們常用的`printf()`,`scanf()`,`strcmp()`也都是一種函式
**函式的特色:**
* 一段程式碼,執行特別的工作。
* 可重複使用
* 讓程式變得淺顯易懂
* 在呼叫函式不變的狀況下,可以直接修改程式。
> [C語言筆記 — 函式(Functions) @Sharon Peng](https://mycollegenotebook.medium.com/%EF%BD%83%E8%AA%9E%E8%A8%80%E7%AD%86%E8%A8%98-%E5%87%BD%E5%BC%8F-functions-cea21d86560f)
## 函式的結構
函式的宣告格式如下:
```c=
int my_function(int a,int b){
}
{回傳值變數型態} {函式名稱}(輸入的參數)
```
除此之外在函式的結尾,我們必須根據我們宣告的回傳值變數型態來`return`該變數型態的資料
同時也代表函式的運算結束
```c=
int my_function(int a,int b){
....
return a+b;
}
```
:::info
如果不希望函式回傳任何值得話,可以在`{回傳值變數型態}`填上`void`
:::
我們可以結合之前我們學到的程式片段,將他們打包成一個函式
```c=
//閏年判斷
void leap_year(int year){
if(((year%4==0) && (year%100!=0)) || (year%400==0)){
printf("%d年是閏年喔",year);
}else{
printf("%d年不是閏年喔",year);
}
return;
}
```
使用範例:
```c=
#include<stdio.h>
void leap_year(int year){
if(((year%4==0) && (year%100!=0)) || (year%400==0)){
printf("%d年是閏年喔\n",year);
}else{
printf("%d年不是閏年喔\n",year);
}
return;
}
int main(){
int year;
while(scanf("%d",&year)){
leap_year(year);
}
}
```
輸入內容:
```c=
123
352
611
2314
```
輸出結果:
```c=
123
123年不是閏年喔
352
352年是閏年喔
611
611年不是閏年喔
2314
2314年不是閏年喔
```
<a style="color:orange">【例題】</a>
> 請寫一個會回傳兩個數字最小值的函式
範例輸入:
```c=
40
59
```
範例輸出:
```c=
請輸入a的值: 40
請輸入b的值: 59
a和b的最小值為: 40
```
範例程式:
```c=
#include<stdio.h>
int min(int a,int b){
if(b<a) return b;
else return a;
}
int main(){
int a,b;
printf("請輸入a的值: ");
scanf("%d",&a);
printf("請輸入b的值: ");
scanf("%d",&b);
printf("a和b的最小值為: %d",min(a,b));
}
```
## 程式的重複執行結構
在程式裡面,有兩種程式的重複執行結構,分別是`recursive(遞迴)`以及`iterative(疊代)`
**recursive(遞迴)**
* 指一段程式(通常為一個function)呼叫自己
**iterative(疊代)**
* 指一段程式擁有迴圈的結構
## recursive遞迴
遞迴就是透過不斷呼叫自己(function)來完成類似迴圈重複執行的動作
其最大好處為減少程式碼的數量,並且程式邏輯上也比較直觀
**範例程式:**
分別使用`recursive(遞迴)`和`iterative(疊代)`完成一個計算n!的程式
**iterative(疊代)**
```c=
double iterFact(int n) {
if (n <= 1) return 1.0;
double answer = 1.0;
for (int i = 2; i <= n; i++)
answer *= i;
return answer;
}
```
**recursive(遞迴)**
```c=
double recurFact(int n) {
if (n <= 1) return 1.0;
return n * recurFact(n - 1);
}
```
使用遞迴的方式完成一個計算費氏數列的程式:
```c=
#include<stdio.h>
int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main(){
int num;
printf("請輸入你要計算費氏數列的第幾位: ");
scanf("%d",&num);
printf("費氏數列第%d位的結果為: %d",num,fibonacci(num));
}
```
範例輸入:
```c=
7
```
範例輸出:
```c=
請輸入你要計算費氏數列的第幾位: 7
費氏數列第7位的結果為: 13
```
<a style="color:orange">【例題】</a>
> 請使用遞迴的方式,寫一個可以判斷輸入整數是否為質數的function
範例輸入:
```c=
67
79
55
96
```
範例輸出:
```c=
請輸入: 67
67是質數
請輸入: 79
79是質數
請輸入: 55
55不是質數
請輸入: 96
96不是質數
```
範例程式:
```c=
#include<stdio.h>
int prime(int n,int divider){
if(divider<n && n%divider!=0) return prime(n,divider+1);
else return divider;
}
int main(){
int num;
printf("請輸入: ");
scanf("%d",&num);
if(num == prime(num,2)) printf("%d是質數",num);
else printf("%d不是質數",num);
}
```
---
> 上一章: [Ch08 字串處理](https://hackmd.io/@sunfrancis12/ryI9bAsfa)
> 下一章: [Ch10 指標](https://hackmd.io/@sunfrancis12/B19JXRjGT)
> 回目錄: [NTCU程式戰鬥營C講義](https://hackmd.io/@sunfrancis12/ByfdXdjG6)