# 東華大學資管系初階程式設計(進階題)112年考古 ## 相關資訊 課程代碼:IM__1120AA-初階程式設計 老師:劉英和教授 使用程式:C++ [初階考古](https://hackmd.io/@sumo0711/SyFipiOfA) ## 免責申明 :::danger 此文件僅為個人參考解答,並非標準答案。請僅供個人學習使用,切勿用於商業用途,如有侵權請寫信告知。 ::: ## 生活費 ### Description 小鳴剛上大學拿到人生第一份零用錢,他希望寫一支可以幫他計算每天預算的程式。 請你讓小鳴可以輸入他的生活費, 幫他除以剩餘的天數,算出他每天可以用多少(如果有小數則無條件捨棄)。 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) 請問您有多少生活費:**10000** 還剩下幾天需要過:**30** 您一天可以使用333元 ### Solution ```cpp= #include <iostream> using namespace std; int main() { int pocket_money, day; // 利用 int 型態無條件捨去小數點後面的數字 cout << "請問您有多少生活費:"; cin >> pocket_money; cout << "還剩下幾天需要過:"; cin >> day; pocket_money = pocket_money / day; cout << "您一天可以使用" << pocket_money << "元"; return 0; } ``` ## 時分秒 ### Description 「再等我15分鐘!」小依邊化著妝說著。 「每次等妳出門都好久」小鳴無奈。 「那等我900秒好了。」小鈴改口。 「ok!」小鳴覺得秒比分快多了,立刻答應。 仔細思考後,他就開始後悔了。 小鳴每次都無法快速轉換秒數和小時、分、秒,請你寫一個程式幫他吧! ### Example 參考執行畫面如下:(粗體字為使用者輸入的) 請輸入您要轉換的秒數:**4853** 轉換結果為: 1小時20分鐘53秒 ### Solution ```cpp= #include <iostream> using namespace std; int main() { int s, m, h, number; cout << "請輸入你想轉換的秒數:"; cin >> number; h = number / 3600; // 一小時為3600秒 number = number % 3600; // 將餘數帶回 number m = number / 60; // 一分鐘為60秒 s = number % 60; // 餘數為秒 cout << "轉換結果為:\n" << h << "小時" << m << "分鐘" << s << "秒"; return 0; } ``` ## 轉換電腦進位 ### Description 請編寫一個程式,接受使用者輸入一個十進位數字,然後將該數字轉換為二進位、八進位和十六進位的表示形式,並輸出結果。 提示: 可以使用適當的內建函數或自行編寫轉換函數來實現進制轉換。 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) 請輸入一個十進位數字:**42** 轉換結果: 二進位表示:101010 八進位表示:52 十六進位表示:2A ### Solution ```ccp= #include <iostream> #include <bitset> //bitset #include <iomanip> //setiosflags(ios::uppercase) using namespace std; int main() { int ten_number; cout << "請輸入一個十進位的數字:"; cin >> ten_number; cout << "轉換結果:\n"; bitset<100> b(ten_number); // 把10進位ten_number放到bitset進行轉換 string s = b.to_string(); // 轉換成string s.erase(0, s.find_first_not_of('0')); // 利用string函數去除前面的0 cout << "二進位表示:" << s << endl; // bitset<6> b(ten_number); // cout << "二進位表示:" << b << endl; // 原本寫的 cout << oct << "八進位表示:" << ten_number << endl; cout << setiosflags(ios::uppercase) << hex << "十六進位表示:" << ten_number; // setiosflags(ios::uppercase)將十六進位abc轉換成大寫ABC return 0; } ``` ## 字串 ### Description 請使用四種不同的方法的其中一種來實現以下多行字串: ``` Hello, World! This is a multiline string. It contains: - Bulleted - Nested - Items - And some code: int x = 10; int y = 20; int sum = x + y; ``` (四種方法分別為String Literals、Backslash Character和 Raw String Literals) #### String Literals \n = 換行 \t = tab #### Backslash Character \ = 接續上一行程式 #### Raw String Literals R"(能打任何字排版字串)" ### Example ``` Hello, World! This is a multiline string. It contains: - Bulleted - Nested - Items - And some code: int x = 10; int y = 20; int sum = x + y; ``` ### Solution ```cpp= #include <iostream> #include <string> using namespace std; int main() { cout << "Hello, World!\n\ This is a multiline string.\n\ It contains:\n\ \t- Bulleted\n\ \t\t- Nested\n\ \t\t\t- Items\n\ \t- And some code:\n\ \t\tint x = 10;\n\ \t\tint y = 20; int sum = x + y;"; return 0; } ``` ## 一元二次方程式 ### Description 寫一個幫忙解一元二次方程式的程式 (輸出的數字只到小數點第二位,且希望輸入一元二次方程式的a,b和c係數時,僅用空格隔開。) (使用三元運算符) ### Example 參考執行畫面如下:(粗體字為使用者輸入的) 請輸入一元二次方程式的係數a,b,c:**1 5 6** 方程式有兩個實根:-2.00 & -3.00 ### Solution ```cpp= #include <iostream> #include <iomanip> #include <cmath> // 數學函式庫 using namespace std; // 一般二元一次方程式: ax^2 + bx + c = 0 // 判别式的計算方式是: Δ = b^2 - 4ac // 其中,Δ表示判别式(discriminant),b是x的一次系數,a是x的二次系數,c是常數。 // 如果 Δ > 0,有兩個不相等的實根。 // 如果 Δ = 0,有兩個相等的實根。 // 如果 Δ < 0,沒有實根。 // 求解的公式 x = (-b ± √Δ) / (2a) int main() { double a, b, c, root1, root2, root3; cout << "請輸入一元二次方程式的係數a,b,c:"; cin >> a >> b >> c; double discriminant = b * b - 4 * a * c; int roots = (discriminant > 0) ? 2 : (discriminant == 0) ? 1 : 0; // discriminant = b^2 - 4ac // discriminant>0 roots=2 , discriminant=0 roots=1 , discriminant<0 roots=0 cout << "方程式"; switch (roots) { case 2: // roots=2 root1 = (-b + sqrt(discriminant)) / (2 * a); // x = (-b + √Δ) / (2a) root2 = (-b - sqrt(discriminant)) / (2 * a); // x = (-b - √Δ) / (2a) cout << "有兩個實根: " << fixed << setprecision(2) << root1 << " & " << root2; break; case 1: // roots=1 root3 = -b / (2 * a); cout << "有一個實根: " << fixed << setprecision(2) << root3; break; default: // roots=0 cout << "無實根"; break; } } ``` ### Verify 請輸入一元二次方程式的係數a,b,c:**1 -6 9** 方程式有一個實根: 3.00 請輸入一元二次方程式的係數a,b,c:**1 2 3** 方程式無實根 ## 三元運算符 ### Description 寫一個可以判斷輸入的三個數字是否可以組成一個三角形 (使用三元運算符) #### 三元運算符 if else 的另一種寫法 >(判斷式)?成立要做的事:否則做這個 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) 請輸入三個正整數: **3 4 5** 這三個數能組成一個三角形。 ### Solution ```cpp= #include <iostream> using namespace std; // 三角形不等式(Triangle Inequality)任意兩邊的總長度必須大於或等於第三邊的長度。 // 具體來說,對於一個三角形,假設三邊的長度分別為 a、b 和 c,則三角形不等式可以表達如下: // a + b > c // a + c > b // b + c > a // 如果這些不等式都成立,則這三個邊可以形成一個有效的三角形。 // 如果有任何一個不等式不成立,則無法構成三角形。 int main() { int a, b, c; cout << "請輸入三個正整數: "; cin >> a >> b >> c; cout << ((a + b > c) && (a + c > b) && (b + c > a) ? "這三個數能組成一個三角形。" : "這三個數無法組成一個三角形。"); } ``` ### Verify 請輸入三個正整數: **1 2 4** 這三個數無法能組成一個三角形。 ## Try-Catch ### Description 請設計一個程式, 可以幫忙處理克拉瑪法則的計算,克拉瑪法則是一種用於解線性方程的方法。 (需包含try catch來保護程式碼) ### Example 參考執行畫面如下:(粗體字為使用者輸入的) 請輸入第一個方程式的係數(a1,b1,c1): **2 3 2** 請輸入第二個方程式的係數(a2,b2,c2): **3 4 2** x的值為: -2 y的值為: 2 ### Solution ```cpp= #include <iostream> #include <stdexcept> // Try-catch using namespace std; // 克拉瑪公式 // 方程式一:a1X + b1Y = c1 // 方程式二:a2X + b2Y = c2 // Delta = (a1 * b2) - (a2 * b1) // X = (c1 * b2) - (c2 * b1) / Delta // Y = (c1 * a2) - (c2 * a1) / (a2 * b1) - (a1 * b2) // 條件一:若 Delta 不等於 0,則方程有一組解 X Y // 條件二:若 Delta = 0,但 X Y 至少有一個不為 0,方程式無解 // 條件三:若 Delta = X = Y = 0,方程式無限多解 int main() { try { double a1, a2, b1, b2, c1, c2, x, y; cout << "請輸入第一個方程式的係數(a1,b1,c1): "; if (!(cin >> a1) || !(cin >> b1) || !(cin >> c1)) // 判斷使用者輸入是否為整數 throw runtime_error("請輸入整數"); cout << "請輸入第二個方程式的係數(a2,b2,c2): "; if (!(cin >> a2) || !(cin >> b2) || !(cin >> c2)) // 判斷使用者輸入是否為整數 throw runtime_error("請輸入整數"); x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1); y = (c1 * a2 - c2 * a1) / (a2 * b1 - a1 * b2); if ((a1 * b2 - a2 * b1) == 0) // 判斷 Delta 是否為 0 { if ((x < 0) || (x > 0) || (y < 0) || (y > 0)) // 判斷 X Y 至少有一個不為 0 throw runtime_error("方程式無解"); else throw runtime_error("方程式無限多組解"); // X = Y = 0 } // 無錯誤印出 X Y 的值 cout << "x的值為: " << x << endl << "y的值為: " << y << endl; } catch (const runtime_error &e) // e 為 runtime_error 的變數 { cout << "錯誤: " << e.what() << endl; // 輸出錯誤訊息 } return 0; } ``` ### Verify 請輸入第一個方程式的係數(a1,b1,c1): **q 1 3** 錯誤: 請輸入整數 請輸入第一個方程式的係數(a1,b1,c1): **6 4 -18** 請輸入第二個方程式的係數(a2,b2,c2): **3 2 -1** 錯誤: 方程式無解 請輸入第一個方程式的係數(a1,b1,c1): **0 0 0** 請輸入第二個方程式的係數(a2,b2,c2): **0 0 0** 錯誤: 方程式無限多組解 ## 猜數字 ### Description 電腦以亂數產生一小於100的正整數(num),使用者不斷猜測該數(guess),每次猜測時電腦會提示猜的太大或太小,直到猜到或者猜超過五次為止。 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) Your guess? **50** Too high! Guess again!(remaining times: 5) **25** Too high! Guess again!(remaining times: 4) **12** Too low! Guess again!(remaining times: 3) **18** Too high! Guess again!(remaining times: 2) **15** Too low! Guess again!(remaining times: 1) **17** Too high! Game over! ### Solution ```cpp= #include <iostream> #include <ctime> #include <cstdlib> using namespace std; int main() { int num, Answer, guess_num = 6; srand(time(NULL)); // 取得時間序列 Answer = rand() % 100 + 1; // 取亂數 1-100 // rand() 生成一個隨機整數。 // %100 確保結果在0到99的範圍內。 // +1 然後將範圍移動到1到100。 cout << "Your guess?\n"; while (guess_num > 0) // 6 次猜數字的機會 { cin >> num; if (num == Answer) { cout << "Bingo!"; break; // 直到使用者猜到答案 跳出 while } else cout << ((num > Answer) ? "Too high!\n" : "Too low!\n"); // 如果使用者輸入大於 Answer 輸出 Too high! 否則輸出 Too low! guess_num -= 1; if (guess_num == 0) continue; // 如果 guess_num = 0 跳過這次迴圈 cout << "Guess again!(remaining times: " << guess_num << ")\n"; } if (guess_num == 0) // 如果猜滿五次還沒猜出 cout << "Game over!\n"; return 0; } ``` ## 消失的等差數列 ### Description 你穿越成為一名天才偵探,遇到一個極具挑戰性的任務。在古老的地圖上,標記了兩串有規律的數字(等差級數),代表寶藏的座標。這兩串數字是經過精心安排的,但其中有兩個數字(以*來表示)被小偷偷走,使得你無法直接找到寶藏的位置。然而,你聰明的頭腦讓你想到可以設計一個程式,透過找出這兩個缺失的數字,來找到小偷藏寶藏的位置。給定兩串整數陣列A和B,假設它們都有相同的長度N,且內容都是1到N的整數,代表寶藏的座標。請你設計一個程式,找出在陣列A和陣列B中缺失的兩個數字。這兩個缺失的數字就是小偷所偷走的座標,將它們輸出後,你將能找到寶藏的位置,並成功解開這個謎題。 〈提示:用等差級數的公式解〉 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) Please enter the array length: N=**10** 1 6 11 16 21 26 31 36 * 46 1 9 17 25 33 41 49 57 65 * A[] common difference = 5 B[] common difference = 8 The disappearing array is: A[8]=41 B[9]=73 ### Solution ```cpp= #include <iostream> #include <ctime> #include <cstdlib> using namespace std; int N, D_A, D_B; // 數列長度 AB數列公差 void Random(int &RemoveA_par, int &RemoveB_par, int &D_A_par, int &D_B_par); // 隨機取得要刪除陣列的數字 與 AB公差的值 void Initialize(int Initialize_A_par[], int Initialize_B_par[]); // 初始化AB陣列 void Sum_before(int &Total_A_Sum_par, int &Total_B_Sum_par); // 計算陣列和 int Sum_after(int Sum_par[]); // 把刪除陣列後的數值加起來 int main() { cout << "Please enter the array length:\nN="; cin >> N; // 輸入陣列長度 int A[N], B[N], RemoveA, RemoveB, MissA, MissB, Total_A_Sum, Total_B_Sum; Random(RemoveA, RemoveB, D_A, D_B); // 取得要刪除的陣列數字 與 AB公差的值 Initialize(A, B); // 初始化陣列 Sum_before(Total_A_Sum, Total_B_Sum); // 等差級數公式解 A[RemoveA] = 0; // 刪除陣列的值 B[RemoveB] = 0; MissA = Total_A_Sum - Sum_after(A); // 將原本的總和 - 刪除後的陣列總和 = 少掉的數字 MissB = Total_B_Sum - Sum_after(B); cout << "A[] common difference = " << D_A << endl // 印出公差 << "B[] common difference = " << D_B << endl; cout << "The disappearing array is:\nA[" << RemoveA << "]=" << MissA << "\tB[" << RemoveB << "]=" << MissB; return 0; } void Random(int &RemoveA_par, int &RemoveB_par, int &D_A_par, int &D_B_par) { srand(time(NULL)); // 取得時間序列 RemoveA_par = rand() % N; // 取得陣列要刪除的數字 RemoveB_par = rand() % N; D_A_par = rand() % 10 + 1; // 取得陣列差的數字 取 1-10 D_B_par = rand() % 10 + 1; } void Initialize(int Initialize_A_par[], int Initialize_B_par[]) { // G 為暫存值的變數 每增加一圈用複利的觀念 for (int i = 0, G = 0; i < N; i++, G += D_A) // 賦予陣列數值 Initialize_A_par[i] = G + 1; // 從 1 開始賦予 for (int i = 0, G = 0; i < N; i++, G += D_B) Initialize_B_par[i] = G + 1; } void Sum_before(int &Total_A_Sum_par, int &Total_B_Sum_par) { Total_A_Sum_par = N * (2 + (N - 1) * D_A) / 2; // 等差級數公式解 Total_B_Sum_par = N * (2 + (N - 1) * D_B) / 2; } int Sum_after(int Sum_par[]) { int sum = 0; for (int i = 0; i < N; i++) { if (Sum_par[i] == 0) // 如果碰到被移除的數字 就印出 * 顯示 cout << '*' << " "; else cout << Sum_par[i] << " "; sum += Sum_par[i]; // 把所有陣列數值相加 } cout << endl; return sum; } ``` ## 計算機 ### Description 請設計一個簡易的計算機程式,該程式能夠讓使用者選擇四種基本的算術運算:加法、減法、乘法和除法。程式將要求使用者輸入兩個整數數字,然後根據使用者選擇的運算符號執行相應的計算。如果選擇的是除法,並且第二個數字為零,則程式會輸出「Cannot divide by zero!」的錯誤訊息。 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) Select +, -, * and / : **+** Enter two integers: **2** **4** 6 ### Solution ```cpp= #include <iostream> using namespace std; void Input(int &num1, int &num2); int main() { try { int num1, num2; char choose; cout << "Select +, -, * and / :\n"; cin >> choose; if (choose == '+') { Input(num1, num2); cout << num1 + num2; } else if (choose == '-') { Input(num1, num2); cout << num1 - num2; } else if (choose == '*') { Input(num1, num2); cout << num1 * num2; } else if (choose == '/') { Input(num1, num2); if (num2 == 0) throw runtime_error("Cannot divide by zero!"); cout << num1 / num2; } else throw runtime_error("Undefined Input"); } catch (const runtime_error &e) // e 為 runtime_error 的變數 { cout << "Error: " << e.what() << endl; // 輸出錯誤訊息 } return 0; } void Input(int &num1, int &num2) { cout << "Enter two integers:\n"; cin >> num1 >> num2; } ``` ### Verify Select +, -, * and / : **/** Enter two integers: **9** **0** Error: Cannot divide by zero! Select +, -, * and / : **a** Error: Undefined Input ## 質數 ### Description 設計一個程式,讓使用者輸入一個正整數,列出所有小於它的質數並相加,輸出於螢幕。 ### Example 參考執行畫面如下:(粗體字為使用者輸入的) Please enter a positive integer: **20** The prime number is: 2 3 5 7 11 13 17 19 The sum is: 77 ### Solution ```cpp= #include <iostream> using namespace std; int main() { int prime, num, sum = 0; cout << "Please enter a positive integer:\n"; cin >> num; cout << "The prime number is:\n"; for (int i = 2; i <= num; i++) { prime = 1; // 讓prime在 j 迴圈完之後又回到1 for (int j = 2; j <= (i / 2); j++) { if (i % j == 0) prime = 0; } if (prime == 1) { cout << i << " "; sum += i; } } cout << endl << "The sum is: " << sum; return 0; } ``` ## 費氏數列 ### Description fib 費式數列 (請用RecursiveFunction撰寫) ### Example 參考執行畫面如下:(粗體字為使用者輸入的) Please enter the Fibonacci sequence to be calculated: **10** The value of Fibonacci sequence is: 55 ### Solution ```cpp= #include <iostream> using namespace std; // 費氏數列 // 公式 F(0)=0, F(1)=1, F(n)=F(n−1)+F(n−2) int fib(int n); int main() { int n; cout << "Please enter the Fibonacci sequence to be calculated:\n"; cin >> n; cout << "The value of Fibonacci sequence is:\n" << fib(n); return 0; } int fib(int n) { return (n == 0 || n == 1) ? n : (fib(n - 1) + fib(n - 2)); // n 為 0 或 1 時,直接返回 n,作為遞迴的終止條件。 } ``` ## 排列組合 ### Description 勇敢的冒險家在神秘森林尋找魔法寶藏。魔法石上有五個字母:“a”、“b”、“c”、“d”和“e"。解開所有字母的全部排列,就能啟動魔法力量。請你撰寫一支程式幫助冒險家。 (請用Recursive Function撰寫) ### Example a b c d e a b c e d a b d c e a b d e c a b e d c a b e c d a c b d e a c b e d a c d b e a c d e b a c e d b a c e b d a d c b e a d c e b a d b c e a d b e c a d e b c a d e c b a e c d b a e c b d a e d c b a e d b c a e b d c a e b c d b a c d e b a c e d b a d c e b a d e c b a e d c b a e c d b c a d e b c a e d b c d a e b c d e a b c e d a b c e a d b d c a e b d c e a b d a c e b d a e c b d e a c b d e c a b e c d a b e c a d b e d c a b e d a c b e a d c b e a c d c b a d e c b a e d c b d a e c b d e a c b e d a c b e a d c a b d e c a b e d c a d b e c a d e b c a e d b c a e b d c d a b e c d a e b c d b a e c d b e a c d e b a c d e a b c e a d b c e a b d c e d a b c e d b a c e b d a c e b a d d b c a e d b c e a d b a c e d b a e c d b e a c d b e c a d c b a e d c b e a d c a b e d c a e b d c e a b d c e b a d a c b e d a c e b d a b c e d a b e c d a e b c d a e c b d e c a b d e c b a d e a c b d e a b c d e b a c d e b c a e b c d a e b c a d e b d c a e b d a c e b a d c e b a c d e c b d a e c b a d e c d b a e c d a b e c a d b e c a b d e d c b a e d c a b e d b c a e d b a c e d a b c e d a c b e a c d b e a c b d e a d c b e a d b c e a b d c e a b c d ### Solution ```cpp= #include <iostream> using namespace std; void swap(char &a, char &b); void undo(char arr[], int start, int end); int main() { char abcde[5] = {'a', 'b', 'c', 'd', 'e'}; undo(abcde, 0, 4); return 0; } // 交換兩個字 void swap(char &a, char &b) { char temp = a; a = b; b = temp; } void undo(char arr[], int start, int end) { // 如果已經處理到最後一個元素,輸出排列 if (start == end) { for (int i = 0; i <= end; i++) { cout << arr[i] << " "; } cout << endl; } else { // 初始 start=0 end=4 逐一進行交換 for (int i = start; i <= end; i++) { // 交換位置 swap(arr[start], arr[i]); // 遞迴處理下一層 undo(arr, start + 1, end); // 恢復原始順序,準備下一次交換 swap(arr[start], arr[i]); } } } ```