110 司法特考三等 檢察事務官電子資訊組 程式語言 考古題詳解
第 一 題25 分
以下為 C++ 定義類別 Student 與 Class 的程式碼,請撰寫一「班級成績計算」的 C++ 程式。首先讓使用者輸入兩班學生(每班各有 3 位學生)的姓名與國文、英文、數學課的成績,並符合以下要求:
- 為類別 Class 撰寫一建構元函式,將班上 3 位學生的國文、英文、數學成績、該班學生成績的平均分數與最高總分設為 0。
- 為類別 Class 撰寫一方法
cal(),計算該班學生的平均分數。 - 為類別 Class 撰寫一方法
findTop(),找出該班學生的最高總分與其所在位置。 - 撰寫運算子
>多載(overloading)功能,可以比較兩班的最高總分,並回傳哪一班的最高總分較高。 - 撰寫主程式
main(),以驗證此程式的正確性。
類別 Student 與 Class 的程式碼如下:
class Student { //學生類別定義 public: string name; //學生姓名 int chn, eng, math; //學生國英數成績 };
class Class { //班級類別定義 public: Student student[3]; //每班 3 位學生 double avg; //該班學生的平均分數 int top, top_index; //該班學生的最高總分與其所在位置
public: Class(); //建構元函式將類別內變數初值設為 0 int operator>(Class &win); //定義運算子 > 的多載,以回傳最高總分班級 void cal(void); //計算該班學生的平均分數 void findTop(void); //找出該班學生的最高總分與其所在位置 };
程式執行範例如下:
第 1 班第 1 位學生名字:大明
請依序輸入他的國英數成績:85 66 92
第 1 班第 2 位學生名字:阿美
請依序輸入他的國英數成績:92 85 78
第 1 班第 3 位學生名字:小凱
請依序輸入他的國英數成績:96 92 90
第 2 班第 1 位學生名字:大雄
請依序輸入他的國英數成績:65 82 72
第 2 班第 2 位學生名字:阿吉
請依序輸入他的國英數成績:98 92 99
第 2 班第 3 位學生名字:小文
請依序輸入他的國英數成績:90 92 95
第 1 班平均成績:86.22
第 2 班平均成績:87.22
最高分在第 2 班是阿吉,總分為 289 分
登入後即可作答並保存紀錄。
核心觀念
本題考查 C++ 物件導向程式設計,重點包括:
- 類別與物件
Student表示一位學生。Class表示一個班級,內含 3 個Student物件。
- 建構元函式
Class用來初始化班級資料。- 將所有成績、平均分數、最高總分與最高分位置設為 。
- 陣列成員
Student student[3]表示每班有 3 位學生。- 陣列索引由 到 。
- 成員函式
cal計算班級平均分數。findTop找出最高總分及學生位置。
- 運算子多載
- 以
operator>比較兩班的最高總分。 - 回傳第 1 班、第 2 班,平手時回傳 。
解題方法
一、平均分數計算
每位學生有國文、英文、數學三科成績,因此全班共有 個科目成績。
班級平均分數為:
也可以先求每位學生的總分,再將 3 位學生總分相加後除以 。
二、最高總分計算
每位學生總分為:
依序比較 3 位學生的總分:
- 若目前學生總分高於
top,更新top。 - 同時將其位置記錄到
top_index。 - 程式內部使用 起始索引,輸出時再加 轉成人類習慣的第 1 位、第 2 位、第 3 位。
三、兩班最高總分比較
呼叫:
int winner = class1 > class2;
定義如下:
- 第 1 班最高總分較高,回傳
1。 - 第 2 班最高總分較高,回傳
2。 - 兩班相同,回傳
0。
必須先執行兩班的 findTop,才能正確比較 top。
完整 C++ 程式
第 二 題25 分
(一)變數的種類可概分為區域變數(Local Variable)、全域變數(Global Variable)與靜態變數(Static Variable),請就宣告方式、有效範圍(Scope)、程式碼維護比較其差異。(15 分)
(二)遞迴函式(Recursive Function)通常也可以改用迴圈(Loop)方式來撰寫,請就程式碼撰寫難易度、理解性、執行效能、記憶體使用比較其差異。(10 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查兩組程式設計基礎觀念:
- 變數的分類與作用域管理:
- 區域變數(Local Variable)
- 全域變數(Global Variable)
- 靜態變數(Static Variable)
- 遞迴函式與迴圈的程式實作比較:
- 程式碼撰寫難易度
- 程式理解性
- 執行效能
- 記憶體使用量
以下以 C/C++ 常見語意說明。不同程式語言對 static 的細節定義不同,作答時應掌握「作用域」與「生命週期」兩個核心概念。
(一)區域變數、全域變數與靜態變數比較
1. 區域變數(Local Variable)
宣告方式
在函式、區塊或迴圈內宣告的變數,通常就是區域變數。
void func {
int x = 10; // 區域變數
}
若在某個區塊中宣告,其作用範圍通常限於該區塊:
void func {
if (condition) {
int y = 20;
printf("%d", y);
}
// y 在此處不可使用
}
有效範圍(Scope)
區域變數只能在宣告它的函式或區塊內使用,離開該範圍後便不可直接存取。
void func {
int x = 10;
printf("%d", x); // 正確
}
void other {
printf("%d", x); // 錯誤,x 不在此函式的作用域內
}
區域變數具有封裝性,其他函式無法直接修改其內容。
生命週期
一般區域變數通常具有自動儲存期:
- 進入函式或區塊時建立。
- 離開函式或區塊時消失。
- 每次重新進入函式時,通常會重新建立並初始化。
程式碼維護
優點如下:
- 變數使用範圍小,容易追蹤資料流向。
- 不同函式可以使用相同變數名稱,不易互相干擾。
- 降低函式之間的耦合程度。
- 修改某一函式時,較不容易影響其他程式區域。
缺點是:
- 若多個函式都需要相同資料,必須透過參數傳遞或回傳值交換資料。
- 不適合保存跨函式呼叫仍須保留的狀態。
2. 全域變數(Global Variable)
宣告方式
在所有函式之外宣告的變數,通常屬於全域變數。
int count = 0; // 全域變數
void add {
count++;
}
void print {
printf("%d", count);
}
若跨檔案使用,通常會在其他檔案使用 extern 宣告:
extern int count;
有效範圍(Scope)
全域變數的作用域通常自宣告位置開始,延伸到該原始檔案的結尾。若搭配 extern,可供其他原始檔案使用。
在單一檔案中,函式通常都可以存取同一個全域變數:
int value = 5;
void func1 {
value = 10;
}
void func2 {
printf("%d", value);
}
生命週期
全域變數通常具有整個程式執行期間的生命週期:
- 程式開始執行時配置。
- 程式結束時釋放。
- 若未明確初始化,通常會自動初始化為零值。
程式碼維護
優點如下:
- 多個函式可以直接共用資料。
- 適合表示整個程式共用的設定值、狀態或資源。
缺點如下:
- 任何可見的函式都可能修改它,資料流向不易追蹤。
- 形成函式之間的高度耦合。
- 修改一處全域變數,可能造成多個模組行為改變。
- 不利於模組化、測試及除錯。
- 在多執行緒程式中,若缺乏同步控制,可能產生競爭條件。
- 名稱容易與區域變數衝突,增加閱讀困難。
因此,除非確實需要整個程式共用,通常應優先使用區域變數、參數傳遞或封裝於物件中的成員變數。
3. 靜態變數(Static Variable)
static 的意義必須同時從「作用域」及「生命週期」判斷。在 C/C++ 中,靜態變數常見於兩種形式。
(1)函式內的靜態區域變數
void counter {
static int count = 0;
count++;
printf("%d\n", count);
}
若連續呼叫:
counter; // 1
counter; // 2
counter; // 3
作用域
函式內的 static 變數仍然只有函式內可直接使用,因此其作用域與區域變數相近。
生命週期
與一般區域變數不同,函式內的靜態變數:
- 程式啟動時配置。
- 整個程式執行期間持續存在。
- 函式結束後不會消失。
- 再次進入函式時保留上次的值。
- 通常只在第一次執行宣告處時初始化。
因此,函式內靜態變數可視為「具有區域作用域、全程生命週期」的變數。
(2)檔案層級的靜態變數
static int file_count = 0;
此變數宣告於所有函式之外,但加上 static 後:
- 生命週期仍為整個程式執行期間。
- 作用域限制在目前的原始檔案。
- 其他原始檔案無法透過
extern直接存取。
這種語法常用於實作檔案內部資料,避免名稱暴露給其他模組。
4. 綜合比較表
| 比較項目 | 區域變數 | 全域變數 | 靜態變數 |
|---|---|---|---|
| 常見宣告位置 | 函式或區塊內 | 所有函式之外 | 函式內或檔案層級,搭配 static |
| 作用域 | 函式或區塊內 | 通常可跨函式,亦可跨檔案 | 函式內靜態變數限於函式;檔案層級靜態變數限於該檔案 |
| 生命週期 | 進入區塊建立,離開區塊消失 | 整個程式執行期間 | 整個程式執行期間 |
| 函式結束後資料是否保留 | 否 | 是 | 是 |
| 是否容易被其他模組修改 | 不容易 | 容易 | 檔案層級靜態變數不易;函式內靜態變數只能透過函式操作 |
| 封裝性 | 高 | 低 | 通常高於全域變數 |
| 適用情況 | 暫時性計算、函式內部資料 | 多個模組確實共用的狀態 | 保存函式狀態、隱藏檔案內部資料 |
| 維護性 | 最佳 | 較差 | 通常優於全域變數 |
5. 程式碼維護的比較與結論
維護性通常可作如下排序:
區域變數的影響範圍最小,最容易進行模組化與測試。靜態變數能限制外部存取範圍,但因為生命週期很長,仍可能造成隱藏狀態,使函式不再完全依賴輸入參數。全域變數雖然使用方便,卻會增加耦合與除錯困難。
(二)遞迴函式與迴圈比較
1. 遞迴函式的核心概念
遞迴函式是指函式在執行過程中直接或間接呼叫自己。
遞迴必須具備兩個要素:
- 基底條件(Base Case):決定何時停止遞迴。
- 遞迴步驟(Recursive Case):將問題化為規模較小的相同問題。
例如計算階乘:
int factorial(int n) {
if (n == 0) {
return 1; // 基底條件
}
return n * factorial(n - 1); // 遞迴步驟
}
其數學定義為:
第 三 題25 分
請使用 C/C++、Java 或 Python 任一程式語言,撰寫一支加密演算法程式,讓使用者輸入一語句,然後將語句中的每個大小寫字母轉換成其反序的字母(、、、、、、)。
若所輸入的語句中有不是英文字母的字元,則以原字元輸出。
例如:
所輸入的語句為「abcd6ZYXW」。
所輸入的語句為「R olev blf!」,則輸出應為「I love you!」。(25 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查「逐字元處理」與英文字母的反序替換,也稱為 Atbash substitution。
英文字母共有 26 個,將字母編號如下:
- 大寫:
- 小寫:
反序字母的編號為:
因此:
- 大寫字母範圍為
A至Z - 小寫字母範圍為
a至z - 非英文字母,例如空白、數字、標點符號,必須原樣輸出
例如大寫字母 C:
所以 C 轉換為 X。
解題方法
讀入整行語句,從左至右逐一檢查每個字元:
- 若字元介於
A與Z之間,依大寫字母公式轉換。 - 若字元介於
a與z之間,依小寫字母公式轉換。 - 其餘字元直接保留。
- 將所有轉換後的字元依原順序連接並輸出。
大寫字母的轉換公式為:
小寫字母的轉換公式為:
其中:
ord(c):取得字元的數值編碼chr(n):將數值編碼轉回字元
Python 參考程式
第 四 題25 分
中華民國的身分證字號共有 10 個字元,其編碼原則如下:
第一個字元為大寫的英文字母,代表出生地區;其餘 9 個字元皆為數字。
在套用編碼原則時,第一個大寫英文字母須先依下表轉換為數字:
字母:A B C D E F G H I J K L M
數字:10 11 12 13 14 15 16 17 34 18 19 20 21
字母:N O P Q R S T U V W X Y Z
數字:22 35 23 24 25 26 27 28 29 32 30 31 33
轉換後的身分證字號共有 11 位數字,每一位數字均有固定的權重(Weight),由左往右依序為:
判斷身分證字號是否正確的方法為:各位數字與其相對應的權重相乘後再加總。加總後的結果若為 10 的倍數,則該身分證字號即屬有效。
請使用 C/C++、Java 或 Python 任一程式語言,撰寫一支中華民國身分證字號的驗證程式。
例如:
所輸入的身分證字號為「A123456789」,則輸出應為「A123456789 為有效的身分證字號」。
所輸入的身分證字號為「Z987654321」,則輸出應為「Z987654321 為無效的身分證字號」。(25 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查:
- 身分證字號格式判斷。
- 英文字母轉換為兩位數字。
- 加權總和驗證法。
- 字串處理與迴圈運算。
依題目規則,身分證字號原本為:
- 第 1 碼:大寫英文字母。
- 第 2 至第 10 碼:數字。
英文字母轉換後,會產生兩位數字,因此共形成 11 位數字,再搭配權重:
將各位數字與對應權重相乘後加總,若總和為 的倍數,即為有效身分證字號。
本題屬程式設計題,沒有涉及法條適用問題。
解題方法
一、先檢查輸入格式
輸入字串必須符合:
- 長度為 10。
- 第 1 個字元為
A至Z的大寫英文字母。 - 第 2 至第 10 個字元全部為數字。
格式不符時,直接判定為無效。
二、將英文字母轉為兩位數字
建立英文字母與數字的對照表,例如:
A對應10B對應11I對應34Z對應33
若輸入為 A123456789,英文字母 A 轉換為 10,所以完整數字序列為:
三、進行加權計算
將上述數字依序乘上權重:
因此:
因為 是 的倍數,所以 A123456789 為有效身分證字號。
若:
則判定有效;否則判定無效。