得能教育 Telearn Logo

得能教育 APCS識讀

第一部分:解構新制APCS程式識讀測驗

1.1 洞悉2025年的變革:從語法到綜合分析

大學程式能力先修檢測(APCS)自114學年度起,其「程式識讀」項目迎來了一次深刻的變革。這次優化不僅是題型或範圍的微調,而是一次測驗哲學的根本轉變:從過去側重語法記憶與片段程式碼執行的評量,進化為對計算思維程式邏輯效能分析除錯能力的綜合性檢驗。這意味著,考生不再能僅僅依賴刷題、背誦特定題型模式來獲取高分。新制度的目標是篩選出那些不僅能「寫」程式,更能「讀懂」、「分析」並「評價」程式的未來資訊科學家與工程師。

這次變革的核心,是五大新檢測題型的確立:

  1. 程式運行追蹤 (Code Tracing):精準模擬程式執行流程,判斷最終輸出或變數狀態。
  2. 程式填空 (Code Completion):根據上下文邏輯,填入最恰當的程式碼片段。
  3. 程式測試與除錯 (Code Testing and Debugging):找出程式碼中的邏輯錯誤、邊界條件問題或不符預期的行為。
  4. 程式效能分析 (Code Performance Analysis):評估程式碼的時間與空間複雜度,判斷其執行效率。
  5. 解析計算邏輯 (Computational Logic Analysis):從程式碼中抽象出其背後的演算法或解決的問題模型。

這些題型的出現,其背後動機是為了彌合學術程式設計與真實世界軟體開發之間的鴻溝。在業界,軟體工程師花費大量的時間閱讀、維護和除錯他人撰寫的程式碼。因此,能夠快速理解一段陌生程式碼的意圖(解析計算邏輯)、找出其中潛在的錯誤(程式測試與除錯)、並評估其是否有效率(程式效能分析),是極其關鍵的專業技能。過去的考試形式,如舊版經驗分享中提到的,可能可以透過記憶題型模式來應對。然而,新制中的「效能分析」與「邏輯分析」題型,直接挑戰了這種學習方法。它們要求考生從一個更高的維度去思考:「這段程式碼的『目的』是什麼?」以及「這是一個『好』的實作方式嗎?」。這是一種更高階的認知能力,更能預測學生在大學資訊工程學系及未來職涯的成功。因此,本講義的目標,是訓練考生像一位「程式碼審閱者(Code Reviewer)」一樣思考,而不僅僅是一台「人肉編譯器」。

1.2 C與Python的應試策略比較

APCS同時提供C和Python兩種語言選項,這並非偶然,而是測驗設計者用以評量考生對計算科學核心概念理解深度的巧妙工具。兩種語言在語法、資料結構和執行模型上的根本差異,為設計出能鑑別考生能力的題目提供了絕佳的素材。許多題目看似在兩種語言中邏輯相同,但由於底層機制的差異,會產生截然不同的結果。考生必須超越語法層面,深入理解這些差異,才能避免落入陷阱。

特性 C 實作/行為 Python 實作/行為 APCS 測驗意涵
資料型別 靜態型別 (Statically Typed)。變數在使用前必須宣告其型別,如 int x;。編譯時期進行型別檢查。 動態型別 (Dynamically Typed)。變數在賦值時才決定型別,如 x = 10。執行時期才進行型別檢查。 除錯/追蹤陷阱:一個Python函式可能因接收到預期外的型別而引發執行期錯誤(TypeError),這種情況在C語言的編譯階段就會被攔截。
陣列 vs. 串列 陣列 (Array) 大小固定、元素型別同質、佔用連續記憶體空間。 串列 (List) 大小可動態改變、元素型別可異質、基於物件參考儲存。 效能分析陷阱:在Python串列尾端新增元素(append)的攤銷時間複雜度為 O(1),但若要在C陣列「擴增」容量,則需手動重新配置記憶體並複製元素,成本極高。
指標 vs. 參考 提供明確的指標運算,可直接存取和操作記憶體位址,如 *ptrptr++ 變數名稱是對物件的參考(Object Reference),不提供直接的指標運算。 追蹤/除錯陷阱:C語言可透過指標在函式內直接修改傳入陣列的內容。Python中,若在函式內重新賦值變數(如 my_list = [9, 3, 2]),只會改變函式內的參考,不影響外部;但若修改物件內容(如 my_list.append(4)),則會影響外部。
控制流程 switch 語句具有「穿透 (fall-through)」特性,若 case 結尾沒有 break,會繼續執行下一個 case 使用 if/elif/else 鏈,結構清晰,沒有穿透問題。 除錯陷阱:一個沒有 break 的C switch 語句會執行多個區塊,這是非常經典的除錯題型,用來測試考生是否細心。
整數除法 兩個整數相除,結果會無條件捨去小數部分,例如 5 / 2 的結果是 2 5 / 2 的結果是浮點數 2.5。若要執行整數除法,需使用 // 運算子,即 5 // 2 結果為 2 運行追蹤陷阱:一個簡單的算術表達式,在兩種語言中會得出不同結果,是程式追蹤題中最常見的陷阱之一。
字串處理 字串實質上是以空字元 結尾的字元陣列 (char array),是可變的(mutable)。 字串 (str) 是不可變的(immutable)物件。任何修改字串的操作都會回傳一個新的字串物件。 除錯陷阱:試圖在原地修改字串內容的程式碼,對C的字元陣列是合法的,但對Python的字串物件則會引發錯誤或產生非預期的行為。

