## 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"; } ``` ::: ---