109 地方特考四等 資訊處理 程式設計概要 考古題詳解

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];

}

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

這一題的完整詳解

核心觀念

  1. 二維陣列在記憶體中的配置(Row-Major Order): C 語言的二維陣列採用「列主序」連續配置於記憶體中。對於維度為 x×yx \times y 的二維陣列,元素 arr[i][j] 在一維連續空間中的相對位移量為: Offset=i×y+j\text{Offset} = i \times y + j 指標型態若為指向整數的指標 int *ptr,則 *(ptr + i * y + j) 等價於以二維索引存取元素 arr[i][j]。

  2. 陣列名稱的型態衰減(Array Decay)與指標傳遞: 在 main 函式中宣告 int arr[X][Y],其名稱 arr 代表陣列首列的指標,型態為 int (*)[4];而 *arr 即代表首列首元素的位址 &arr[0][0],型態衰減為 int *。將其傳遞給 funA 與 funB 的參數 int *ptr,即可透過該單一指標走訪整個連續配置的二維陣列。

  3. 可變長度陣列(Variable-Length Array, VLA)與空間反轉: funB 內部宣告了區域陣列 int arr[x][y] 作為暫存空間,並利用對稱索引公式將二維資料首尾顛倒存放,再寫回原始記憶體,實現二維陣列元素的 180 度旋轉(或等同於一維連續空間的完全逆序置換)。

  4. 格式化輸出控制字元: printf("%3d ", ...) 表示以至少 3 格欄寬靠右對齊輸出整數,若位數不足則左方補空格,數值後方緊接一個空格。


解題方法

步驟一:分析初始陣列配置

在 main 函式中定義: arr=[123456789101112]arr = \begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \end{bmatrix} 維度 X=3X = 3(列數)、Y=4Y = 4(行數)。在連續記憶體中,其存放順序為:1,2,3,4,5,6,7,8,9,10,11,121, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12。

步驟二:追蹤「輸出1:」與第一次 funA 呼叫

  • 程式執行 printf("輸出1:\n");,先印出標題字串並換行。
  • 呼叫 funA(*arr, 3, 4): 雙重迴圈中,ii 由 00 至 22,jj 由 00 至 33,依序以 *(ptr + i * 4 + j) 讀取元素。
  • 當 i=0i = 0:印出 1、2、3、4,隨後換行。
  • 當 i=1i = 1:印出 5、6、7、8,隨後換行。
  • 當 i=2i = 2:印出 9、10、11、12,隨後換行。

步驟三:追蹤 funB 的陣列內容反轉

  • 第一個雙重迴圈: 公式為 arr[x - i - 1][y - j - 1] = *(ptr + i * y + j),將原始陣列中座標 (i,j)(i, j) 的元素存入暫存陣列 arr 的對稱座標 (x−1−i,y−1−j)(x - 1 - i, y - 1 - j)。
🔒

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

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

免費註冊

