---
# System prepended metadata

title: 嘉科實中社團講義(114第1學期)

---

## 2025/10/17 
### 今日目標
* 宣告變數與變數型態
* C++中的運算子
* 邏輯運算閘道
* 迴圈的使用
---

### 變數宣告
在 C++ 中，變數宣告是告訴程式需要使用一個特定的變數名來儲存資料。每個變數必須指定其型態，型態決定了該變數能儲存什麼類型的資料。

### 變數型態
常見的變數型態有：
|型別|C語言表示法|格式化字串表示法|佔幾個位元組(byte)|值的範圍|
|---|---------|-------------|---------------|----------
|整數|int|%d|4|-2^31^~2^31^-1|
|浮點數|float|%f|4|2.939x10^−38^~3.403x10^38^|
||double|%lf|8|5.563x10^−309^~1.798x10^308^|
|字元|char|%c|1|-2^7^~2^7^-1|
|布林值|bool||4|{0,1}|
- `int`：整數型態
- `float`：單精度浮點數型態
- `double`：雙精度浮點數型態
- `char`：字符型態
- `bool`：布林型態 (True/False)

### 輸出語法
- `cin >>`:從鍵盤輸入值
- `cout <<`:從螢幕輸出變數

### 範例：
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    int age = 20;      // 整數型態變數
    float height = 5.9; // 浮點數型態變數
    char grade = 'A';   // 字符型態變數
    bool isGraduated = true; // 布林型態變數

    cout << "Age: " << age << endl;
    cout << "Height: " << height << endl;
    cout << "Grade: " << grade << endl;
    cout << "Graduated: " << isGraduated << endl;

    return 0;
}
```
:::


## 2. 運算子 (Operators)

C++ 支援各種運算符，常見的有：

- **算術運算子**：`+`, ` -`, ` *`, ` /(除法)`, ` %(取餘數)`
- **比較運算子**：`==`, ` !=`, ` >`, ` <`, ` >=`, ` <=`
- **邏輯運算子**：`&&(AND)`  , ` ||(OR)`  ,` !(NOT)` 

### 範例：
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    int a = 10, b = 20;

    // 算術運算符
    cout << "a + b = " << a + b << endl;
    cout << "a * b = " << a * b << endl;

    // 比較運算符
    cout << "a == b: " << (a == b) << endl;
    cout << "a != b: " << (a != b) << endl;

    // 邏輯運算符
    cout << "(a < b) && (b > 0): " << ((a < b) && (b > 0)) << endl;

    return 0;
}
```
:::

## 3. 邏輯閘道 (Logical Gates)

邏輯閘道是一種數位邏輯運算，主要有：

- **AND (與)**：`&&`
- **OR (或)**：`||`
- **NOT (非)**：`!`

### 範例：
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    bool A = true, B = false;

    cout << "A && B = " << (A && B) << endl;  // AND
    cout << "A || B = " << (A || B) << endl;  // OR
    cout << "!A = " << !A << endl;            // NOT

    return 0;
}
```
:::

## 4. `while` 迴圈

`while` 迴圈會在條件為 `true` 時重複執行某段程式碼。

### 範例：
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    int count = 0;

    while (count < 5) {
        cout << "Count: " << count << endl;
        count++;
    }

    return 0;
}
```
:::

## 5. `for` 迴圈

`for` 迴圈通常用來在已知執行次數的情況下執行某段程式碼。

### 範例：
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    for (int i = 0; i < 5; i++) {
        cout << "i: " << i << endl;
    }

    return 0;
}
```
:::

## 6. 比較 `while` 和 `for` 迴圈

- **`while` 迴圈**：當條件為真時重複執行，適合條件未知或不確定次數的情況。
- **`for` 迴圈**：通常用於已知確定次數的情況，特別是循環次數是固定的。

## 7. 條件式 if else if else
```cpp
#include <iostream>
using namespace std;

int main() {
    int i = 0;
    if(i==0){
        cout << "i為0";
    }
    else if(i==2){
        cout << "i為1";
    }
    else{
        cout << "i不為1也不2";
    }
}
```

### 範例比較：
:::spoiler
```cpp=
#include <iostream>
using namespace std;

