112 高普考普通考試 資訊處理 程式設計概要 考古題詳解

112 年・高普考・普通考試・資訊處理
試題代碼 程式設計概要

第 一 題25 分

根據以下 C 程式碼,回答下列問題:

#include <stdio.h>

void g(int *x, int *y) { *x = *y - 1; *y = *y - 2; printf("*x = %d, *y = %d\n", *x, *y); }

void f(int *z, int *w) { int n = 13; g(w, &n); printf("*z = %d, *w = %d, n = %d\n", *z, *w, n); }

int main() { int i = 21; int j = 5; int n = 137; f(&i, &j); printf("print 1: i = %d, j = %d, n = %d\n", i, j, n); g(&n, &n); printf("print 2: i = %d, j = %d, n = %d\n", i, j, n); return 0; }

(一)請說明程式碼第 8 行至第 12 行中,每一行之運算子符號 ∗* 及 &\& 操作所代表的意義。

(二)請問該程式碼執行後輸出的結果為何?

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

這一題的完整詳解

核心觀念

本題考 C 語言的指標、取址運算子 &、間接取值運算子 *,以及函式呼叫時傳入指標所造成的變數變化。

  • &變數:取得該變數的記憶體位址。
  • 指標:儲存記憶體位址的變數。
  • *指標:透過指標存取該位址上的變數值;用在指派左側時,會修改該變數。

呼叫函式時,C 語言仍是傳值;傳入指標時,複製的是位址,因此函式可透過該位址修改呼叫端的變數。

(一)運算子 * 與 & 的意義

題目第 8 行至第 12 行對應 f 函式中的程式:

int n = 13;
g(w, &n);
printf("*z = %d, *w = %d, n = %d\n", *z, *w, n);
  • g(w, &n) 中的 w 是指標變數,內容為呼叫端傳入的位址;直接使用 w,表示把這個位址傳給 g。
  • &n 使用取址運算子,取得 f 函式區域變數 n 的位址。
  • printf 格式字串中的 *z、*w 只是輸出的文字,不是運算式。
  • printf 引數中的 *z、*w 使用間接取值運算子,分別讀取 z、w 所指向的整數值。

(二)輸出結果

**解題方法:**逐次追蹤每個指標指向哪個變數,再依照 g 內的指派順序更新變數。特別注意,若兩個指標指向同一個變數,後一次指派會使用前一次更新後的值。

第一次呼叫 f(&i, &j)

呼叫時 z 指向 i,w 指向 j,而 f 內的區域變數 n 初值為 1313。

🔒

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

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

免費註冊

第 二 題25 分

根據以下 C 程式碼,回答下列問題:

#include <stdio.h>

int f(int a, int b) { if (b == 1) return a; else { int value = a + f(a, b - 1); return value; } }

int main() { printf("%d\n", f(5, 3)); printf("%d\n", f(0, 0)); }

(一)請問哪一行是此遞迴程式的中止條件?

(二)請說明第 10 行的輸出,以及其運作邏輯。

(三)請說明第 11 行的輸出,以及其運作邏輯。

(四)請說明函式 ff 的主要功能,包含輸入參數與輸出結果的關係。

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

這一題的完整詳解

核心觀念

本題考查遞迴函式的中止條件、函式呼叫與回傳值,以及如何由遞迴關係判斷函式功能。

函式 f(a, b) 的定義是:

  • 當 b == 1,回傳 a。
  • 否則,先計算 a + f(a, b - 1),再回傳結果。

解題方法

從遞迴呼叫的第二個參數逐步追蹤,直到符合中止條件;接著由最內層開始逐層代回計算。

(一)遞迴程式的中止條件

中止條件是第 2 行:

if (b == 1)

當 b 等於 1 時,函式直接執行 return a;,不再呼叫自己。

(二)第 10 行的輸出與運作邏輯

第 10 行執行 f(5, 3):

f(5, 3) = 5 + f(5, 2)
 = 5 + 5 + f(5, 1)
 = 5 + 5 + 5
 = 15

當 b 降為 1 時,符合中止條件,f(5, 1) 回傳 5。其餘兩層各自再加上 a = 5,因此輸出為:

15

(三)第 11 行的輸出與運作邏輯

第 11 行執行 f(0, 0)。因為 b 不等於 1,程式會持續呼叫 f(0, b - 1):

f(0, 0) → f(0, -1) → f(0, -2) → ⋯
🔒

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

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

免費註冊

第 三 題25 分

關於搜尋法程式:

(一)說明循序(Sequential)搜尋法,以及二元(Binary)搜尋法的優缺點。

(二)以下二元搜尋程式碼有部分錯誤。若要修正為正確程式,請說明「最少」需修改程式碼行數、原因與修改方法。

public class BinarySearch { public int faultyBinarySearch(int[] arr, int x) { int l = 0, r = arr.length - 1; int m = (l + r) / 2; while (l <= r) { m = (l + r) / 2; if (arr[m] == x) return m; if (arr[m] > x) l = m + 1; if (arr[m] < x) r = m - 1; } return -1; } }

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

