111 關務特考四等 資訊處理 程式設計概要 考古題詳解
第 一 題
有關 C++ 物件導向程式設計,請回答下列問題: (一) 基底類別的成員中,何者可以在基底類別和衍生類別中定義,使基底類別和衍生類別的朋友可以存取?請試舉二者。(6分) (二) 請解釋運算符號 的多重含義。(6分) (三) 那個運算子可以用於安全地向下轉換(downcast)基底類別指標?(3分) (四) 當類別成員指定為為何者時,只能由類別的成員函數和類別的朋友來存取?(3分) (五) 運算子中,何者用於動態分配記憶體和建構物件,且此運算子可回傳一個指向物件的指標?(3分)
登入後即可作答並保存紀錄。
核心觀念
本題考查 C++ 物件導向程式設計中的:
- 成員存取權限:
public、protected、private - 朋友函數(friend function)與朋友類別
- 運算子多載及
<<的不同用途 - 基底類別指標的安全向下轉換
- 動態記憶體配置與物件建立
解題方法
判斷各小題時,依照 C++ 的關鍵字與功能直接對應:
- 可供衍生類別及朋友存取的成員,對應
protected。 <<依使用對象不同,可表示位元左移或串流插入。- 安全的執行期向下轉型,使用
dynamic_cast。 - 僅類別成員函數與朋友可存取,對應
private。 - 動態配置記憶體並建立物件,使用
new。
(一)可在基底類別與衍生類別中定義,並供朋友存取的成員
核心觀念
答案是 protected 成員。
protected 成員具有以下特性:
- 基底類別的成員函數可以存取。
- 基底類別的朋友函數或朋友類別可以存取。
- 衍生類別的成員函數可以存取。
- 衍生類別的朋友函數或朋友類別,亦可在衍生類別的存取脈絡中存取。
- 一般外部函數無法直接存取。
舉例一:protected 資料成員
class Base {
protected:
int value;
};
class Derived : public Base {
public:
void setValue(int v) {
value = v;
}
};
此例中,value 是基底類別的 protected 成員,因此 Derived 的成員函數可以直接使用。
舉例二:protected 成員函數
class Base {
protected:
void showValue {
// 顯示資料
}
};
class Derived : public Base {
public:
void display {
showValue;
}
};
此例中,showValue 是基底類別的 protected 成員函數,衍生類別可以直接呼叫。
朋友函數的存取示意如下:
class Base {
protected:
int value;
friend void baseFriend(Base&);
};
void baseFriend(Base& b) {
b.value = 10;
}
朋友函數雖然不是類別成員,但因為被宣告為 friend,可存取類別的 protected 成員。
解題技巧
快速判斷:
public:任何程式碼都可存取。protected:類別本身、衍生類別及朋友可存取。private:類別本身及朋友可存取,衍生類別不能直接存取。
因此題目提到「衍生類別」與「朋友」,關鍵字就是 protected。
(二)運算符號 << 的多重含義
核心觀念
<< 在 C++ 中至少有兩種主要用途:
- 位元左移運算子(left shift operator)
- 串流插入運算子(stream insertion operator)
1. 位元左移運算子
對整數而言,<< 會將二進位位元向左移動指定位數,右側補入 。
int x = 3; // 二進位為 0011
int y = x << 2; // 二進位為 1100
其數值效果通常相當於:
因此:
此公式適用於不涉及溢位及特殊符號整數情形。
2. 串流插入運算子
使用 cout << 時,<< 是將資料送入輸出串流:
int age = 20;
cout << "Age: " << age;
此處的 << 並不是位元左移,而是將字串及變數插入 cout,以便輸出至螢幕。
3. 運算子多載
C++ 可透過運算子多載,使 << 用於自訂類別:
第 二 題
有關 Java 程式設計,請回答下列問題: (一) 說明下列 class Test2_B 程式之功能。(8分) (二) 說明 funcA 程式的功能。(5分) (三) 說明 funcB 程式的功能。(5分) (四) 說明 funcC 程式的功能。(5分) (五) 說明 main 程式的功能。(5分)
public class Test2_B {
public static void main(String[] args) {
int count = 1;
for (int i = 2; true; i++) {
if (funcA(i) && funcC(i)) {
System.out.print(i + " ");
if (count % 10 == 0) {
System.out.println();
}
if (count == 6) {
break;
}
count++;
}
}
}
public static boolean funcA(int num) {
for (int i = 2; i <= num / 2; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
static int funcB(int number) {
int result = 0;
while (number != 0) {
int lastDigit = number % 10;
result = result * 10 + lastDigit;
number = number / 10;
}
return result;
}
static boolean funcC(int number) {
return number == funcB(number);
}
}
登入後即可作答並保存紀錄。
核心觀念
本題考查 Java 程式控制流程與數字判斷,重點包括:
for迴圈與breakif條件判斷&&邏輯 AND 運算%餘數運算與/整數除法- 質數判斷
- 數字反轉
- 回文數判斷
static方法的呼叫
本程式會依序檢查正整數,找出同時符合下列兩項條件的數字:
- 是質數。
- 從左到右與從右到左讀取結果相同,即為回文數。
(一)class Test2_B 程式之功能
程式從 i = 2 開始逐一檢查整數:
for (int i = 2; true; i++)
其中 true 代表這是一個沒有明確終止條件的無窮迴圈,必須依靠迴圈內的 break 結束。
每次迴圈執行:
if (funcA(i) && funcC(i))
只有當:
funcA(i)回傳true,表示i是質數;funcC(i)回傳true,表示i是回文數;
兩個條件均成立時,才會輸出該數字。
符合條件的數字依序為:
| 次序 | 數字 | 質數 | 回文數 |
|---|---|---|---|
| 1 | 2 | 是 | 是 |
| 2 | 3 | 是 | 是 |
| 3 | 5 | 是 | 是 |
| 4 | 7 | 是 | 是 |
| 5 | 11 | 是 | 是 |
| 6 | 101 | 是 | 是 |
因此程式輸出:
2 3 5 7 11 101
當找到第 6 個符合條件的數字時:
if (count == 6) {
break;
}
立即結束迴圈與 main 方法。
count % 10 == 0 的功能是每輸出 10 個數字換行;本題只輸出 6 個數字,因此不會執行換行。
(二)funcA 程式的功能
public static boolean funcA(int num) {
for (int i = 2; i <= num / 2; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
判斷方法
程式從 開始,依序檢查至 :
if (num % i == 0)
若 num 除以某個 i 的餘數為 ,代表 num 可以被 i 整除,因此不是質數,立即回傳 false。
若所有可能的除數都檢查完,仍沒有找到可整除的數字,便回傳 true。
功能結論
funcA 用來判斷輸入的 num 是否為質數:
- 是質數:回傳
true - 不是質數:回傳
false
例如:
funcA(7):7 無法被 2、3 整除,回傳truefuncA(9):9 可被 3 整除,回傳falsefuncA(11):11 無法被 2、3、4、5 整除,回傳true
本程式從 開始使用,因此不會遇到 、 與負數的判斷問題。
(三)funcB 程式的功能
static int funcB(int number) {
int result = 0;
while (number != 0) {
int lastDigit = number % 10;
result = result * 10 + lastDigit;
number = number / 10;
}
return result;
}
funcB 的功能是將整數的十進位數字順序反轉。
執行原理
每次迴圈取出目前數字的個位數:
int lastDigit = number % 10;
再將該位數接到 result 的右側:
result = result * 10 + lastDigit;
最後去除原數字的個位數:
第 三 題
有關 C 程式設計,請回答下列問題: (一) 說明下列程式之功能。(6分) (二) 說明 funcA 程式的功能。(5分) (三) 說明 funcB 程式的功能。(5分) (四) 說明 funcC 程式的功能。(5分) (五) 說明 main 程式的功能。(5分)
#include <stdio.h>
#define S 3
#define E 4
int funcA(const int g[][E], size_t p, size_t t) {
int lg = 100;
for (size_t i = 0; i < p; ++i) {
for (size_t j = 0; j < t; ++j) {
if (g[i][j] < lg) lg = g[i][j];
}
}
return lg;
}
int funcB(const int g[][E], size_t p, size_t t) {
int hg = 0;
for (size_t i = 0; i < p; ++i) {
for (size_t j = 0; j < t; ++j) {
if (g[i][j] > hg) hg = g[i][j];
}
}
return hg;
}
double funcC(const int sg[], size_t t) {
int tl = 0;
for (size_t i = 0; i < t; ++i)
tl += sg[i];
return (double)tl / t;
}
int main(void) {
int sg[S][E] = { { 73, 86, 68, 77 }, { 78, 89, 87, 96 }, { 81, 86, 90, 70 } };
printf("%d %d\n", funcA(sg, S, E), funcB(sg, S, E));
for (size_t s = 0; s < S; ++s)
printf("%u %.2f\n", s, funcC(sg[s], E));
}
登入後即可作答並保存紀錄。
核心觀念
本題主要考查:
- 二維陣列傳遞至函式的方式
const陣列參數- 巢狀迴圈走訪資料
- 最小值、最大值與平均值的計算
- 一維陣列與二維陣列列資料的對應
printf格式控制字串size_t型別與格式指定子的搭配
已知:
#define S 3
#define E 4
因此:
S表示共有 列E表示每列有 個整數sg是 的二維陣列,共有 筆成績
資料如下:
| 列索引 | 成績 |
|---|---|
| 0 | 73、86、68、77 |
| 1 | 78、89、87、96 |
| 2 | 81、86、90、70 |
函式參數:
const int g[][E]
表示傳入「每列固定有 E 個整數」的二維陣列。因為函式不會修改陣列內容,所以使用 const 限制資料不得被函式改寫。
解題方法
依照程式執行順序分析:
funcA逐一走訪全部成績,找出最小值。funcB逐一走訪全部成績,找出最大值。main先輸出全體成績的最小值與最大值。main再將每一列傳給funcC,計算每位考生的平均成績。
(一)說明下列程式之功能
此程式處理 位考生、每位考生 科的成績資料。
整體功能如下:
- 將所有成績中的最低分與最高分輸出。
- 逐位計算每位考生 科成績的平均分數。
- 平均分數以小數點後兩位顯示。
陣列中的所有成績為:
其中:
- 最低分為
- 最高分為
三位考生的平均分數分別為:
所以程式的預期功能是輸出全體成績的最低分、最高分,以及每位考生的編號與平均分數。
(二)說明 funcA 程式的功能
int funcA(const int g[][E], size_t p, size_t t)
參數意義:
g:二維成績陣列p:列數t:每列元素數量- 回傳值:所有資料中的最小值
函式先設定:
int lg = 100;
lg 可視為目前找到的最小值。接著透過兩層迴圈走訪:
for (size_t i = 0; i < p; ++i)
for (size_t j = 0; j < t; ++j)
其中:
i控制第幾列j控制該列中的第幾個元素g[i][j]表示第i列、第j欄的成績
若目前成績小於 lg,便更新最小值:
if (g[i][j] < lg) lg = g[i][j];
資料走訪結果中的最小值為:
因此:
funcA(sg, S, E)
回傳 。
功能結論:funcA 計算並回傳二維陣列指定範圍內的最小值。
(三)說明 funcB 程式的功能
int funcB(const int g[][E], size_t p, size_t t)
此函式使用兩層迴圈走訪二維陣列中的所有元素。
初始設定:
int hg = 0;
hg 表示目前找到的最大值。若目前成績大於 hg,便更新:
if (g[i][j] > hg) hg = g[i][j];
所有資料中的最大值為:
因此:
funcB(sg, S, E)
回傳 。
功能結論:funcB 計算並回傳二維陣列指定範圍內的最大值。
補充而言,hg 初始值設為 ,代表本題假設成績為非負數。若資料可能包含負數,這種寫法便不適合,應將初值設為第一個元素,或使用適當的最小整數值。
(四)說明 funcC 程式的功能
double funcC(const int sg[], size_t t)
此函式接收一維陣列,計算其中 t 個整數的平均值。
初始總和為:
int tl = 0;
透過迴圈累加每一個元素:
for (size_t i = 0; i < t; ++i)
tl += sg[i];
最後執行:
return (double)tl / t;
第 四 題
有關 Python 程式設計,請回答下列問題: (一) 下列程式執行結果為何?(7分)
def main():
i = 1
while i <= 4:
funcA(i, 3)
i += 1
def funcA(i, n):
for j in range(1, i + 1):
print(n, end = " ")
n *= 4
print()
main()
(二) 下列程式執行結果為何?(4分)
def main():
x = 1
print("{0:<5d} {1:<5.4f}".format(x, funcC(x)))
def funcC(i):
sum = 0
for j in range(1, i + 1):
sum += j / (2 * j + 1)
return sum
main()
(三) 請寫一個 Python 程式,它可以隨機產生 個 到 之間的整數,並能顯示每個數字出現的次數。(10分)
(四) 下列程式執行結果為何?(4分)
class ClassA:
def __init__(self, count = 0):
self.count = count
def main():
c = ClassA()
times = 0
for i in range(0, 100):
funcB(c, times)
print("count is " + str(c.count))
print("times is " + str(times))
def funcB(c, times):
c.count += 1
times += 1
main()
登入後即可作答並保存紀錄。
(一)程式執行結果
核心觀念
本題考查:
while迴圈的執行次數。for迴圈與range(1, i + 1)的範圍。- 函式參數
n為區域變數,每次呼叫funcA都重新由 開始。 print(..., end=" ")不換行,最後的print負責換行。n *= 4等同於n = n * 4。
解題方法
外層迴圈中, 依序為 。每次呼叫:
funcA(i, 3)
因此每次函式執行時,n 都重新設定為 。
| 的範圍 | 印出內容 | |
|---|---|---|
| 1 | 1 | |
| 2 | 1, 2 | |
| 3 | 1, 2, 3 | |
| 4 | 1, 2, 3, 4 |
例如 時:
【答案】
3
3 12
3 12 48
3 12 48 192
每一行最後均有換行;每個數字後面均因 end=" " 留有一個空格。
解題技巧
判斷此類題目時,須注意 n 不會跨越不同的 funcA 呼叫持續累加。因為每次呼叫都執行 n = 3,所以每一行都從 開始。
(二)程式執行結果
核心觀念
本題考查:
- 函式回傳值。
for j in range(1, i + 1)的迴圈範圍。- Python 的浮點數除法
/。 format的欄位格式:{0:<5d}:第 0 個資料,以整數格式輸出,靠左對齊,欄寬至少為 5。{1:<5.4f}:第 1 個資料,以浮點數格式輸出,小數點後 4 位,靠左對齊,欄寬至少為 5。
解題方法
main 中設定:
x = 1
呼叫:
funcC(x)
此時 i=1,因此:
for j in range(1, 2):
迴圈只執行一次,:
使用 .4f 後,取小數點後四位:
整數 以欄寬 5 靠左對齊,會在右側補上 4 個空格;格式字串中兩個欄位之間另有 1 個空格。
【答案】
1 0.3333
其中數字 1 與 0.3333 之間共有 5 個空格。
解題技巧
range(1, i + 1) 的終點不包含,因此 時只會處理 。此外,欄寬是「至少」指定寬度;若實際內容已超過欄寬,Python 不會截斷內容。