int main() {
    // 使用 while 迴圈
    int i = 0;
    while (i < 5) {
        cout << "While i: " << i << endl;
        i++;
    }

    // 使用 for 迴圈
    for (int j = 0; j < 5; j++) {
        cout << "For j: " << j << endl;
    }

    return 0;
}
```
:::
# APCS題目練習
- **來源APCS歷屆試題**
 
### 第一題
```cpp
#include <iostream>
using namespace std;

int main() {
    int a = 2, b = 3;
    int c = 4, d = 5;
    int val;

    val = b / a + c / b + d / b;
    cout << val << endl;

    return 0;
}
```

上述程式的執行結果為何?
(a.)3
(b.)4
(c.)5
(d.)6

---
### 第二題
```cpp
#include <iostream>
using namespace std;

int main() {
    int a = 5;

    for (int i = 0; i < 20; i = i + 1) {
        i = i + a;
        cout << i;
    }

}
```
上述程式的輸出結果為何?
(a.)5 10 15 20
(b.)5 11 17 23
(c.)6 12 18 24
(d.)6 11 17 22

---
### 實作題
請用以上所學試著寫一個程式:
當你輸入一個正整數後，給予對應的評分等第。
80 ~ 100  輸出'A'
70 ~ 79   輸出'B'
60 ~ 69   輸出'C'
0 ~ 59    輸出'F'

## 2025/10/31
### 學習資源推薦
- [嘉科實中社團講義(113第1學期)](https://hackmd.io/lET1Jb4eRdCFQizaaFQ3-w)
- [AP325](https://drive.google.com/drive/folders/10hZCMHH0YgsfguVZCHU7EYiG8qJE5f-m) 作者: 吳邦一
### 今日目標
* 去報名APCS！！！
（「2026年01月04日檢測」：2025/11/03～2025/12/05，每日 9:00至18:00。） {%preview https://apcs.csie.ntnu.edu.tw/index.php/2025/10/20251028/ %}
* 加入LINE群體
* 複習上次上課的內容
* 了解巢狀迴圈的概念
* 了解如何使用陣列

### 複習內容
* 資料型態(整數、浮點數、字元、布林值)
* 輸入 cin >> ; cout << ;
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    cout << "打想顯示的文字" << endl; // endl代表換行
    cout << "文字1" << endl << "文字2" << endl << "文字3" << endl; //也可以這樣
    int example1, e2, e3;
    cin << example1; //cin 要先宣告變數 這裡的example是整數型態
    cin << example1 << e2 << e3; // 輸入三個變數    
}
```
:::
* 宣告符號 與 等於符號 分別是甚麼?
* 邏輯運算(and or not 或是 && || !)
* while迴圈
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    while(條件(通常會有<,>,==,!=,and,or 等會產出bool的東西)){
        // 如果條件為True才會執行迴圈裡面的東西
        // 否則會跳到section 2

        // 想重複執行的動作

        // 終止條件
        // 方法1:如使用 break;(通常搭配if使用)
        // 方法2:改變你的條件變數 例如 i++; i--; 等等方式
    }
    // section 2
}
```
:::
* for迴圈 (通常已知要重複使用幾次)
:::spoiler
```cpp
#include <iostream>
using namespace std;

int main() {
    for(初始值 如int i = 0;執行條件e.g. i < 3; 改變變數e.g. i+= 3(最後才會到這)) { 
        //注意是;不是,哦!!!!
        
        // 想重複執行的動作

        // 終止條件
        // 使用 break;(通常搭配if使用)
    } 
    // section 2
}
```
:::
### 巢狀迴圈

#### 雙重迴圈使用範例1

> 要怎麼印出下面的圖形？？
> 
![image](https://hackmd.io/_uploads/BJC8_I00gx.png)

##### 簡單的想法

```cpp=
#include <iostream>
using namespace std;

int main() 
{
    cout << "*" << endl;
    cout << "**" << endl;
    cout << "***" << endl;
    cout << "****" << endl;
    cout << "*****" << endl;
    return 0;
}
```


> 這樣的想法會遇到什麼問題？？？

##### 聰明的寫法
```cpp=
#include <iostream>
using namespace std;

int main() 
{
    for(int i = 1 ; i <= 5 ; ++i){      // 控制輸出的行數
      for(int j = 1 ; j <= i ; ++j){    // 控制每行輸出的個數
        cout << "*" ;
      }
      cout << endl; // cout << '\n';
    }
    return 0;
}
```
下面是可以讓使用者控制層數的版本
```cpp=
#include <iostream>
using namespace std;