這一題的完整詳解

核心觀念

本題考查循序搜尋(Sequential Search)與二元搜尋(Binary Search)的比較,以及二元搜尋程式中「比較結果後,應縮小哪一側搜尋範圍」的邏輯。

二元搜尋的前提是資料已依遞增或遞減順序排列。以遞增排列為例,令左、右界限分別為 ll 與 rr,每次取中間位置

m=⌊l+r2⌋m=\left\lfloor\frac{l+r}{2}\right\rfloor

再比較 arr[m]arr[m] 與目標值 xx。若 arr[m]<xarr[m]<x,目標只可能在右半部;若 arr[m]>xarr[m]>x,目標只可能在左半部。

解題方法

(一)兩種搜尋法的優缺點

搜尋法方法與時間複雜度優點缺點
循序搜尋從頭至尾逐一比較;最壞情況需比較 nn 次,時間複雜度為 O(n)O(n)不要求資料排序;實作簡單;適用於小型或未排序資料資料量大時搜尋較慢
二元搜尋每次比較中間元素並排除一半範圍;時間複雜度為 O(log⁡n)O(\log n)對大量資料搜尋效率高資料必須已排序,且通常需能以索引快速存取中間元素;維護排序資料也可能增加成本

(二)最少修改行數與修正方式

錯誤在兩個界限更新條件:程式把 arr[m]>xarr[m]>x 時的左界限往右移,把 arr[m]<xarr[m]<x 時的右界限往左移,方向都與二元搜尋的判斷相反。

  • 若 arr[m]>xarr[m]>x,較大的元素位於中間位置,目標若存在,只會在左半部,因此應令 r=m−1r=m-1。
  • 若 arr[m]<xarr[m]<x,目標若存在,只會在右半部,因此應令 l=m+1l=m+1。
🔒

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

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

免費註冊

第 四 題25 分

請依據以下 Java 程式碼回答下列問題:

import java.util.Scanner;

public class MyJavaCode { public static void main(String[] args) { Scanner in = new Scanner(System.in); int a = in.nextInt(); Animal dog = new Dog(); dog.run(a); dog.run(); } }

class Dog extends Animal { public void run(int units) { System.out.println("Dog's running speed is " + units); }

public void run() {
    System.out.println("Dog's default running speed is 20");
}

}

(一)請說明 Java 中 class、abstract class 與 interface 之間的主要差異。

(二)請說明上述程式碼那幾行會產生編譯錯誤,以及錯誤的原因。

(三)不改變原 1-19 行程式碼順序的條件下,請修正問題(二)之編譯問題,使之可以正常執行。修正不包含左右大括號「{}」,新增或修改之指令行數不可以超過 3 行。

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

這一題的完整詳解

核心觀念

本題考查 Java 的型別宣告、繼承與方法多載。class、abstract class 和 interface 都能定義型別,但在能否直接建立物件、能否包含實作內容,以及類別如何繼承或實作等方面有所不同。

  • class(一般類別):可包含欄位、建構子及已實作的方法;具體類別可以直接建立物件。Java 類別只能直接繼承一個父類別。
  • abstract class(抽象類別):以 abstract 宣告,不能直接建立物件,可包含抽象方法和已實作的方法,也可有欄位及建構子。子類別必須實作繼承而來的抽象方法,否則子類別也要宣告為抽象類別。
  • interface(介面):描述一組型別應提供的操作,類別以 implements 表示實作介面。一個類別可實作多個介面。介面可宣告抽象方法,也可包含 default、static 等方法;介面中的常數欄位具有 public static final 性質。

解題方法

先檢視每個型別是否已宣告,再檢查子類別是否完成父類別要求的抽象方法,最後檢查呼叫的方法是否存在於變數的編譯時型別。

(一)三種型別的主要差異

比較項目classabstract classinterface
可否直接建立物件具體類別可以不可以不可以
方法內容可有已實作的方法可有已實作及抽象方法可有抽象方法,也可有 default、static 等方法
繼承/實作關係類別只能直接繼承一個類別子類別以 extends 繼承類別以 implements 實作,可實作多個介面
常見用途建立具體物件提供共用狀態或部分實作,並要求子類別補完方法定義可由不同類別共同遵循的操作規格

(二)編譯錯誤及原因

會產生編譯錯誤的宣告是:

class Dog extends Animal {

原因是程式中沒有宣告 Animal 類別或介面,編譯器無法解析 Animal。因此 Dog 的父類別無效,後續 Animal dog = new Dog; 也無法通過編譯,因為 Animal 仍是未定義型別。

題目其餘方法本身並無錯誤:Dog 宣告了 run(int units) 與 run,兩者參數不同,屬於方法多載。但要讓整段程式可編譯,還需在 Dog 的父類別宣告中提供合法的 Animal 型別。

(三)修正程式

🔒

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

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

免費註冊

其他考古題