第二部分:掌握五大核心題型

要征服新制APCS程式識讀,考生必須針對五大題型,建立系統化的解題策略。這不僅是技巧,更是一種思維模式的訓練。

2.1 程式運行追蹤的應試策略

核心技能:一絲不苟地模擬程式的每一步執行,以機械般的精準度追蹤變數狀態的變化,最終確定程式的輸出或最終狀態。

戰略方法

  • 建立「變數狀態表」:這是應對程式追蹤最有效、最可靠的工具。在計算紙上,為程式中出現的每一個變數建立一個欄位。
  • 視覺化「函式呼叫堆疊 (Call Stack)」:當遇到遞迴函式時,單純的變數狀態表可能不足以應付。
  • 緊跟「控制流」:精確判讀 ifforwhile 的條件式至關重要。

2.2 程式填空的應試策略

核心技能:運用演繹推理,將程式碼的上下文視為線索,推斷出缺失部分的功能與邏輯。

戰略方法

  • 由上而下進行「目標分析」:快速掃描整個函式或程式碼區塊,問自己:「這段程式碼的『整體目標』是什麼?」
  • 由下而上進行「變數用途分析」:仔細觀察空白處「之後」的程式碼是如何使用相關變數的。
  • 代入選項進行「測試驗證」:將每個選項逐一代入空白處,然後用一個簡單的、自己設計的測試案例來追蹤程式的執行流程。

2.3 程式測試與除錯的應試策略

核心技能:從「測試者」而非「開發者」的視角審視程式碼,專注於尋找邏輯上的漏洞,而不僅僅是語法錯誤。

戰略方法

  • 搜獵「差一錯誤 (Off-by-One Errors)」:這是迴圈和陣列索引中最常見的邏輯錯誤。
  • 識別「邊界條件 (Edge Cases)」:一個健壯的程式必須能處理極端或非典型的輸入。
  • 揪出「語言特性陷阱」:主動尋找那些可能因語言特性而導致錯誤的程式碼片段。

2.4 程式效能分析的應試策略

核心技能:在不實際執行程式碼的情況下,快速估算其計算複雜度(時間複雜度為主,即 Big O notation),並判斷其效率等級。

戰略方法

  • 數「迴圈層數」:一個迭代 n 次的單層迴圈,其時間複雜度通常是 O(n)
  • 分析「遞迴呼叫」:線性遞迴複雜度通常為 O(n),樹狀遞迴可能是指數級的 O(2^n)
  • 牢記「資料結構操作成本」:熟記基礎資料結構的各種操作的時間複雜度。
複雜度名稱APCS 程式碼模式範例
O(1)常數 (Constant)x = a + b;
return array[i];
O(log n)對數 (Logarithmic)while (low <= high) { mid = low + (high-low)/2;... } (二分搜尋法)
O(n)線性 (Linear)for (int i = 0; i < n; i++) {... }
O(n log n)線性對數 (Log-linear)辨識出一個對高效排序演算法的呼叫,如 qsort()sort()
O(n^2)平方 (Quadratic)for (i=0..n-1) { for (j=0..n-1) {... } } (巢狀迴圈)
O(2^n)指數 (Exponential)int fib(int n) { return fib(n-1) + fib(n-2); } (未優化的樹狀遞迴)

2.5 解析計算邏輯的應試策略

核心技能:將具體的程式碼「抽象化」為演算法層級的理解。看透程式碼的表象,洞悉其正在解決的「問題」是什麼。

