107 高普考高考三級 資訊處理 程式語言 考古題詳解

107 年・高普考・高考三級・資訊處理
試題代碼 程式語言

第 一 題20 分

以下二小題是完整的 C/C++ 程式碼,請回答執行的結果為何?(每小題 10 分,共 20 分)

(一)

#include <stdio.h> #include <stdlib.h>

int recFun(int);

int main(void) { printf("%d\n", recFun(12345));

return 0;

}

int recFun(int n) { if (n < 10) return n; else return recFun(n / 10) + n % 10; }

(二)

#include <iostream> #include <cstdlib> #include <string> using namespace std;

struct data { string name; int a, b; };

void fun1(struct data), fun2(struct data *), fun3(struct data);

int main(void) { struct data man = {"John", 11, 33}, lady = {"Linda", 22, 44};

cout << "After process..." << endl;
fun2(&man);
fun3(lady);
fun1(man);
fun1(lady);

return 0;

}

void fun1(struct data in) { cout << "Name: " << in.name << endl; cout << "a=" << in.a << ", "; cout << "b=" << in.b << endl; }

void fun2(struct data *ptr) { int tmp;

tmp = ptr->a;
ptr->a = ptr->b;
ptr->b = tmp;

}

void fun3(struct data in) { int tmp;

tmp = in.a;
in.a = in.b;
in.b = tmp;

}

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

  1. 遞迴函數(Recursive Function):函式在執行過程中直接或間接呼叫自身。一個正確的遞迴函式必須具備「終止條件(Base Case)」與「遞迴關係(Recursive Step)」,以避免無窮遞迴導致堆疊溢位(Stack Overflow)。
  2. 整數除法與餘數運算:在 C/C++ 中,整數除法 / 會無條件捨去小數點(截尾取整);餘數運算子 % 可取出被除數除以除數後的餘數。
  • n % 10:取得十進位整數 nn 的個位數字(最低有效位)。
  • n / 10:消除十進位整數 nn 的個位數字,將高位數字向右位移一位。

解題方法

本題定義遞迴函式 recFun(int n) 如下:

  • 終止條件:當 n<10n < 10 時,直接回傳 nn(已達最高位的單一數字)。
  • 遞迴步驟:當 n≥10n \ge 10 時,回傳 recFun(n / 10) + n % 10。

計算 recFun(12345) 的呼叫堆疊(Call Stack)展開與回溯推導過程如下:

  1. 呼叫展開階段(Push to Stack):
  • recFun(12345)=recFun(1234)+12345(mod10)=recFun(1234)+5\text{recFun}(12345) = \text{recFun}(1234) + 12345 \pmod{10} = \text{recFun}(1234) + 5
  • recFun(1234)=recFun(123)+1234(mod10)=recFun(123)+4\text{recFun}(1234) = \text{recFun}(123) + 1234 \pmod{10} = \text{recFun}(123) + 4
  • recFun(123)=recFun(12)+123(mod10)=recFun(12)+3\text{recFun}(123) = \text{recFun}(12) + 123 \pmod{10} = \text{recFun}(12) + 3
  • recFun(12)=recFun(1)+12(mod10)=recFun(1)+2\text{recFun}(12) = \text{recFun}(1) + 12 \pmod{10} = \text{recFun}(1) + 2
  • recFun(1)\text{recFun}(1):此時引數 1<101 < 10,符合終止條件,直接回傳 11。
  1. 遞迴回溯計算階段(Pop from Stack):
  • recFun(12)=1+2=3\text{recFun}(12) = 1 + 2 = 3
  • recFun(123)=3+3=6\text{recFun}(123) = 3 + 3 = 6
  • recFun(1234)=6+4=10\text{recFun}(1234) = 6 + 4 = 10
  • recFun(12345)=10+5=15\text{recFun}(12345) = 10 + 5 = 15

main 函式執行 printf("%d\n", recFun(12345));,將回傳值 1515 格式化為整數輸出並換行。