int main() {
    int n; // n 代表要有n層
    cout << "請輸入要印出幾層：" ;
    cin >> n;
    
    for(int i = 1 ; i <= n ; ++i){      // 控制輸出的行數
      for(int j = 1 ; j <= i ; ++j){    // 控制每行輸出的個數
        cout << "*" ;
      }
      cout << endl; // cout << '\n';
    }
    return 0;
}
```

#### 練習題1
> 要怎麼印出下面的圖形？？

:::info
1. 先想出一共有幾層，哪一層迴圈控制層數
2. 再思考內層迴圈，每行要先輸出幾個??，再輸出幾個?? （要輸出的個數與外層迴圈的什麼變數有關？）
:::

![image](https://hackmd.io/_uploads/B1JGsLRAel.png)
:::spoiler 參考答案
```cpp=
#include <iostream>
using namespace std;

int main() 
{
    for(int i = 1 ; i <= 5 ; ++i){
      for(int j = 1 ; j <= 5 - i ; j++){
        cout << " ";
      }
      for(int k = 1 ; k <= i ; ++k){
        cout << "*" ;
      }
      cout << endl; // cout << '\n';
    }
    return 0;
}
```
:::

#### 雙重迴圈使用範例2
> 要如印出下方的斜直線？
> 
![image](https://hackmd.io/_uploads/SkzzzvC0xe.png)



##### 想法一
> 控制輸出每層輸出空白的個數
```cpp=
#include <iostream>
using namespace std;

int main() {

    for(int i = 1 ; i <= 5 ; ++i){
        for(int j = 1 ; j <= i - 1 ; ++j){
            cout << " ";
        }
        cout << "*" << endl; 
    }
    
    return 0;
}
```

##### 想法二
> 用類似直線方程式(y = x)的想法
```cpp=
#include <iostream>
using namespace std;

int main() {

    for(int i = 1 ; i <= 5 ; ++i){
        for(int j = 1 ; j <= 5 ; ++j){
            if(i == j){
                cout << "*";
            }
            else{
                cout << " ";
            }
        }
        cout << endl;
    }
    
    return 0;
}
```

#### 練習題2
> 請讓使用者先輸入總共幾層，之後再去印出一個「X」字形
> 
![image](https://hackmd.io/_uploads/HyAv0LACgg.png)

::: spoiler 參考解答
```cpp=
#include <iostream>
using namespace std;

