## 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
> 要怎麼印出下面的圖形??
>

##### 簡單的想法
```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. 再思考內層迴圈,每行要先輸出幾個??,再輸出幾個?? (要輸出的個數與外層迴圈的什麼變數有關?)
:::

:::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
> 要如印出下方的斜直線?
>

##### 想法一
> 控制輸出每層輸出空白的個數
```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」字形
>

::: 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)要怎麼設定條件

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

下方的程式可以讓使用者自己輸入到陣列再印出
```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";
}
```
:::
---