戰略方法

  • 辨識「知名演算法」的特徵:例如輾轉相除法質數判斷法基礎排序演算法等。
  • 使用「有意義的範例」進行追蹤:選擇一個小而有代表性的輸入來幫助理解。
  • 解讀「變數命名」的線索:命題者通常會使用具有提示性的變數名稱。

第三部分:深入探討關鍵知識領域

本章節將依據APCS官方公布的檢測範圍,系統性地深入探討各個知識領域。每個小節都會提供更深入的應考策略、答題技巧,並剖析常見的陷阱,幫助您將知識轉化為實戰能力。


3.1 基礎:資料型態、變數與表達式

這是程式設計的基石,也是最容易因疏忽而失分的地方。此類題目考驗的是細心與對語言特性的精準掌握。

應考策略與技巧

  • 步步為營,不跳步驟:在追蹤複雜表達式時,嚴格遵守「運算子優先順序」(先乘除後加減,先AND後OR),切勿心算。用紙筆寫下每一步的計算結果。
  • 注意型別轉換:特別是在C語言中,當整數(int)與浮點數(double)混合運算時,結果會被提升為浮點數。但在賦值時,浮點數若被存入整數變數,小數部分會被無條件捨去。

常見陷阱分析

  • 整數除法陷阱:這是C與Python最經典的差異考點。看到 5 / 2 就要立刻反應:在C中是 2,在Python中是 2.5
  • C的遞增/遞減運算子++x (前置) 會先將 x 加一,再使用 x 的值;x++ (後置) 會先使用 x 的值,再將 x 加一。這在單行複雜表達式中是極易混淆的陷阱。例如 int x=5; int y = ++x + x;int y = x++ + x; 結果會完全不同。
  • 短路求值:在邏輯表達式 A && B 中,若 A 為假,則 B 不會被執行。在 A || B 中,若 A 為真,則 B 也不會被執行。考題可能會在 B 的位置放一個會改變變數狀態的函式呼叫,例如 if (x != 0 && some_func(&y)),若 x 為0,則 some_func 不會被呼叫,y 的值也不會改變。

3.2 控制結構:循序、選擇與重複

控制結構是程式邏輯的骨架。理解其執行路徑是識讀所有程式碼的基礎。

應考策略與技巧

  • 畫流程圖/縮排分析:對於巢狀的 if-else 或迴圈,可以在紙上簡單畫出執行流程,或用筆標示出Python程式碼的縮排層級,以釐清哪個區塊屬於哪個控制結構。
  • 關注迴圈邊界:看到 forwhile 迴圈,第一時間就要確認其「起始條件」、「終止條件」和「迭代變化」。這是找出「差一錯誤」的關鍵。

常見陷阱分析

  • C的switch穿透:這是C語言獨有的高頻考點。一個沒有 breakcase 會繼續執行下一個 case 的程式碼,直到遇到 breakswitch 結束。追蹤題會故意遺漏 break,要求判斷變數的最終值。
  • Python的縮排陷阱:除錯題可能會給出一段邏輯上看似正確,但因縮排錯誤導致行為不符預期的Python程式碼。例如,某行程式碼本應在迴圈內,卻因縮排錯誤而只在迴圈結束後執行一次。
  • 空迴圈/無窮迴圈:注意迴圈的終止條件是否可能永遠無法滿足(無窮迴圈),或一開始就不滿足(迴圈一次都不執行)。

3.3 函式與模組化

函式題的核心在於測試對「作用域」和「參數傳遞」的理解。

應考策略與技巧

  • 區分「修改內容」與「重新賦值」:這是理解參數傳遞的關鍵。
    • 在函式內修改傳入的可變物件(如C的陣列、Python的串列)的內容(例如 arr[0]=100),會影響到函式外部的原始物件。
    • 在函式內將參數重新賦值給一個全新的物件(例如 arr = new_array),則只會改變函式內部的參考,不影響外部。
  • 變數查找順序:當函式內使用一個變數時,會先從函式的「區域作用域」找,找不到才往「全域作用域」找。

常見陷阱分析

  • 變數遮蔽 (Shadowing):函式內宣告了一個與全域變數同名的區域變數。在函式內對該變數的所有操作都只會影響這個區域變數,而不會碰到全域變數。
  • Python的可變預設參數:例如 def func(a, b=[]):。這個預設的空串列 [] 只會被建立一次。若函式內修改了 b,這個修改會保留到下一次呼叫,這是Python中一個非常隱晦且常見的陷阱。

3.4 遞迴的藝術

遞迴題看似複雜,但掌握其核心思維模式後便能迎刃而解。

