---
tags: 語法
title: 函式&遞迴
---
:::success
# 函式 Function
## 宣告
### 回傳類別
```cpp=
// "dataType" "nameOfFunction"();
int func();
char func();
long long func();
float func();
bool func();
void func();
int* func();
```
- 在宣告時告知編譯器函式回傳值的資料類別
- 相當於在回傳前呼叫"dataType"()
- void : 無回傳值
### 形參 Parameter
```cpp=
//"dataType" "nameOfFunction"("dataType" "nameOfVariable");
int func(int num, bool vis);
bool func(int cnt = 0);
void init();
```
- 在宣告時告知編譯器呼叫函式時需要傳入的實參資料類別,並在呼叫時宣告一個屬於此函式的區域性變數來接收實參的值
- 可以先給定默認值,若呼叫時未傳入實參,則照順序套用默認值
- 小括號內為空則表示無需傳入實參
- 在上面的code中為"num","vis","cnt"等
## 程式定義
```cpp=
int add(int a, int b) {
return a+b;
}
```
- 若回傳型別不為void,至少要有一個return語句
- 可以呼叫全域變數或其他函式
## 呼叫
```cpp=
#include <cstdio>
using namespace std;
int add(int a, int b) {
return a+b;
}
int main(void) {
int math, english, ans;
scanf("%d %d", &math, &english);
//
ans = add(math, english);
//
printf("%d\n", ans);
return 0;
}
```
### 實參 Argument
- 呼叫函式時實際傳入的參數值
- 在上面的code中為"math"和"english"
## 宣告 -> 呼叫 -> 定義
```cpp=
#include <cstdio>
using namespace std;
int add(int a, int b);
int main(void) {
int math, english, ans;
scanf("%d %d", &math, &english);
//
ans = add(math, english);
//
printf("%d\n", ans);
}
int add(int a, int b) {
return a+b;
}
```
- 可以先告知編譯器函式的存在,使呼叫合法,再在主函式下補充定義
- 注意和"呼叫"標題下code的不同,前者同時完成了宣告和定義
- 可以在需要某個工具時先宣告,之後再來完善工具的code
## 參照 Reference
```cpp=
void swap(int &a, int &b) {
int temp;
temp = a;
a = b;
b = temp;
}
int main(void) {
int p, q;
scanf("%d %d", &p, &q);
swap(p, q);
printf("%d %d\n", p, q);
}
```
- 直接給予實參一個在此函式中使用的代稱,在函式程式中使用使用代稱會直接對位址修改實參的值
- 上面的code會將p與q的值互換並輸出
:::
:::success
# 遞迴 Recursion
## 定義
- 函式重複呼叫自身直到達到停止條件
- 相信每次遞迴都會得到正確結果 -> 有時比迴圈更直觀、更好理解
## 遞迴求最大公因數和最小公倍數
### 數學原理
- 以輾轉相除法求最大公因數,再由$gcd(a, b)\times lcm(a, b) = a\times b$求最小公倍數
- $\forall x,y\in \mathbb Z,x\ge y, gcd(x, y) = gcd(y, x\%y)$
- 重複直到其中一數為0,另一數即為$gcd(x, y)$
### 實作
- 停止條件:y為0
```cpp=
#include <cstdio>
using namespace std;
void swap(int &a, int &b) {
int temp;
temp = a;
a = b;
b = temp;
}
int gcd(int x, int y) {
if (y == 0) return x;
else return gcd(y, x%y); //顯然x%y < y
}
int main(void) {
int p, q, gcdAns, lcmAns;
scanf("%d %d", &p, &q);
if (p < q) swap(p, q); //保證第一次遞迴時x >= y
gcdAns = gcd(p, q);
lcmAns = p*q/gcdAns;
printf("%d %d\n", gcdAns, lcmAns);
}
```
:::