解題技巧

  • 功能特徵判斷:看到 (n / 10) 搭配 (n % 10),即可判定此函式的語意為「十進位整數各個位數加總(Sum of Digits)」。
  • 快速驗算:直接將各個位數相加: 1+2+3+4+5=151 + 2 + 3 + 4 + 5 = 15 考場上只需花 3 秒即可心算求出答案,再行書寫呼叫過程以確保無誤。

【答案】

15

第(二)小題

核心觀念

  1. 參數傳遞機制(Parameter Passing Mechanisms):
  • 傳值呼叫(Call by Value):呼叫端將實引數(Actual Parameter)的值複製一份給函式的虛引數(Formal Parameter)
🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 二 題10 分

以下是完整的 Python 程式碼,請說明此程式的詳細功能為何?(10 分)

import os.path

file1 = input("Input a file name: ") file2 = input("Input the other file name: ")

while not os.path.isfile(file1): print("The file does not exist!") file1 = input("Input a file name again: ")

while os.path.isfile(file2): answer = input("The file existed, Overwrite it? y/n? ") if answer == 'n' or answer == 'N': file2 = input("Input a file name again: ") else: break

fileObject1 = open(file1, "r") fileObject2 = open(file2, "w")

content = fileObject1.read() fileObject2.write(content)

fileObject1.close() fileObject2.close()

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題評量 Python 基礎程式設計中的檔案輸入/輸出(File I/O)​與使用者互動流程控制,核心涵蓋以下四大觀念:

  1. 檔案狀態檢查與 os.path 模組: 使用 os.path.isfile(path) 函式判斷指定路徑是否為已存在的一般檔案(Regular File),回傳布林值(True 或 False)。
  2. 防呆驗證與迴圈控制(Validation Loops):
  • 藉由 while not ... 迴圈阻擋無效輸入,強制使用者直到輸入合法資料才能繼續。
  • 藉由條件分支(if-else)搭配 break 陳述式,控制是否跳出迴圈或重新請求輸入。
  1. 檔案讀寫模式(File Access Modes):
  • open(file, "r"):以唯讀(Read)模式開啟檔案,若檔案不存在會拋出 FileNotFoundError。
  • open(file, "w"):以寫入(Write)模式開啟檔案,若檔案已存在會將原內容完全清空(截斷,Truncate)並覆寫;若檔案不存在則會建立新檔。
  1. 資源存取與釋放(File Resource Management): 透過 read 一次性讀取全檔內容至記憶體字串,透過 write 寫入內容,最後呼叫 close 關閉檔案串流以釋放作業系統之檔案描述子(File Descriptor)。

解題方法

本題要求說明「此程式的詳細功能」。解題切入點應採由上而下(Top-down)分段剖析程式執行流程,先釐清各區塊的防呆與邏輯處理,再彙整出整體的系統功能:

  1. 第一階段:取得使用者輸入檔名
  • 提示使用者輸入來源檔案名稱(file1)與目的檔案名稱(file2)。
  1. 第二階段:來源檔案存在性防呆(Source File Validation)
  • 判斷 file1 是否存在。若不存在,進入 while 迴圈印出警告訊息 "The file does not exist!",並要求使用者重新輸入,直到輸入一個確實存在的檔案為止。
  1. 第三階段:目的檔案覆寫確認防呆(Destination File Overwrite Check)
  • 判斷 file2 是否已存在。若不存在,直接略過此迴圈;若已存在,進入 while 迴圈詢問使用者是否覆寫("The file existed, Overwrite it? y/n? ")。
  • 若使用者輸入 'n' 或 'N',則提示重新輸入另一個目的檔名,並由迴圈重新檢查新檔名是否衝突。
  • 若使用者輸入其他字元(包含 'y'、'Y' 或任意非 N 字元),則執行 else: break 跳出迴圈,代表確定使用該檔名(允許覆寫)。
  1. 第四階段:執行複製與關閉檔案
  • 以唯讀模式開啟 file1,以寫入模式開啟 file2。
  • 將 file1 的所有文字內容讀出後存入變數 content,接著寫入 file2。
  • 依序關閉兩檔案物件,完成檔案複製作業。

選項分析

本題為非選擇題(程式功能問答題),以下針對各程式碼邏輯區塊進行逐段功能與狀態轉換解析:

  • 區塊一:模組匯入與初次輸入
