---
# System prepended metadata

title: 函式&遞迴
tags: [語法]

---

---
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);
}
```

:::