應考策略與技巧

  • 信任遞迴:不要試圖在腦中完整展開每一步遞迴。先找到「基礎情況」(終止點),然後理解「遞迴步驟」(如何將問題變小)。只要這兩點邏輯正確,就可以相信函式能完成任務。
  • 畫呼叫樹:對於追蹤題,特別是 fib(n-1) + fib(n-2) 這類樹狀遞迴,畫出呼叫關係樹是唯一可靠的方法。在樹的節點旁標註回傳值,由下往上計算出最終結果。

常見陷阱分析

  • 基礎情況錯誤:除錯題的遞迴錯誤,90%都出在基礎情況。可能是條件判斷錯誤(例如 n==1 寫成 n<1),或是基礎情況的回傳值錯誤。
  • 堆疊溢位 (Stack Overflow):效能分析或除錯題可能會問,為什麼某個遞迴函式在輸入值很大時會出錯。原因通常是遞迴太深,超過了呼叫堆疊的極限。

3.5 陣列與串列

陣列與串列是資料的容器,考題圍繞著如何存取和操作這些資料。

應考策略與技巧

  • 索引值恆為 0長度-1:將這句話刻在腦海裡。看到任何 arr[i] 形式的存取,都要立刻檢查 i 的可能範圍是否會超出邊界。
  • 視覺化二維陣列:遇到二維陣列時,直接在紙上畫一個表格,將初始值填入。在追蹤迴圈時,用筆尖在表格上移動,模擬 matrix[i][j] 的存取過程。

常見陷阱分析

  • 索引越界:最常見的陷阱。通常發生在迴圈的最後一次迭代,例如 for (i=0; i<=n; i++) 存取 arr[i],當 i=n 時就會越界。
  • C與Python的初始化差異:C語言宣告 int arr[5]; 後,裡面的值是未定義的(隨機值)。而Python arr = [0] * 5 則會得到 [0, 0, 0, 0, 0]。這個差異可能成為除錯題的考點。

3.6 基礎資料結構

這類題目不考你會不會實作,而是考你懂不懂它們的「行為模式」。

應考策略與技巧

  • 辨識行為模式
    • 看到「後進先出」(LIFO) 的操作順序,就要聯想到堆疊(Stack)。例如,括號匹配、函式呼叫都符合堆疊的行為。
    • 看到「先進先出」(FIFO) 的操作順序,就要聯想到佇列(Queue)。例如,排隊系統、廣度優先搜尋(BFS)都符合佇列的行為。
  • 用紙筆模擬:拿一張紙,畫一個開口朝上的方框代表堆疊,或一個左右貫通的管道代表佇列。根據程式碼的 push/popenqueue/dequeue 操作,實際畫出元素的進出過程。

常見陷阱分析

  • 用串列模擬時的操作混淆:Python中,用 list 模擬堆疊很直觀 (appendpop)。但用 list 模擬佇列時,若使用 pop(0) 來取出頭部元素,其時間複雜度是 O(n),效率很差。效能分析題可能會考這個觀念。
  • Struct/Class的存取語法:C語言中,存取 struct 變數的成員用 . (例如 p.x),存取 struct 指標的成員用 -> (例如 ptr->x)。這兩種符號的混用是常見的語法錯誤。

3.7 基礎演算法

演算法題考驗的是模式識別能力。你需要能從程式碼的結構,反推出它背後的演算法思想。

應考策略與技巧

  • 記憶「程式碼簽章」
    • 二分搜尋:標誌是 while (low <= high) 迴圈,以及在迴圈內計算 mid 並移動 lowhigh 指標。前提是資料必須已排序。
    • 選擇排序:標誌是兩層巢狀迴圈,內層迴圈只做「尋找最小值索引」的動作,真正的「交換」發生在外層迴圈的結尾。
    • 氣泡/插入排序:標誌也是兩層巢狀迴圈,但「交換」操作可能在內層迴圈中就頻繁發生。

常見陷阱分析

  • 二分搜尋的前提:除錯題可能會給一個未排序的陣列,卻對它執行二分搜尋,導致結果錯誤。考生需要指出其根本錯誤在於未滿足演算法的前提。
  • 迴圈邊界與更新邏輯:二分搜尋的 high = mid - 1low = mid + 1 若寫錯,會導致無窮迴圈或找不到答案。排序演算法的迴圈邊界若有差一錯誤,可能導致最後一個元素未被排序。

第四部分:線上模擬測驗

共 20 題。請先選擇您要使用的測驗語言。