int main() {
    int n; // n 代表要有n層
    cout << "請輸入要有幾層：" ;
    cin >> n;
    
    for(int i = 1 ; i <= n ; ++i){
        for(int j = 1 ; j <= n ; ++j){
            if(i == j || j == n - i + 1){
                cout << "*";
            }
            else{
                cout << " ";
            }
        }
        cout << endl;
    }
    
    return 0;
}
```
:::
#### 觀念題練習
題目取自：[APCS範例試題](https://apcs.csie.ntnu.edu.tw/wp-content/uploads/2025/09/%E7%A8%8B%E5%BC%8F%E8%AD%98%E8%AE%80_%E9%A1%8C%E7%9B%AE%E7%AF%84%E4%BE%8B_C%E9%A1%8C%E6%9C%AC_0912.pdf)

若程式要輸出的圖案如下，請問我的程式碼第四行的(a)要怎麼設定條件
![image](https://hackmd.io/_uploads/BJgz3v00gg.png)
```cpp=
for (int i=0; i<=3; i=i+1) {
    for (int j=0; j<i; j=j+1)
        cout << " ";
    for (int k=6-2*i; (a) ; k=k-1)
        cout << "*";
        cout << endl;
}
```

- ( A ) k > 2
- ( B ) k > 1
- ( C ) k > 0
- ( D ) k >－1





### 陣列使用
> 陣列是用於儲存很多相同型態的變數

#### 使用範例
`陣列`的宣告方式跟一般變數宣告很像，只是後面要多加`[]`並且裡面要放上代表`要儲存幾個值`，**陣列的`索引值`是從0開始**
```cpp=
#include <iostream>
using namespace std;
int main(){
    int height[4] = {168, 170, 165, 160};
    //宣告height陣列裡面可以存放4個整數


    /*
    索引值          0     1     2     3

    記憶體位址     0x01  0x05  0x09  0x13
                |-----|-----|-----|-----|
                | 168 | 170 | 165 | 160 |
                |-----|-----|-----|-----|  
    */  

    cout << "height[0]的值 = " << height[0] << "endl" << "height[0]的記憶體位址 = " << &height[0] <<endl;
    cout << "height[1]的值 = " << height[1] << "endl" << "height[1]的記憶體位址 = " << &height[1] <<endl;
```
![image](https://hackmd.io/_uploads/H1YA8vARll.png)


下方的程式可以讓使用者自己輸入到陣列再印出
```cpp=
#include <iostream>
using namespace std;
int main(){
    int height[4];

    for(int i = 0;i<4;i++){
        cin >> height[i];  
    }

    for(int i = 0;i<4;i++){
        cout << i << " : " << height[i];
    }
    return 0;
}
```

下方的程式可以找到陣列面的最大值
```cpp=
#include <iostream>
using namespace std;
int main(){
    int height[4] = {168,170,165,160};
    int max_height;

    for(int i = 0;i<4;i++){
        if(i == 0){
            max_height = height[0];
        }
        else if(height[i]>max_height){
            max_height = height[i];
        }
    }
    cout << "最高的身高 = " << max_height << endl;

    return 0;
}
```
#### 練習題
> 請寫出一個程式可以滿足以下需求
1. 讓使用者先輸入陣列裡面要有幾個數字
2. 讓使用者輸入數字到陣列裡面
3. 在陣列裡面找到「最小值」

##### 程式架構
```cpp=
#include <iostream>
using namespace std;
int main(){
    
    int n;
    
    cout << "請輸入陣列裡面要有幾個數字：";
    // 請完成讓使用者輸入裡面要有幾個數字
    
    int arr[n]; // 這個寫法在某些版本的編譯器不能這樣寫
    
    // 請完成讓使用者輸入數字到陣列裡面
    
    int min_value;
    // 請完成在陣列裡面找到最小值
    
    cout << "最小值 = " << min_value;
    
    return 0;
    
}
```

::: spoiler 參考解答
```cpp=
#include <iostream>
using namespace std;
int main(){
    
    int n;
    
    cout << "請輸入陣列裡面要有幾個數字：";
    cin >> n;
    int arr[n]; // 這個寫法在某些版本的編譯器不能這樣寫
    
    for(int i = 0 ; i < n ; ++i){
        cin >> arr[i];
    }
    
    int min_value = arr[0];
    
    for(int i = 1 ; i < n ; ++i){
        if(arr[i] < min_value){
            min_value = arr[i];
        }
    }
    
    cout << "最小值 = " << min_value;
    
    return 0;
    
}
```


:::

## 2025/12/12
### 學習資源推薦
- [嘉科實中社團講義(113第1學期)](https://hackmd.io/lET1Jb4eRdCFQizaaFQ3-w)

### 今日目標

* 複習上次上課的內容
* 了解陣列的應用
* 二分搜尋法、泡沫排序法
* 學會撰寫函式(Function)  
* 了解傳值與傳址  
* 了解遞迴(Recursion)  
* 練習題

---

### 陣列進階

#### 範例1
##### 計算陣列總和
```cpp
#include <iostream>
using namespace std;

int main() {
    int arr[5] = {3, 7, 2, 9, 10};
    int sum = 0;

    for(int i = 0; i < 5; i++){
        sum += arr[i];
    }

    cout << "總和 = " << sum << endl;
}
```

---

#### 範例2
##### 找出陣列最大值與最小值
```cpp
#include <iostream>
using namespace std;

int main() {
    int arr[5] = {12, 3, 8, 20, 7};
    int max = arr[0];
    int min = arr[0];

    for(int i = 1; i < 5; i++){
        if(arr[i] > max) max = arr[i];
        if(arr[i] < min) min = arr[i];
    }

    cout << "最大值 = " << max << endl;
    cout << "最小值 = " << min << endl;
}
```

---

#### 範例3
##### 計算特定值出現次數
```cpp
#include <iostream>
using namespace std;

int main() {
    int arr[8] = {1, 2, 1, 3, 4, 1, 5, 1};
    int target = 1;
    int count = 0;

    for(int i = 0 ; i < 8 ; i++){
        if(arr[i] == target){
            count++;
        }
    }

    cout << target << " 出現次數 = " << count;
}
```

---

### 動態陣列 vector

:::info
使用 vector<array_type>可讓整體陣列使用更加彈性。
:::

### Vector 基礎教學

`vector` 可以把它想像成「會自動長大的陣列」，不需要預先決定大小，也不會因為空間不足而爆掉，非常適合輸入筆數不確定的題目。

---

#### 1. vector 的幾項簡易指令

##### 建立 vector
```cpp
vector<int> v;         // 建立空 vector
vector<int> v2(5);     // 建立有 5 個元素的 vector（預設值 0）
vector<int> v3 = {1,2,3};
```

---

##### 新增值：push_back()
```cpp
v.push_back(10);
v.push_back(20);
// v = {10, 20}
```

---

##### 取得目前陣列大小：size()
```cpp
cout << v.size();
```

---

##### 讀取或修改值：v[i]
```cpp
cout << v[0];
v[1] = 99;
```

---

##### 刪除最後一個元素：pop_back()
```cpp
v.pop_back();
```

---

##### 清除所有元素：clear()
```cpp
v.clear();
```

---

#### 2. 小範例：讀入成績並找最大值

> 題目：輸入 n，代表成績數量，再輸入 n 個成績，最後輸出最大值。

####  vector版本

:::spoiler 參考程式碼（vector 版本）
```cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n;
    cout << "請輸入有幾筆成績：";
    cin >> n;

    vector<int> score;   // 建立空 vector

    // 讀入成績
    for(int i = 0; i < n; i++){
        int x;
        cin >> x;
        score.push_back(x);
    }

    // 找最大值
    int max = score[0];
    for(int i = 1; i < score.size(); i++){
        if(score[i] > max){
            max = score[i];
        }
    }

    cout << "最高分 = " << max << endl;
    return 0;
}
```
:::

---


####  array版本

:::warning
array 必須「先決定最大長度」，不適合輸入筆數不確定的情況。
:::

:::spoiler 參考程式碼（array 版本）
```cpp
#include <iostream>
using namespace std;

