114 司法特考三等 檢察事務官類科電子資訊組 程式語言 考古題詳解
第 一 題25 分
針對以下 C 程式碼,請先說明執行該程式之輸出,以及程式中函式 left()、right() 之運作功能;並請說明在 testGen() 測試 left()、right() 過程中,有哪幾行指令未被充分測試。
#include <stdio.h> #include <stdlib.h> #include <string.h>
char* left(char* data, int len, const char symbol) { int dLen = strlen(data); char* result = (char*)malloc(dLen + 1); if (len > dLen) len = dLen; strcpy(result, data); for (int i = len; i < dLen; i++) result[i] = symbol; return result; }
char* right(char* data, int len, const char symbol) { int dLen = strlen(data); char* result = (char*)malloc(dLen + 1); if (len > dLen) len = dLen; strcpy(result, data); for (int i = (dLen - len); i < dLen; i++) result[i] = symbol; return result; }
void testGen() { char str[] = "abcdef"; char* left1 = left(str, 4, '@'); char* left2 = left(str, 8, '@'); char* right1 = right(str, 4, '@');
printf("%s\n", left1);
printf("%s\n", left2);
printf("%s\n", right1);
free(left1);
free(left2);
free(right1);
}
int main() { testGen(); return 0; }
登入後即可作答並保存紀錄。
核心觀念
本題考查 C 語言字串的儲存方式、strlen 與 strcpy 的用途、動態記憶體配置,以及依程式控制流程判斷測試涵蓋情形。
C 字串以空字元 '\0' 結尾,strlen(data) 計算字串中不含結尾空字元的字元數。本題的 data 是 "abcdef",因此 dLen = 6。兩個函式都配置 dLen + 1 個位元組,複製原字串,再以指定符號覆寫部分字元;最後由呼叫端以 free 釋放配置的記憶體。
解題方法
left 的運作
left(data, len, symbol) 保留字串左側前 len 個字元,並將其餘字元改成 symbol。
當 len > dLen 時,程式將 len 限制為 dLen。接著從索引 len 起,逐一覆寫至索引 dLen - 1。
left(str, 4, '@'):索引 0 至 3 保留,索引 4、5 改成@,結果為abcd@@。left(str, 8, '@'):8 > 6,所以將len設為 6;迴圈不執行,結果為abcdef。
right 的運作
right(data, len, symbol) 保留字串右側最後 len 個字元,並將左側其餘字元改成 symbol。
迴圈從 dLen - len 開始,覆寫至索引 dLen - 1。
right(str, 4, '@'):從索引 2 開始覆寫,索引 2 至 5 都變成@,結果為ab@@@@。
程式輸出
printf("%s\n", ...) 會印出各字串,輸出如下:
abcd@@
abcdef
ab@@@@
第 二 題25 分
以下 Java 程式碼計算人類(Human)進行不同運動(Exercise)消耗的卡路里量。請完成統一塑模語言 UML 圖;並說明程式執行後的輸出,以及動態多型(Dynamic Polymorphism)指令所在之程式碼行數與其構成之原因。
UML 類別圖中包含以下類別及成員:
🖼️【此處有附圖,請對照原卷】
ExerciseRunningClimbingHuman
abstract class Exercise { public Exercise(String name, int cal) { this.name = name; this.calorie = cal; }
abstract public void computeCal(int x);
public String show(int c) {
String result = name + ":";
computeCal(c);
result += calorie;
return result;
}
private String name;
protected int calorie;
}
class Running extends Exercise { public Running(String name, int cal, int dis) { super(name, cal); distance = dis; }
public void computeCal(int time) {
calorie += distance * (10 - time);
}
private int distance;
}
class Climbing extends Exercise { public Climbing(String name, int cal, int lev) { super(name, cal); level = lev * 2; }
public void computeCal(int height) {
calorie += height * level * 20;
}
private int level;
}
class Human { public void setExercise(Exercise e) { exercise = e; }
public String getCal() {
return exercise.show(2);
}
private Exercise exercise;
}
public class ExerciseTest { public static void main(String[] args) { Exercise[] exs = { new Running("marathon", 12, 26), new Running("endurance", 10, 5), new Climbing("Yushan", 30, 4) };
Human h = new Human();
for (Exercise e : exs) {
h.setExercise(e);
System.out.println(h.getCal());
}
}
}
登入後即可作答並保存紀錄。
核心觀念
本題考查 UML 類別圖、繼承與方法覆寫,以及 Java 的動態多型。Exercise 是抽象類別,宣告抽象方法 computeCal;Running 和 Climbing 繼承它,並各自提供計算卡路里的實作。Human 則持有一個 Exercise 參考,透過它呼叫運動物件的方法。
解題方法
先依程式碼整理各類別的欄位、建構子與方法,再標出繼承及關聯:
Exercise為抽象類別,含私有欄位name、受保護欄位calorie,以及抽象方法computeCal和一般方法show。Running、Climbing繼承Exercise,並分別新增distance、level欄位,覆寫computeCal。Human有一個私有欄位exercise: Exercise,表示它與Exercise之間有關聯。
以下以 UML 常用符號表示可見度:+ 公開、- 私有、# 受保護;斜體表示抽象類別或抽象方法。
第 三 題25 分
以下 Python 程式碼,可以解析下列 BNF 規則。請先寫出 BNF 規則中 (I)~(V);並說明程式執行後之輸出。
BNF 規則:
<assign> ::= <id> = <____(I)>
<id> ::= ____(II)
<expr> ::= <expr> ____(III) <expr> | <expr> (IV) <expr> | <(V)>
程式碼:
def id_(s, i): if i < len(s) and s[i] in ('A', 'B', 'C'): return i + 1, True return i, False
def expr(s, i): i, ok = id_(s, i) if not ok: return i, False
while i + 1 < len(s) and s[i] in ('+', '*'):
i, ok = id_(s, i + 1)
if not ok:
raise Exception('id error')
return i, True
def assign(s, i): i, ok = id_(s, i) if not ok or i >= len(s): raise Exception('id error')
if s[i] != '=':
raise Exception('not =')
i, ok = expr(s, i + 1)
if not ok:
raise Exception('expr error')
if i != len(s):
raise Exception('end or expr error')
print('ok')
def test(code): try: assign(code, 0) except Exception as e: print(e)
test('B=CB+AA') test('B=CB+DA') test('B=CB+A') test('A-CD+A++A') test('A=CD+A++A')
登入後即可作答並保存紀錄。
核心觀念
本題考查 BNF(Backus–Naur Form)文法與遞迴下降式解析的對應關係。程式以 id_ 判斷識別字,以 expr 解析運算式,再由 assign 檢查指定敘述的格式與輸入是否完整。
id_ 僅接受字元 A、B、C,因此 <id> 的文法是:
expr 先解析一個識別字,再以 + 或 * 接續另一個識別字,因此運算式的 BNF 為:
指定敘述則是識別字、等號與運算式:
解題方法
逐一比對程式的檢查條件與 BNF:
id_接受A、B、C,故 (II) 為A | B | C。expr的迴圈只接受+、*,故 (III)、(IV) 分別為+、*。expr每次先呼叫id_,故 (V) 為id。assign在識別字後要求=,再解析運算式,故 (I) 為expr。
第 四 題25 分
臺灣智慧金融公司設計一個關聯式資料庫(Relational database),內有兩個關聯(Relation):
工程師 Engineer:
- 編號(整數、Primary key)
- 姓名(字串)
- 電話(字串)
- 專長(字串)
助理 Assistant:
- 編號(整數、Primary key)
- 姓名(字串)
- 薪水(整數)
- 工程師編號(Foreign key)
請寫出 SQL 指令,查詢出工程師編號小於等於 50 且其助理薪水大於 30000 的工程師姓名與專長,並造出工程師專長為「hack」相關之工程師姓名與協助的助理姓名與電話的 View。
另請說明何謂 View,以及使用 View 的優點。
登入後即可作答並保存紀錄。
核心觀念
本題考查 SQL 的多表連接、條件篩選、檢視表(View)的建立,以及 View 的定義與用途。
Engineer.編號與Assistant.工程師編號相互對應,可用JOIN連接兩個關聯。WHERE用來篩選符合條件的資料列。CREATE VIEW可將查詢結果定義為一個可重複使用的虛擬資料表。
解題方法
一、查詢符合條件的工程師姓名與專長
助理的薪水條件要套用在 Assistant,工程師編號條件則套用在 Engineer。兩表以工程師編號連接:
SELECT DISTINCT E.姓名, E.專長
FROM Engineer AS E
JOIN Assistant AS A
ON E.編號 = A.工程師編號
WHERE E.編號 <= 50
AND A.薪水 > 30000;
DISTINCT 用來避免同一位工程師有多位符合條件的助理時,姓名與專長重複出現。若題意要求每筆符合條件的工程師—助理配對都列出,則可省略 DISTINCT。
二、建立專長為「hack」的工程師及其助理 View
題目要求輸出工程師姓名、助理姓名與助理電話,因此連接工程師與助理後,依工程師專長篩選:
CREATE VIEW HackEngineerAssistant AS
SELECT E.姓名 AS 工程師姓名,
A.姓名 AS 助理姓名,
A.電話 AS 助理電話
FROM Engineer AS E
JOIN Assistant AS A
ON E.編號 = A.工程師編號
WHERE E.專長 = 'hack';