import os.path
file1 = input("Input a file name: ")
file2 = input("Input the other file name: ")
  • os.path 提供了與作業系統路徑相關的實用工具。
  • 透過 input 取得使用者鍵入的字串,分別代表欲讀取的來源檔名與欲寫入的目的檔名。
🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 三 題20 分

請撰寫一支密碼產生模組程式。此模組的密碼組成為一個五位數字,最後一碼(個位數)為驗證碼。合法的密碼規則是:除了驗證碼之外的所有數字相乘後,再除以 10 的餘數當作驗證碼。

例如:1357513575 即為合法的密碼,因為 (1×3×5×7) mod 10=5(1 \times 3 \times 5 \times 7) \bmod 10 = 5。

請撰寫一支完整 C/C++ 程式,包含 main() 與 codeGen():

  1. codeGen() 的功能為:輸入參數為密碼的前四碼,輸出為產生驗證碼後的五位數字密碼。
  2. 程式讓使用者輸入密碼的前四碼後,檢查使用者所輸入的數值是否為四位數。
  3. 若輸入正確,則呼叫 codeGen(),將傳回的五位數字密碼從螢幕顯示出。
  4. main() 需有迴圈功能,詢問使用者是否要繼續輸入,直到使用者按下不是 Y 或 y 鍵時結束程式。(20 分)

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題為典型的模組化程式設計與字元/數值處理題,評量考生在 C/C++ 語言中的基礎程式架構與流程控制能力,核心要點涵蓋:

  1. 函式模組化設計(Modular Programming):包含函式原型宣告(Declaration)、定義(Definition)以及參數傳遞(Parameter Passing)與回傳值(Return Value)。
  2. 整數除法與餘數運算(Integer Division & Modulo Operations):利用除法運算子 /(商數)與取餘數運算子 % 分離出整數的各個獨立位數。
  3. 資料驗證與範圍檢查(Data Validation):判斷數值是否符合題意之「四位數」(即介於 10001000 至 99999999 之間)。
  4. 迴圈控制與 I/O 緩衝區管理(Loop Control & Buffer Handling):採用後測試迴圈(do-while)確保至少執行一次互動,並正確處理字元讀取時殘留於標準輸入串流中的換行字元(\n)。

解題方法

本題解題步驟分為兩大主軸:codeGen 模組的運算邏輯推導,以及 main 函式的互動與驗證流程。

1. 密碼產生模組 codeGen 之推導

設輸入之前四碼為正整數 NN(1000≤N≤99991000 \le N \le 9999):

  • 分離位數:
  • 千位數:d1=⌊N/1000⌋d_1 = \lfloor N / 1000 \rfloor
  • 百位數:d2=⌊(N/100)⌋ mod 10d_2 = \lfloor (N / 100) \rfloor \bmod 10
  • 十位數:d3=⌊(N/10)⌋ mod 10d_3 = \lfloor (N / 10) \rfloor \bmod 10
  • 個位數:d4=N mod 10d_4 = N \bmod 10
  • 計算乘積與驗證碼: 各個位數乘積 P=d1×d2×d3×d4P = d_1 \times d_2 \times d_3 \times d_4。 驗證碼(個位數)C=P mod 10C = P \bmod 10
  • 組合五位數密碼: 將原四位數左移一位(乘以 10)後加上驗證碼 CC: Password=N×10+C\text{Password} = N \times 10 + C 回傳該整數值即為題目所需之五位數密碼。

2. 主程式 main 之流程規劃

  • 輸入驗證:讀取使用者輸入後,檢查是否符合條件 N≥1000∧N≤9999N \ge 1000 \land N \le 9999。若不符合,輸出提示訊息並跳過運算;若符合,呼叫 codeGen(N) 並輸出結果。
  • 持續執行迴圈:使用 do-while 結構,於每次運算結束後詢問使用者是否繼續。使用者輸入之字元若為 'Y' 或 'y' 則進入下一次反覆,否則結束迴圈。