int main() {
    int n;
    cout << "請輸入有幾筆成績：";
    cin >> n;

    int score[1000];  // 假設最多 1000 筆資料

    // 讀入成績
    for(int i = 0; i < n; i++){
        cin >> score[i];
    }

    // 找最大值
    int max = score[0];
    for(int i = 1; i < n; i++){
        if(score[i] > max){
            max = score[i];
        }
    }

    cout << "最高分 = " << mx << endl;
    return 0;
}
```
:::

---

#### 為什麼 vector 比 array 好用？

| 方法 | vector | array |
|------|--------|--------|
| 可自動變大 | 是 |  否 |
| 要不要先知道數量 |  不用 |  要 |
| 新增元素 | push_back() | 不支援 |
| 取得長度 | size() | 需要自己記 |
| 記憶體安全性 | 高（可擴容） | 低（可能爆掉） |

> **一句話總結：vector 更安全、更彈性。**

---

## 2025/12/26
### 學習資源推薦
- [嘉科實中社團講義(113第1學期)](https://hackmd.io/lET1Jb4eRdCFQizaaFQ3-w)

### 今日目標

* 複習上次上課的內容
* 了解陣列的應用
* 二分搜尋法、泡沫排序法
* 學會撰寫函式(Function)  
* 了解傳值與傳址  
* 了解遞迴(Recursion)  
* 練習題

---

### 二分搜尋（Binary Search）

#### 1. 基本概念

二分搜尋是一種**在「已排序」資料中**尋找目標值的高效率方法。核心想法是：

1. 先看中間元素 `mid`
2. 如果 `mid` 等於目標 → 找到
3. 如果 `mid` 比目標大 → 目標在左半邊
4. 如果 `mid` 比目標小 → 目標在右半邊
5. 重複直到範圍縮小到沒有元素

#### 2. 範例

```cpp
#include <iostream>
using namespace std;