第 二 題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 程式語言的基礎語法掌握度、資料結構操作及同餘演算法之理解,核心概念包含:

  1. 控制流程結構:while 無窮迴圈控制、break 強制中斷迴圈、巢狀迴圈(Nested Loops)與 if-else 雙向條件分支。
  2. 字串與型態轉換:input 輸入處理、str.upper 大小寫轉換、len 字串長度計算,以及 int 將字元型態強制轉型為整數型態。
  3. 串列(List)與切片(Slicing):list.append 動態新增元素、半開區間切片語法 list[start:end](包含 start,不包含 end)、負數索引(Negative Indexing,如 list[-1] 代表最後一個元素)。
  4. 檢查碼(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 的餘數(即 var(mod10)var \pmod{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")
🔒

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

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

免費註冊

第 三 題25 分

請使用 C 程式語言撰寫一猜數字遊戲程式,此程式必須滿足下列規定:

  1. 撰寫一函式 int Randomize(int n),可回傳一個隨機產生介於 1 到 nn 間(包含 1 與 nn)的正整數,此正整數即為此遊戲的答案。

  2. 利用上述函式實作一猜數字遊戲。此遊戲開始時先讓使用者輸入此猜數字遊戲的最大值,程式須確認使用者所輸入的數值必須大於 20。

  3. 使用者每次猜答時,程式必須顯示出是第幾次的猜答。

  4. 使用者每次輸入後,程式必須顯示結果;如果猜錯時,程式必須依使用者的輸入值縮小範圍;當猜對時,顯示「恭喜你猜對了!」。

  5. 當使用者猜答次數超過 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 語言基本語法、標準函式庫運用以及程序控制結構的綜合實作能力,核心觀念涵蓋以下四項:

  1. 亂數產生原理與範圍映射:
  • 使用 <stdlib.h> 的 rand 函式可產生介於 00 至 RAND_MAX 之間的偽隨機整數。
  • 透過取餘數運算子與平移量,將數值區間映射至 [1,n][1, n]: Random Number=(rand mod n)+1\text{Random Number} = (\text{rand} \bmod n) + 1
  • 配合 <time.h> 的 time(NULL) 做為種子傳入 srand,確保每次程式執行時產生的亂數序列不同。
  1. 輸入驗證與條件迴圈(Input Validation):
  • 運用 while 迴圈或 do-while 迴圈配合條件判斷式 if,檢驗使用者輸入之數值是否符合嚴格大於 20(n>20n > 20)之規格;若不符則持續要求重新輸入。
  1. 區間邊界動態更新(State Tracking):
  • 模擬經典「終極密碼」二分逼近邏輯,宣告變數維護當前有效範圍的下界(low)與上界(high)。
  • 當猜測值小於答案時更新下界,大於答案時更新上界,逐步縮小範圍。
  1. 迴圈計數器與終止條件控制:
  • 限制最大猜答次數為 10 次,透過計數器 count 與布林/旗標變數 win 控制遊戲提早結束(猜對)或超過次數失敗終止之分支邏輯。

解題方法

本題採結構化程式設計(Modular Programming),分為「自訂亂數函式」與「主程式流程」兩大區塊:

  1. 設計函式 int Randomize(int n):
  • 依題意接收整數參數 nn,利用運算式 (rand % n) + 1 計算出介於 11 到 nn 間的正整數並回傳。
  1. 最大值輸入與驗證:
  • 提示使用者輸入上限值 nn。
  • 使用 while (n <= 20) 檢核,若數值小於等於 20,印出指定錯誤提示字串並重新讀取,直至使用者輸入合法數值為止。
  1. 初始化遊戲環境:
  • 於 main 開頭呼叫 srand((unsigned int)time(NULL)); 初始化亂數產生器。
  • 呼叫 Randomize(n) 取得謎底正整數 answer。
  • 設定初始範圍下界 low = 1,上界 high = n。
  1. 猜答主迴圈實作:
  • 設置 for 迴圈使計數器從第 1 次至第 10 次迭代。
  • 每次印出 第 %d 次猜答: 並以 scanf 讀入猜答值 guess。
  • 判斷邏輯如下:
  • 若 guess == answer:印出「結果為:恭喜你猜對了!」,將旗標標記為已猜中,並以 break 跳出迴圈。
  • 若 guess < answer:若 guess > low 則更新 low = guess,印出縮小後的提示訊息。
  • 若 guess > answer:若 guess < high 則更新 high = guess,印出縮小後的提示訊息。
  1. 超次判斷與結果處理:
  • 離開迴圈後,檢視旗標;若 10 次均未猜中,依規定印出遊戲結束訊息並揭示正確答案。

選項分析

本題為程式設計實作題(非選擇題),無選項分析。


解題技巧

🔒

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

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

免費註冊

第 四 題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),並測驗考生的程式追蹤能力與基礎數學轉化能力:

  1. 迴圈累乘(函式 funA):
  • 考查 for 迴圈的初值、終止條件與累乘運算(*=)。
  • 數學本質為偶數連乘積,即雙階乘(Double Factorial)或階乘的倍數型態: ∏i=1n2i=2n×n!\prod_{i=1}^{n} 2i = 2^n \times n!
  1. 遞迴函式(函式 funB):
  • 考查遞迴的兩大要素:基本終止條件(Base Case)與遞迴關係式(Recursive Step)。
  • 數學本質為等差級數求和的遞迴定義: funB(y)=3y+funB(y−1)\text{funB}(y) = 3y + \text{funB}(y-1) 終止於 funB(1)=3\text{funB}(1) = 3。
  1. 格式化輸出(printf):
  • 評量格式化字串的精確比對,包含字串常數、逗號、空格與換行字元。

解題方法

一、追蹤與推導 funA(5)

  1. 進入函式:傳入引數 x=5x = 5。
  2. 邊界判斷:x<1x < 1 條件為假(5<15 < 1 為假),不執行 return -1。
  3. 迴圈迭代:變數初值 answer = 1,迴圈由 i=1i = 1 執行至 i=5i = 5:
  • 當 i=1i = 1:answer=1×(1×2)=2\text{answer} = 1 \times (1 \times 2) = 2
  • 當 i=2i = 2:answer=2×(2×2)=2×4=8\text{answer} = 2 \times (2 \times 2) = 2 \times 4 = 8
  • 當 i=3i = 3:answer=8×(3×2)=8×6=48\text{answer} = 8 \times (3 \times 2) = 8 \times 6 = 48
  • 當 i=4i = 4:answer=48×(4×2)=48×8=384\text{answer} = 48 \times (4 \times 2) = 48 \times 8 = 384
  • 當 i=5i = 5:answer=384×(5×2)=384×10=3840\text{answer} = 384 \times (5 \times 2) = 384 \times 10 = 3840
  1. 迴圈結束:i=6i = 6 時跳出迴圈,回傳值為 38403840。

二、追蹤與推導 funB(5)

  1. 進入函式:傳入引數 y=5y = 5。
  2. 遞迴關係展開:
  • funB(5)=3×5+funB(4)=15+funB(4)\text{funB}(5) = 3 \times 5 + \text{funB}(4) = 15 + \text{funB}(4)
  • funB(4)=3×4+funB(3)=12+funB(3)\text{funB}(4) = 3 \times 4 + \text{funB}(3) = 12 + \text{funB}(3)
  • funB(3)=3×3+funB(2)=9+funB(2)\text{funB}(3) = 3 \times 3 + \text{funB}(2) = 9 + \text{funB}(2)
🔒

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

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

免費註冊

第 五 題25 分

請使用 C++、Java 或 Python 程式語言為三角形面積計算公式設計一個名稱為 HeronFormula 的類別,並撰寫一測試程式驗證此類別程式碼的正確性。

此類別須包含:

  1. 三邊長的私有資料 aa、bb、cc。

  2. 三邊長 aa、bb、cc 的初始化設定或建構元方法。

  3. inputSide() 公有方法:讓使用者輸入三邊長 aa、bb、cc。此方法須能確認使用者所輸入的三邊長皆須大於 0,另此方法不須回傳值。

  4. getAssessResult() 公有方法:判斷三邊長 aa、bb、cc 是否可以構成三角形。如果可以的話則回傳布林型別(Boolean)「真」,如果不可以的話則回傳「假」。

  5. getPerimeter() 公有方法:回傳三角形的周長。此方法須呼叫 getAssessResult() 方法;如果回傳值為「真」則回傳三角形的周長,如果回傳值為「假」則回傳 −1-1。

  6. getArea() 公有方法:回傳三角形的面積。此方法須呼叫 getAssessResult() 方法;如果回傳值為「真」則回傳三角形的面積,如果回傳值為「假」則回傳 −1-1。三角形面積的 Heron 計算公式為:

s(s−a)(s−b)(s−c)\sqrt{s(s-a)(s-b)(s-c)}

其中:

s=a+b+c2s=\frac{a+b+c}{2}

程式執行範例如下:

請輸入大於 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)中的基礎實作能力,主要涵蓋以下核心觀念:

  1. 資訊隱藏與封裝(Encapsulation):將屬性設為私有(Private),外部無法直接存取,必須透過類別提供的公有方法(Public Methods)進行互動與修改。
  2. 建構元/初始化方法(Constructor):物件實體化時負責屬性初始化的機制。
  3. 防禦性設計與輸入驗證(Input Validation):於 inputSide 中過濾非正數(≤0\le 0)之輸入,並以迴圈控制重試流程,確保物件狀態合規。
  4. 三角形幾何構成定理:任意三正數邊長 a,b,ca, b, c 能構成三角形的充要條件為「任兩邊之和大於第三邊」: a+b>c∧a+c>b∧b+c>aa + b > c \quad \land \quad a + c > b \quad \land \quad b + c > a
  5. 海倫公式(Heron's Formula):設三角形半周長為 s=a+b+c2s = \frac{a+b+c}{2},其面積為: Area=s(s−a)(s−b)(s−c)\text{Area} = \sqrt{s(s-a)(s-b)(s-c)}
  6. 方法重用(Method Reuse):在計算周長與面積時,直接呼叫內部已封裝的判定方法 getAssessResult,避免重複撰寫檢核邏輯。

解題方法

本題允許使用 C++、Java 或 Python。在國家考試手寫程式碼的情境下,Python 語法最為精簡、無冗贅樣板程式碼,能大幅縮短作答時間並降低手寫漏寫符號的風險;Java 則為標準強型別物件導向語言,能精確對應題目「私有資料」、「建構元」與「布林型別」等專有名詞。

整體實作步驟如下:

  1. 宣告類別與私有屬性:定義類別 HeronFormula,內部包含 a,b,ca, b, c 三個私有屬性。
  2. 實作建構元:提供建構元將 a,b,ca, b, c 預設初始化為 0。
  3. 實作 inputSide:
  • 使用迴圈持續提示使用者輸入三邊長。
  • 解析字串輸入(支援逗號或空白分隔),驗證三數皆大於 0(a>0∧b>0∧c>0a > 0 \land b > 0 \land c > 0)。
  • 若不符規格,輸出「輸入錯誤,請重新輸入大於 0 的三邊長:」並再次讀取;若符合則寫入私有屬性並結束方法,無回傳值。
  1. 實作 getAssessResult:驗證是否滿足三邊各任兩邊之和大於第三邊,回傳布林值(Boolean)。
  2. 實作 getPerimeter 與 getArea:
  • 兩者內部第一步皆須呼叫 getAssessResult。
  • 若為真,分別計算周長 a+b+ca+b+c 與海倫公式面積;若為假,一律回傳 −1-1。
  1. 撰寫測試主程式:
  • 建立 while 迴圈控制「繼續玩嗎?」之流程,以字元 'y' 或 'Y' 決定是否持續執行。
  • 依序呼叫 inputSide,並以 getAssessResult 判斷是否能構成三角形,依題目格式印出結果。

選項分析

本題為非選擇題(程式設計實作題),無固定選項。依據試題評分標準,各題旨規格與實作要點評析如下:

  • 規格 1(私有資料 a,b,ca, b, c):若在 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,將被嚴重扣分;且檢驗失敗時必須回傳 −1-1。
  • 測試程式互動性:測試迴圈須精確比對使用者輸入之字元(大小寫 'y' 與 'Y'),並依照題目指定之範例字串格式輸出。

解題技巧

  1. 手寫考卷語言首選 Python:國家考試作答卷空間有限,Python 行數少、不需匯入過多套件(僅需 math.sqrt),且免去型別宣告與分號,手寫負擔最小。
  2. 輸入字串切割容錯:題目範例輸入格式包含逗號與空白(如 -3, 6, 9),處理時使用 .split(',') 分割後去除頭尾空白,可避免型別轉換錯誤。
  3. 避免根號內負數錯誤:若未檢驗三角形即代入海倫公式,當三邊無法構成三角形時,s(s−a)(s−b)(s−c)s(s-a)(s-b)(s-c) 會出現負數,造成開根號產生數學例外(Domain Error)。因此依題目要求先呼叫 getAssessResult 能確保數學計算的安全性。

【答案】

本題提供 Python(建議考場作答使用)與 Java 兩種標準參考解答。

解法一:Python 實作

🔒

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

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

免費註冊

其他考古題