解題技巧與常見陷阱

  1. scanf 讀取字元時的緩衝區換行陷阱(關鍵得分點): 在輸入整數後按下 Enter 鍵,換行字元 \n 會留在標準輸入緩衝區內。若後續直接使用 scanf("%c", &choice);,會直接讀到該換行字元而導致迴圈非預期結束。
🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 四 題25 分

請撰寫一支完整的 C/C++ 程式,此程式包含一維陣列。陣列元素的個數由使用者輸入,陣列元素值由時間亂數產生,數值範圍介於 11(含)至 9999(含)間。

此程式需包含下列函數:

(一)arrMean():將所傳入的一維陣列計算其陣列元素的平均值後傳回。(10 分)

(二)arrBubble():將所傳入的一維陣列利用氣泡排序法,將陣列元素由小至大排序。(10 分)

(三)撰寫 main(),以驗證 arrMean() 與 arrBubble() 的正確性。(5 分)

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題為經典的 C/C++ 基礎綜合實作題,主要評量考生對記憶體管理、亂數生成、陣列傳遞與基礎演算法的掌握度:

  1. 動態記憶體配置(Dynamic Memory Allocation): 題目要求「陣列元素個數由使用者輸入」,在 C/C++ 中靜態陣列大小必須為編譯期常數(Compile-time Constant)。因此應使用動態配置(如 C 的 malloc / free 或 C++ 的 new[] / delete[]),以確保程式的可移植性與標準相容性。
  2. 時間亂數生成(PRNG Seeding & Mapping): 透過 <time.h> 的 time(NULL) 做為種子(Seed)傳入 srand 初始化偽亂數產生器;利用取餘數運算將 rand 的輸出範圍映射至區間 [Min,Max][Min, Max]: rand%(Max−Min+1)+Min\text{rand} \% (Max - Min + 1) + Min 本題範圍為 11 至 9999,公式即為 rand % 99 + 1。
  3. 陣列的函式傳遞(Array Decay to Pointer): 一維陣列傳遞給函式時會退化為指向其首元素的指標(int * 或 int[])。在 C/C++ 中無法由指標直接得知陣列大小,因此必須同時將元素個數 nn 作為參數傳入。
  4. 數值型別轉換與平均值計算: 整數陣列的元素總和可能造成溢位(Overflow),且平均值為浮點數,進行除法時需做顯式型別轉換(Explicit Type Casting),避免整數除法產生截斷誤差(Truncation Error)。
  5. 氣泡排序法(Bubble Sort): 相鄰元素兩兩比較,若前大於後則交換,每輪走訪將當前最大值推移至末端。其時間複雜度在最差與平均情況下皆為 O(n2)O(n^2)。

解題方法

(一)arrMean 函式設計

  1. 參數與回傳值:傳入陣列首位址 const int arr[](使用 const 確保唯讀安全)與長度 int n,回傳值型別定為 double。
  2. 計算推導:
  • 累加變數 sum 使用 long long 或 double 型別,避免當陣列規模較大時整數溢位: Mean=∑i=0n−1arr[i]n\text{Mean} = \frac{\sum_{i=0}^{n-1} \text{arr}[i]}{n}
  • 在除法運算時確保被除數或除數轉為浮點數:(double)sum / n。
  • 若 n≤0n \le 0,應回傳 0.00.0 作為邊界防護。

(二)arrBubble 函式設計

  1. 參數與傳址機制:傳入 int arr[] 與長度 int n。陣列在 C/C++ 預設透過位址傳遞,函式內對陣列元素的交換會直接反映至原陣列。
  2. 演算法實作:
  • 外層迴圈控制回合數(共需 n−1n-1 回合):for (int i = 0; i < n - 1; i++)。
  • 內層迴圈進行相鄰元素比較:for (int j = 0; j < n - 1 - i; j++)。
  • 若 arr[j] > arr[j + 1] 則進行數值交換(Swap)。
  • 可加入旗標(Flag)優化:若某一回合未發生任何交換,代表已完成排序,可提早終止。

