109 地方特考四等 資訊處理 程式設計概要 考古題詳解
第 一 題15 分
下列 C 程式的執行結果為何?
#include <stdio.h> #include <stdlib.h>
#define X 3 #define Y 4
void funA(int *, int, int), funB(int *, int, int);
int main(void) { int arr[X][Y] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printf("輸出1:\n");
funA(*arr, X, Y);
funB(*arr, X, Y);
printf("輸出2:\n");
funA(*arr, X, Y);
system("pause");
return 0;
}
void funA(int *ptr, int x, int y) { int i, j;
for (i = 0; i < x; i++) {
for (j = 0; j < y; j++)
printf("%3d ", *(ptr + i * y + j));
printf("\n");
}
}
void funB(int *ptr, int x, int y) { int i, j; int arr[x][y];
for (i = 0; i < x; i++)
for (j = 0; j < y; j++)
arr[x - i - 1][y - j - 1] = *(ptr + i * y + j);
for (i = 0; i < x; i++)
for (j = 0; j < y; j++)
*(ptr + i * y + j) = arr[i][j];
}
登入後即可作答並保存紀錄。
核心觀念
-
二維陣列在記憶體中的配置(Row-Major Order): C 語言的二維陣列採用「列主序」連續配置於記憶體中。對於維度為 的二維陣列,元素
arr[i][j]在一維連續空間中的相對位移量為: 指標型態若為指向整數的指標int *ptr,則*(ptr + i * y + j)等價於以二維索引存取元素arr[i][j]。 -
陣列名稱的型態衰減(Array Decay)與指標傳遞: 在
main函式中宣告int arr[X][Y],其名稱arr代表陣列首列的指標,型態為int (*)[4];而*arr即代表首列首元素的位址&arr[0][0],型態衰減為int *。將其傳遞給funA與funB的參數int *ptr,即可透過該單一指標走訪整個連續配置的二維陣列。 -
可變長度陣列(Variable-Length Array, VLA)與空間反轉:
funB內部宣告了區域陣列int arr[x][y]作為暫存空間,並利用對稱索引公式將二維資料首尾顛倒存放,再寫回原始記憶體,實現二維陣列元素的 180 度旋轉(或等同於一維連續空間的完全逆序置換)。 -
格式化輸出控制字元:
printf("%3d ", ...)表示以至少 3 格欄寬靠右對齊輸出整數,若位數不足則左方補空格,數值後方緊接一個空格。
解題方法
步驟一:分析初始陣列配置
在 main 函式中定義:
維度 (列數)、(行數)。在連續記憶體中,其存放順序為:。
步驟二:追蹤「輸出1:」與第一次 funA 呼叫
- 程式執行
printf("輸出1:\n");,先印出標題字串並換行。 - 呼叫
funA(*arr, 3, 4): 雙重迴圈中, 由 至 , 由 至 ,依序以*(ptr + i * 4 + j)讀取元素。 - 當 :印出
1、2、3、4,隨後換行。 - 當 :印出
5、6、7、8,隨後換行。 - 當 :印出
9、10、11、12,隨後換行。
步驟三:追蹤 funB 的陣列內容反轉
- 第一個雙重迴圈:
公式為
arr[x - i - 1][y - j - 1] = *(ptr + i * y + j),將原始陣列中座標 的元素存入暫存陣列arr的對稱座標 。
第 二 題15 分
請依行號解說下列 Python 程式碼,並說明此程式的功能為何?
01 while(True): 02 number=input("請輸入至少三位數的整數值或輸入 'q' 或 'Q' 結束程式:") 03 if(number.upper()!='Q'): 04 while(len(number)<3): 05 number=input("輸入值至少須為三位數,請重新輸入:") 06 listA = [] 07 for x in number: 08 listA.append(int(x))
10 var=0 11 for y in listA[0:len(listA)-1]: 12 var+=y 13 if (var%10==listA[-1]): 14 print(var%10, listA[-1], number, "is acceptable") 15 else: 16 print(var%10, listA[-1], number, "is unacceptable") 17 else: 18 break
登入後即可作答並保存紀錄。
核心觀念
本題評量 Python 程式語言的基礎語法掌握度、資料結構操作及同餘演算法之理解,核心概念包含:
- 控制流程結構:
while無窮迴圈控制、break強制中斷迴圈、巢狀迴圈(Nested Loops)與if-else雙向條件分支。 - 字串與型態轉換:
input輸入處理、str.upper大小寫轉換、len字串長度計算,以及int將字元型態強制轉型為整數型態。 - 串列(List)與切片(Slicing):
list.append動態新增元素、半開區間切片語法list[start:end](包含start,不包含end)、負數索引(Negative Indexing,如list[-1]代表最後一個元素)。 - 檢查碼(Check Digit)演算法:利用模除運算子
%(求餘數)計算驗證碼,檢驗資料傳輸或輸入時之正確性(常見於身分證字號、條碼檢核機制)。
解題方法
解析本題需分為兩大核心部分:第一部分依行號依序詳解各語句的語法與執行邏輯;第二部分綜合演算法邏輯,以具體範例歸納並定案該程式的整體功能。
一、 逐行程式碼詳細解說
- 第 01 行
while(True):建立條件永遠為真的無窮迴圈,持續接收使用者的輸入,直到執行到第 18 行的break指令才會終止。 - 第 02 行
number=input("請輸入至少三位數的整數值或輸入 'q' 或 'Q' 結束程式:")提示使用者輸入字串,並將輸入結果以字串型態指派給變數number。 - 第 03 行
if(number.upper!='Q'):呼叫字串方法upper將輸入轉為大寫,檢查是否不等於'Q'。若使用者輸入不是'q'或'Q',則進入驗證區塊;若為'q'或'Q',則跳至第 17 行的else。 - 第 04 行
while(len(number)<3):檢查字串number的長度是否小於 3 位數。若不足三位數,進入校驗防錯迴圈。 - 第 05 行
number=input("輸入值至少須為三位數,請重新輸入:")印出提示訊息並要求使用者重新輸入,重複此步驟直到輸入字串長度大於或等於 3。 - 第 06 行
listA = []宣告並初始化一個名為listA的空串列,用以儲存各個位數的數值。 - 第 07 行
for x in number:以for迴圈逐一走訪字串number中的每一個字元x。 - 第 08 行
listA.append(int(x))透過int(x)將走訪到的每個數字字元轉為整數型態,並呼叫append依序新增至listA中。 - 第 09 行(程式碼為空行) 空白行,用於區隔資料輸入與資料運算邏輯,增加程式碼可讀性。
- 第 10 行
var=0初始化整數累加變數var為 0。 - 第 11 行
for y in listA[0:len(listA)-1]:利用串列切片[0:len(listA)-1],取出從索引 0 到倒數第二個元素(即排除最後一位數),透過for迴圈逐一走訪該子串列中的數字y。 - 第 12 行
var+=y進行累加運算,將除了最後一位數字以外的所有位數數值相加,並存入var。 - 第 13 行
if (var%10==listA[-1]):計算累加值var除以 10 的餘數(即 ),並判斷該餘數是否等於串列最後一個元素listA[-1](即原輸入值的最後一位數)。 - 第 14 行
print(var%10, listA[-1], number, "is acceptable")若條件成立(餘數等於最後一位數),印出計算所得餘數、最後一位數、原始輸入值以及字串"is acceptable"。 - 第 15 行
else:若條件不成立(餘數不等於最後一位數),進入此分支。 - 第 16 行
print(var%10, listA[-1], number, "is unacceptable")
第 三 題25 分
請使用 C 程式語言撰寫一猜數字遊戲程式,此程式必須滿足下列規定:
-
撰寫一函式
int Randomize(int n),可回傳一個隨機產生介於 1 到 間(包含 1 與 )的正整數,此正整數即為此遊戲的答案。 -
利用上述函式實作一猜數字遊戲。此遊戲開始時先讓使用者輸入此猜數字遊戲的最大值,程式須確認使用者所輸入的數值必須大於 20。
-
使用者每次猜答時,程式必須顯示出是第幾次的猜答。
-
使用者每次輸入後,程式必須顯示結果;如果猜錯時,程式必須依使用者的輸入值縮小範圍;當猜對時,顯示「恭喜你猜對了!」。
-
當使用者猜答次數超過 10 次仍未猜中答案時,程式就必須結束使用者的猜答,並顯示出正確答案。
程式執行範例如下:
請輸入答案的可能最大值(至少必須大於 20):15
輸入錯誤!15 沒有大於 20,請重新輸入!
請輸入答案的可能最大值(至少必須大於 20):30
第 1 次猜答:15
結果為:猜錯了,答案介於 15 與 30 之間!
第 2 次猜答:23
結果為:猜錯了,答案介於 15 與 23 之間!
第 3 次猜答:19
結果為:猜錯了,答案介於 15 與 19 之間!
第 4 次猜答:17
結果為:猜錯了,答案介於 17 與 19 之間!
第 5 次猜答:18
結果為:恭喜你猜對了!
請按任意鍵繼續 . . .
登入後即可作答並保存紀錄。
核心觀念
本題評量考生對 C 語言基本語法、標準函式庫運用以及程序控制結構的綜合實作能力,核心觀念涵蓋以下四項:
- 亂數產生原理與範圍映射:
- 使用
<stdlib.h>的rand函式可產生介於 至RAND_MAX之間的偽隨機整數。 - 透過取餘數運算子與平移量,將數值區間映射至 :
- 配合
<time.h>的time(NULL)做為種子傳入srand,確保每次程式執行時產生的亂數序列不同。
- 輸入驗證與條件迴圈(Input Validation):
- 運用
while迴圈或do-while迴圈配合條件判斷式if,檢驗使用者輸入之數值是否符合嚴格大於 20()之規格;若不符則持續要求重新輸入。
- 區間邊界動態更新(State Tracking):
- 模擬經典「終極密碼」二分逼近邏輯,宣告變數維護當前有效範圍的下界(
low)與上界(high)。 - 當猜測值小於答案時更新下界,大於答案時更新上界,逐步縮小範圍。
- 迴圈計數器與終止條件控制:
- 限制最大猜答次數為 10 次,透過計數器
count與布林/旗標變數win控制遊戲提早結束(猜對)或超過次數失敗終止之分支邏輯。
解題方法
本題採結構化程式設計(Modular Programming),分為「自訂亂數函式」與「主程式流程」兩大區塊:
- 設計函式
int Randomize(int n):
- 依題意接收整數參數 ,利用運算式
(rand % n) + 1計算出介於 到 間的正整數並回傳。
- 最大值輸入與驗證:
- 提示使用者輸入上限值 。
- 使用
while (n <= 20)檢核,若數值小於等於 20,印出指定錯誤提示字串並重新讀取,直至使用者輸入合法數值為止。
- 初始化遊戲環境:
- 於
main開頭呼叫srand((unsigned int)time(NULL));初始化亂數產生器。 - 呼叫
Randomize(n)取得謎底正整數answer。 - 設定初始範圍下界
low = 1,上界high = n。
- 猜答主迴圈實作:
- 設置
for迴圈使計數器從第 1 次至第 10 次迭代。 - 每次印出
第 %d 次猜答:並以scanf讀入猜答值guess。 - 判斷邏輯如下:
- 若
guess == answer:印出「結果為:恭喜你猜對了!」,將旗標標記為已猜中,並以break跳出迴圈。 - 若
guess < answer:若guess > low則更新low = guess,印出縮小後的提示訊息。 - 若
guess > answer:若guess < high則更新high = guess,印出縮小後的提示訊息。
- 超次判斷與結果處理:
- 離開迴圈後,檢視旗標;若 10 次均未猜中,依規定印出遊戲結束訊息並揭示正確答案。
選項分析
本題為程式設計實作題(非選擇題),無選項分析。
解題技巧
第 四 題20 分
下列 C 程式的執行結果為何?
#include <stdio.h> #include <stdlib.h>
int funA(int x), funB(int y);
int main(void) { printf("funA(5)=%d, funB(5)=%d\n", funA(5), funB(5));
return 0;
}
int funA(int x) { int i, answer = 1;
if (x < 1)
return -1;
for (i = 1; i <= x; i++)
answer *= (i * 2);
return answer;
}
int funB(int y) { if (y < 1) return -1; else if (y == 1) return 3; else return 3 * y + funB(y - 1); }
登入後即可作答並保存紀錄。
核心觀念
本題評量 C 語言的兩大核心控制結構:迭代迴圈(Iteration)與遞迴呼叫(Recursion),並測驗考生的程式追蹤能力與基礎數學轉化能力:
- 迴圈累乘(函式
funA):
- 考查
for迴圈的初值、終止條件與累乘運算(*=)。 - 數學本質為偶數連乘積,即雙階乘(Double Factorial)或階乘的倍數型態:
- 遞迴函式(函式
funB):
- 考查遞迴的兩大要素:基本終止條件(Base Case)與遞迴關係式(Recursive Step)。
- 數學本質為等差級數求和的遞迴定義: 終止於 。
- 格式化輸出(
printf):
- 評量格式化字串的精確比對,包含字串常數、逗號、空格與換行字元。
解題方法
一、追蹤與推導 funA(5)
- 進入函式:傳入引數 。
- 邊界判斷: 條件為假( 為假),不執行
return -1。 - 迴圈迭代:變數初值
answer = 1,迴圈由 執行至 :
- 當 :
- 當 :
- 當 :
- 當 :
- 當 :
- 迴圈結束: 時跳出迴圈,回傳值為 。
二、追蹤與推導 funB(5)
- 進入函式:傳入引數 。
- 遞迴關係展開:
第 五 題25 分
請使用 C++、Java 或 Python 程式語言為三角形面積計算公式設計一個名稱為 HeronFormula 的類別,並撰寫一測試程式驗證此類別程式碼的正確性。
此類別須包含:
-
三邊長的私有資料 、、。
-
三邊長 、、 的初始化設定或建構元方法。
-
inputSide()公有方法:讓使用者輸入三邊長 、、。此方法須能確認使用者所輸入的三邊長皆須大於 0,另此方法不須回傳值。 -
getAssessResult()公有方法:判斷三邊長 、、 是否可以構成三角形。如果可以的話則回傳布林型別(Boolean)「真」,如果不可以的話則回傳「假」。 -
getPerimeter()公有方法:回傳三角形的周長。此方法須呼叫getAssessResult()方法;如果回傳值為「真」則回傳三角形的周長,如果回傳值為「假」則回傳 。 -
getArea()公有方法:回傳三角形的面積。此方法須呼叫getAssessResult()方法;如果回傳值為「真」則回傳三角形的面積,如果回傳值為「假」則回傳 。三角形面積的 Heron 計算公式為:
其中:
程式執行範例如下:
請輸入大於 0 的三邊長:-3, 6, 9
輸入錯誤,請重新輸入大於 0 的三邊長:3, 6, 9
所輸入的三個值無法構成三角形
繼續玩嗎?若想繼續玩,請按 'y' 或 'Y':y
請輸入大於 0 的三邊長:3, 4, 5
周長等於:12
面積等於:6.0
繼續玩嗎?若想繼續玩,請按 'y' 或 'Y':n
登入後即可作答並保存紀錄。
核心觀念
本題旨在評量考生於物件導向程式設計(Object-Oriented Programming, OOP)中的基礎實作能力,主要涵蓋以下核心觀念:
- 資訊隱藏與封裝(Encapsulation):將屬性設為私有(Private),外部無法直接存取,必須透過類別提供的公有方法(Public Methods)進行互動與修改。
- 建構元/初始化方法(Constructor):物件實體化時負責屬性初始化的機制。
- 防禦性設計與輸入驗證(Input Validation):於
inputSide中過濾非正數()之輸入,並以迴圈控制重試流程,確保物件狀態合規。 - 三角形幾何構成定理:任意三正數邊長 能構成三角形的充要條件為「任兩邊之和大於第三邊」:
- 海倫公式(Heron's Formula):設三角形半周長為 ,其面積為:
- 方法重用(Method Reuse):在計算周長與面積時,直接呼叫內部已封裝的判定方法
getAssessResult,避免重複撰寫檢核邏輯。
解題方法
本題允許使用 C++、Java 或 Python。在國家考試手寫程式碼的情境下,Python 語法最為精簡、無冗贅樣板程式碼,能大幅縮短作答時間並降低手寫漏寫符號的風險;Java 則為標準強型別物件導向語言,能精確對應題目「私有資料」、「建構元」與「布林型別」等專有名詞。
整體實作步驟如下:
- 宣告類別與私有屬性:定義類別
HeronFormula,內部包含 三個私有屬性。 - 實作建構元:提供建構元將 預設初始化為 0。
- 實作
inputSide:
- 使用迴圈持續提示使用者輸入三邊長。
- 解析字串輸入(支援逗號或空白分隔),驗證三數皆大於 0()。
- 若不符規格,輸出「輸入錯誤,請重新輸入大於 0 的三邊長:」並再次讀取;若符合則寫入私有屬性並結束方法,無回傳值。
- 實作
getAssessResult:驗證是否滿足三邊各任兩邊之和大於第三邊,回傳布林值(Boolean)。 - 實作
getPerimeter與getArea:
- 兩者內部第一步皆須呼叫
getAssessResult。 - 若為真,分別計算周長 與海倫公式面積;若為假,一律回傳 。
- 撰寫測試主程式:
- 建立
while迴圈控制「繼續玩嗎?」之流程,以字元'y'或'Y'決定是否持續執行。 - 依序呼叫
inputSide,並以getAssessResult判斷是否能構成三角形,依題目格式印出結果。
選項分析
本題為非選擇題(程式設計實作題),無固定選項。依據試題評分標準,各題旨規格與實作要點評析如下:
- 規格 1(私有資料 ):若在 Python 中未加上雙底線(如
__a),或在 Java 中未宣告為private,將違反物件導向封裝原則而失分。 - 規格 2(初始化設定或建構元):必須包含初始化邏輯(Python 的
__init__或 Java 的同名 Constructor),確保物件產生時狀態確定。 - 規格 3(
inputSide無回傳值且防呆):此方法回傳值必須為空(None或void)。驗證必須包含「小於等於 0 之數值」與「格式不符」,且必須能反覆提示直到使用者輸入正確數值為止。 - 規格 4(
getAssessResult判斷邏輯):必須完整列出三個不等式條件;若僅比較最大邊與其餘兩邊之和,須先進行排序。直接判斷三組任兩邊和大於第三邊最為直觀且不易出錯。 - 規格 5 與 6(
getPerimeter與getArea必須呼叫getAssessResult):閱卷重點在於是否有「方法間的呼叫(Method Call)」。若在getPerimeter或getArea內直接重新計算三角形判斷而未呼叫getAssessResult,將被嚴重扣分;且檢驗失敗時必須回傳 。 - 測試程式互動性:測試迴圈須精確比對使用者輸入之字元(大小寫
'y'與'Y'),並依照題目指定之範例字串格式輸出。
解題技巧
- 手寫考卷語言首選 Python:國家考試作答卷空間有限,Python 行數少、不需匯入過多套件(僅需
math.sqrt),且免去型別宣告與分號,手寫負擔最小。 - 輸入字串切割容錯:題目範例輸入格式包含逗號與空白(如
-3, 6, 9),處理時使用.split(',')分割後去除頭尾空白,可避免型別轉換錯誤。 - 避免根號內負數錯誤:若未檢驗三角形即代入海倫公式,當三邊無法構成三角形時, 會出現負數,造成開根號產生數學例外(Domain Error)。因此依題目要求先呼叫
getAssessResult能確保數學計算的安全性。
【答案】
本題提供 Python(建議考場作答使用)與 Java 兩種標準參考解答。