int main() {
    int a[7] = {2, 5, 8, 12, 16, 23, 38};
    int target = 16;

    int left = 0;
    int right = 6;
    int mid;
    int found = -1; // 用來記錄找到的位置

    while (left <= right) {
        mid = (left + right) / 2;

        if (a[mid] == target) {
            found = mid;
            break;
        } else if (a[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    if (found != -1) {
        cout << "找到目標，位置在 index = " << found << endl;
    } else {
        cout << "找不到目標" << endl;
    }

    return 0;
}

```
---

### 泡沫排序（Bubble Sort）

#### 1.基本概念

泡沫排序是一種**非常直覺的排序方法**，適合初學者學習排序觀念。

它的想法是：

- 從左到右比較「相鄰」的兩個數字
- 如果前面的數字比後面大，就交換
- 每一輪結束後，**最大的數字會被推到最右邊**
- 重複多輪，直到整個陣列有序

就像泡泡慢慢往上浮，所以叫「泡沫排序」。

#### 2.範例
```cpp
#include <iostream>
using namespace std;

int main() {
    int a[4] = {5, 1, 4, 2};
    int n = 4;

    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1; j++) {
            if (a[j] > a[j + 1]) {
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }

    // 輸出排序後結果
    for (int i = 0; i < n; i++) {
        cout << a[i] << " ";
    }

    return 0;
}

```
---

### 函式（Function）

#### 1. 無參數、無回傳值
```cpp
void hello() {
    cout << "Hello World\n";
}

int main() {
    hello();
}
```

---

#### 2. 有參數、無回傳值
```cpp
void printTwice(int x) {
    cout << x << " " << x << endl;
}

int main() {
    printTwice(7);
}
```

---

#### 3. 有參數、有回傳值
```cpp
int add(int a, int b) {
    return a + b;
}

int main() {
    cout << add(3, 5); // 8
}
```

#### 思考：函式裡宣告的變數，能在 main 裡使用嗎？

在函式內部宣告的變數稱為 **區域變數（local variable）**。  
區域變數只在「它所在的函式」裡面有效，離開函式就消失了。

例如：

```cpp
int add(int a, int b) {
    int c = a + b;  // c 是 add() 函式的區域變數
    return c;
}

int main() {
    cout << c;  //  error！main() 看不到 c
}
```



這種錯誤即為：

> **使用了不存在於該作用域的變數**

---

#### ✔ 改成正確版本（透過 return 回傳結果）

既然 main 看不到 add 裡的變數，那就應該：

1. 在 add 裡面計算  
2. 用 return 把結果帶回來  
3. main 接收結果並使用  

```cpp
int add(int a, int b) {
    int c = a + b;
    return c;  // 回傳 c 的值，而不是回傳變數本身
}

int main() {
    int result = add(3, 5);  // 額外宣告變數來接收回傳值
    cout << result;          // 8
}
```

---

###  全域變數 vs 區域變數：概念比較

| 特性 | 區域變數 Local | 全域變數 Global |
|------|----------------|------------------|
| 宣告位置 | 函式或區塊 `{}` 內 | 所有函式外 |
| 使用範圍 | 僅限該函式/區塊 | 整個程式 |
| 生命週期 | 執行到該區塊結束就消失 | 程式開始到程式結束 |
| 可否與其他函式同名變數不衝突？ | 可以 |  不行 |

---

### 思考範例：同名變數時，誰會優先？

```cpp
int x = 100;   // 全域變數

int main() {
    int x = 5;  // 區域變數（會遮蔽全域變數）
    cout << x;  // 輸出 5，而不是 100
}
```

### Shadowing（變數遮蔽）：
區域變數「會遮蔽」全域變數，因此在 main() 裡優先使用自己的 x。

---

### 小重點

- **函式裡宣告的變數，在函式外無法使用（因為是區域變數）**  
- 要把結果帶出去，就必須用 **return 回傳值**  
- main() 想要使用結果，就必須用額外的變數接住 return 的內容

---

### 傳值與傳址（Call by Value / Call by Reference）

#### 傳值（call by value）
:::warning
傳值 → 傳進去的是複製品，函式內修改不會改到外面。
:::

```cpp
void test(int x){
    x = 100;
}

int main(){
    int a = 5;
    test(a);
    cout << a; // 仍然是 5
}
```

---

#### 傳址（call by reference）
:::success
傳址 → 直接修改本尊！
:::

```cpp
void test(int &x){
    x = 100;
}

int main(){
    int a = 5;
    test(a);
    cout << a; // 變 100
}
```

---

### 遞迴（Recursion）

#### 遞迴觀念
* 函式自己呼叫自己  
* 必須有「終止條件」  
* 每次呼叫問題要變小  

---


#### 範例 1：費氏數列 Fibonacci
```cpp
int fib(int n){
    if(n == 0) return 0;
    if(n == 1) return 1;
    return fib(n-1) + fib(n-2);
}
```

樹狀圖如下：

```
                          fib(4)
                       /           \
                 fib(3)             fib(2)
               /       \           /       \
          fib(2)      fib(1)   fib(1)    fib(0)
         /     \
    fib(1)   fib(0)
```

---

#### 範例 2：階乘 factorial
```cpp
int fact(int n){
    if(n == 1) return 1;   // base case
    return n * fact(n - 1);
}

int main(){
    cout << fact(5); // 120
}
```

---


#### 範例 3：印出 1 到 n
```cpp
void printNum(int n){
    if(n == 0) return;
    printNum(n - 1);
    cout << n << " ";
}

int main() {
    printNum(5); // 1 2 3 4 5
}
```

---

### 小試身手

#### 練習 1：陣列與函式綜合題
請完成以下需求：
1. 輸入 n  
2. 輸入 n 個數字  
3. 使用「四個函式」分別輸出：  
   - 陣列最大值  
   - 陣列最小值  
   - 奇數總和  
   - 偶數的數量  

:::spoiler 參考解答
```cpp
#include <iostream>
#include <vector>
using namespace std;

int getMax(const vector<int>& v){
    int mx = v[0];
    for(int i = 1; i < v.size(); i++){
        if(v[i] > mx) mx = v[i];
    }
    return mx;
}

int getMin(const vector<int>& v){
    int mn = v[0];
    for(int i = 1; i < v.size(); i++){
        if(v[i] < mn) mn = v[i];
    }
    return mn;
}

int sumOdd(const vector<int>& v){
    int sum = 0;
    for(int x : v){
        if(x % 2 != 0) sum += x;
    }
    return sum;
}

int countEven(const vector<int>& v){
    int cnt = 0;
    for(int x : v){
        if(x % 2 == 0) cnt++;
    }
    return cnt;
}

int main(){
    int n;
    cin >> n;

    vector<int> v(n);
    for(int i = 0; i < n; i++){
        cin >> v[i];
    }

    cout << "最大值 = " << getMax(v) << endl;
    cout << "最小值 = " << getMin(v) << endl;
    cout << "奇數總和 = " << sumOdd(v) << endl;
    cout << "偶數數量 = " << countEven(v) << endl;

    return 0;
}
```
:::

---

#### 練習 2：遞迴計算數字各位數的總和
範例：  
輸入：12345  
輸出：15  

:::spoiler 參考解答
```cpp
#include <iostream>
using namespace std;

int digitSum(int x){
    if(x < 10) return x;
    return digitSum(x / 10) + (x % 10);
}

int main(){
    int x;
    cin >> x;
    cout << digitSum(x);
}
```
:::

---

#### 練習3 :回文判斷（Palindrome）

回文：字串從左念與從右念都一樣。  
例如：

- level → 回文  
- radar → 回文  
- abcba → 回文  
- apple → 不是回文  

---

##### 基本版：使用迴圈判斷回文

原理：

1. 使用兩個`索引(index)`：`i` 從左邊開始，`j` 從右邊開始  
2. `s[i]` 與 `s[j]` 不相等 → 不是回文  
3. 若全部相等 → 是回文  

:::spoiler 參考解答

```cpp
#include <iostream>
#include <string>
using namespace std;

bool isPalindrome(string s){
    int i = 0;
    int j = s.size() - 1;

    while(i < j){
        if(s[i] != s[j])
            return false;
        i++;
        j--;
    }
    return true;
}

int main(){
    string s;
    cin >> s;

    if(isPalindrome(s))
        cout << "Yes";
    else
        cout << "No";
}
```
:::

---

#### 遞迴版：使用遞迴判斷回文

遞迴的概念：

- 若頭尾不同 → 不是回文  
- 若頭尾相同 → 繼續檢查中間的字串  
- 字串縮小到只剩 0 或 1 個字元 → 必定是回文  

:::spoiler 參考解答

```cpp
#include <iostream>
#include <string>
using namespace std;

bool isPalindrome(string s, int i, int j){
    if(i >= j) return true;           // base case
    if(s[i] != s[j]) return false;    // 頭尾不同 → 不是回文
    return isPalindrome(s, i+1, j-1); // 縮小範圍
}

int main(){
    string s;
    cin >> s;

    if(isPalindrome(s, 0, s.size()-1))
        cout << "Yes";
    else
        cout << "No";
}
```
:::

---