(三)main 驗證流程設計

  1. 輸入與檢查:讀取使用者輸入的個數 nn,並檢驗 n>0n > 0。
  2. 記憶體配置:配置 nn 個整數空間。
  3. 亂數初始化與填值:呼叫 srand((unsigned int)time(NULL)),利用迴圈填入 1∼991 \sim 99 的亂數值,並輸出原始陣列。
  4. 驗證與輸出:
  • 呼叫 arrMean,印出計算結果(格式化至小數點後兩位)。
  • 呼叫 arrBubble,印出排序後的陣列,直觀驗證是否由小至大排列。
  1. 釋放記憶體:執行 free 避免記憶體洩漏(Memory Leak)。

子題評分要點分析

  • (一)arrMean(10 分): 重點在於函式原型定義是否精確、迴圈累加是否完整、回傳型別是否採用浮點數(float 或 double),以及是否避免了整數除法的整除陷阱。
  • (二)arrBubble(10 分): 重點在於兩層迴圈的邊界條件是否正確(尤其是內層終止條件 n - 1 - i)、相鄰交換邏輯(三步驟暫存變數交換法)是否無誤。
  • (三)main 驗證(5 分): 重點在於是否包含「輸入個數」、「時間亂數種子設定」、「產生 1∼991 \sim 99 亂數」、「正確呼叫上述二函式」並「完整印出結果」以達成題目要求的驗證目的。

解題技巧與常見陷阱

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

第 五 題25 分

使用 C++、Java 或 Python 程式語言設計機車里程數計算程式:

(一)motor:機車類別

  • brand:機車品牌的私有字串資料項目。
  • fuel:機車油量(公升)的私有數值資料項目。
  • speed:機車速度(公里/小時)的私有數值資料項目。
  • km:機車可行駛公里數的私有數值資料項目。
  • 建構函數可將新建立物件之機車品牌、油量、速度作初始化。
  • calKM() 公有方法計算里程數,依標準機車計算,平均每公升可跑 15 公里。
  • show() 公有方法從螢幕顯示出機車品牌、油量、速度、可行駛公里數資訊。

(二)electricMotor:電動機車類別

  • 繼承機車(motor)類別。
  • seat:電動機車座位數私有數值資料項目。
  • 建構函數可將新建立物件初始化。
  • calKM() 公有方法計算電動機車可行駛公里數,不受速度影響,電動機車平均每公升可跑 20 公里。
  • show() 公有方法從螢幕顯示出電動機車品牌、油量、速度、可行駛公里數資訊。

(三)raceMotor:競技機車類別

  • 繼承機車(motor)類別。
  • type:競技機車型號之私有字串資料項目。
  • 建構函數可將新建立物件初始化。
  • calKM() 公有方法計算競技機車可行駛公里數:競技機車若時速超過每小時 60 公里,則平均每公升可跑 10 公里;沒超過的話則平均每公升可跑 12 公里。
  • show() 公有方法從螢幕顯示出競技機車品牌、油量、速度、可行駛公里數資訊。

此題不需讓使用者輸入相關數值,只需在程式內建立電動機車與競技機車物件時給予相關的數值,但程式需執行 show() 方法以驗證程式的正確性。(25 分)

登入後即可作答並保存紀錄。

這一題的完整詳解

核心觀念

本題為標準的物件導向程式設計(Object-Oriented Programming, OOP)​實作題,評量重點涵蓋以下核心概念:

  1. 封裝(Encapsulation)與存取控制(Access Control):
  • 題目明確要求各成員屬性為「私有」(private)。依封裝原則,子類別無法直接存取父類別的私有成員,必須透過父類別提供的公有(public)或保護(protected)存取方法(Getter / Setter)進行資料操作。
  1. 繼承(Inheritance)與建構子鏈(Constructor Chaining):
  • 子類別使用 extends 繼承父類別,並在其建構函數中使用 super(...) 呼叫父類別建構函數,完成基礎資料項目的初始化。
  1. 多型與方法覆寫(Method Overriding):
  • 子類別依個別行駛邏輯重新定義父類別的 calKM 與 show 方法,展現多型行為。
  1. 里程數計算模型:
  • 一般機車:km=fuel×15\text{km} = \text{fuel} \times 15
  • 電動機車:km=fuel×20\text{km} = \text{fuel} \times 20
  • 競技機車: km={fuel×10,若 speed>60fuel×12,若 speed≤60\text{km} = \begin{cases} \text{fuel} \times 10, & \text{若 } \text{speed} > 60 \\ \text{fuel} \times 12, & \text{若 } \text{speed} \le 60 \end{cases}

解題方法

本題選用國家考試中最受閱卷委員青睞、型別定義嚴謹的 Java 程式語言 進行實作:

  1. 父類別 motor 設計:
  • 將 brand、fuel、speed、km 宣告為 private。
  • 實作三參數建構子初始化 brand、fuel、speed,並將初始里程 km 設為 0.00.0。
  • 提供 getFuel、getSpeed 與 setKM、getKM 等方法,供子類別在不破壞封裝的前提下讀取與更新狀態。
  • 實作公有方法 calKM 與 show。
  1. 衍生類別 electricMotor 設計:
  • 宣告私有屬性 seat。
  • 建構子接收四個參數,前三個透過 super(brand, fuel, speed) 傳遞給父類別,最後初始化 this.seat。
  • 覆寫(@Override)calKM:呼叫 setKM(getFuel * 20)。
  • 覆寫 show:可呼叫 super.show 顯示基礎資訊,並附加顯示座位數 seat。
  1. 衍生類別 raceMotor 設計:
  • 宣告私有屬性 type。
  • 建構子透過 super(brand, fuel, speed) 及 this.type 完成初始化。
  • 覆寫 calKM:利用 if (getSpeed > 60) 判斷油耗係數並計算設定 km。
  • 覆寫 show:顯示基礎資訊並可附加顯示型號 type。
  1. 主程式驗證:
  • 建立 electricMotor 與 raceMotor 物件並傳入指定初始值。
  • 呼叫各物件之 calKM 計算里程數後,執行 show 印出結果,驗證多型與覆寫之正確性。

選項分析(規格細部檢核)

本題為程式設計題,依據題目各項規格逐一檢驗實作切入點:

  • (一)motor 類別:
  • brand(字串)、fuel(數值)、speed(數值)、km(數值)全數設為 private,數值型別採 double 避免整數除法失真。
  • 建構函數接收 3 個參數,符合「初始化機車品牌、油量、速度」要求。
  • calKM 實作每公升 15 公里之運算;show 格式化輸出各項資料。
  • (二)electricMotor 類別:
  • 正確繼承 motor,並擴充私有成員 seat。
  • 建構函數完整轉送基礎欄位至父類別。
  • calKM 依每公升 20 公里重新計算,忽略速度影響。
  • (三)raceMotor 類別:
  • 正確繼承 motor,並擴充私有成員 type。
  • calKM 具備條件分支判斷(時速 >60 km/h> 60\text{ km/h} 為 10 km/L10\text{ km/L},否則為 12 km/L12\text{ km/L})。
  • 驗證程式(main 方法):
  • 依照題目要求,不使用 Scanner 讀取鍵盤輸入,直接硬編碼(Hardcode)測試資料建立物件。
  • 明確呼叫 calKM 與 show 達成題目要求之「驗證程式的正確性」。

解題技巧與常見陷阱

  1. 封裝性陷阱(最關鍵扣分點):
  • 許多考生在子類別中直接寫 this.fuel * 20 或 km = ...,在 Java 與 C++ 中會直接引發編譯錯誤(Compiler Error),因為父類別欄位宣告為 private。
  • 正確做法:務必在父類別建立 protected 或 public 的 Getter 與 Setter,或者宣告 protected 存取級別;但題目已指定父類別為「私有」,故撰寫 Getter/Setter 是最正統且不失分的 OOP 作法。
  1. 數值型態的選擇:
  • 油量、時速與里程數多含小數點,宜使用倍精度浮點數 double,避免使用 int 造成截尾誤差。
  1. super 的調用位置:
  • 子類別建構子內若顯式呼叫父類別建構子 super(...),該陳述式必須是建構子內的第一行程式碼。

【答案】

🔒

後續完整解題步驟與【答案】

免費註冊,享 3 天全站完整詳解閱覽。

免費註冊

其他考古題