AS Level 電腦科學 (9618) 溫習筆記:程式編寫 (第 11 及 12 章)

你好,未來的程式設計師!歡迎來到電腦科學的核心:**程式編寫 (Programming)**。本章將帶領大家從算法 (第 9 章) 和數據結構 (第 10 章) 的理論世界,邁向將這些構思轉化為實際解決方案的實踐技巧。
我們將學習編寫代碼的基本構件、如何有效地組織程式,以及規劃、測試和維護穩健軟件所需的關鍵步驟。
如果覺得寫代碼很困難,請不用擔心,我們會將所有內容拆解,一步步教學。掌握這些技能對於 Paper 2 至關重要,屆時你將需要運用虛擬代碼 (Pseudocode) 來解決問題!


11. 程式編寫

11.1 程式編寫基礎

本節涵蓋了我們用來向電腦發送指令的核心規則與工具。

變數、常數與數據類型

把電腦記憶體想像成一個巨大的儲物櫃。

  • 變數 (Variable): 一個已命名的儲存位置,其值在程式執行期間**可以改變**。
  • 常數 (Constant): 一個已命名的儲存位置,其值是**固定**的,在執行期間不能更改。使用常數能讓代碼更清晰、更安全 (防止意外更改關鍵數值)。

宣告變數或常數時,必須指定其數據類型 (Data Type)。這告訴電腦預期接收什麼類型的資訊,以及需要分配多少空間。

AS Level 常見的數據類型 (及其虛擬代碼表示):

  • INTEGER: 整數 (例如:5, -100)。常用於計數器或分數。
  • REAL: 包含小數部分的數值 (例如:3.14, 0.5)。
  • CHAR: 單一字母、數字或符號 (例如:'A', '7', '$')。
  • STRING: 字元序列 (例如:"Hello World")。
  • BOOLEAN: 僅包含兩個值:TRUEFALSE非常適合用於標記 (flags) 或條件判斷。

宣告與賦值 (Declaration and Assignment):

我們在程式或模組的開頭宣告常數和變數。

  • 宣告 (變數): DECLARE StudentName : STRING
  • 宣告 (常數): CONSTANT PI = 3.14
  • 賦值 (給予數值): StudentName ← "Alex"

常見誤區: 切勿混淆賦值 (`←`) 與比較 (`=`)。在虛擬代碼中,`←` 是將數值「放入」變數中。

輸入、輸出與運算式

程式必須與用戶互動 (輸入) 並顯示結果 (輸出)。

  • 輸入: INPUT Age (從鍵盤讀取數據並存入變數 Age)。
  • 輸出: OUTPUT "Your age is ", Age (在控制台顯示文字及 Age 的值)。

運算式 (Expression) 結合了數值、變數與運算子 (算術或邏輯) 來產生一個結果。

  • 算術運算子: +, -, *, /, DIV (整數除法), MOD (取餘數)。
  • 邏輯運算子: AND, OR, NOT

你知道嗎? 使用內建函數 (如計算平方根 SQRT(X)) 和程式庫常式 (預先編寫的代碼塊) 可為程式設計師節省大量時間,並使代碼更可靠,因為這些函數已經過測試並證明正確。

要點 11.1: 使用前務必先宣告變數和常數,選擇合適的數據類型,並釐清輸入、處理 (運算式) 與輸出的分別。

11.2 結構 (控制結構)

任何算法的三個基本構件是順序 (Sequence)、選擇 (Selection) 和迭代 (Iteration)。我們使用控制結構來實現選擇和迭代。

選擇 (決策制定)

選擇結構允許程式根據條件 (布林運算式) 選擇執行路徑。

1. IF...THEN...ELSE (及嵌套 IF)

  • 用於在兩個或多個結果之間進行簡單選擇時。
  • 虛擬代碼範例:
    IF Score > 75 THEN
    OUTPUT "Distinction"
    ELSE
    OUTPUT "Pass"
    ENDIF

2. CASE 結構

  • 當根據單一變數的值有多個互斥的結果時使用。這比使用多層嵌套的 IF 語句更整潔。
  • 虛擬代碼範例:
    CASE DayOfWeek OF
    1: OUTPUT "Monday"
    5: OUTPUT "Friday"
    OTHERWISE OUTPUT "Weekend or other day"
    ENDCASE
迭代 (循環/重複)

迭代允許代碼塊重複執行。選擇正確的循環結構對於編寫高效代碼非常重要。

1. 計數控制循環 (FOR 循環)

  • 當你知道循環需要執行確切次數時使用。
  • 虛擬代碼範例: FOR Counter ← 1 TO 10

2. 前置條件循環 (WHILE 循環)

  • 在執行循環主體之前先檢查條件。循環可能會執行零次或多次。
  • 當終止條件取決於外部因素 (如用戶輸入或檔案狀態) 時使用。
  • 虛擬代碼範例:
    WHILE InputValue <> -1 DO
    // 循環主體
    ENDWHILE

3. 後置條件循環 (REPEAT UNTIL 循環)

  • 在執行循環主體之後檢查條件。該循環保證至少執行一次。
  • 常考用於確保有效輸入 (不斷提示用戶直至輸入可接受的數據)。
  • 虛擬代碼範例:
    REPEAT
    INPUT Password
    UNTIL Password = "secret"

如何選擇循環:

如果問題需要重複特定次數 (例如輸入 5 個分數),使用 FOR 循環。如果必須確保至少執行一次 (例如驗證輸入),使用 REPEAT UNTIL。如果循環可能一次都不需要執行 (例如處理空檔案中的記錄),則使用 WHILE

要點 11.2: 選擇結構根據決策控制流程 (IF/CASE)。迭代結構控制重複 (FOR, WHILE, REPEAT)。請務必了解何時使用哪種循環!

11.3 結構化程式編寫 (程序與函數)

結構化程式編寫涉及將大型程式分解為較小、獨立的模組。這使得代碼編寫、除錯及維護更容易。這些模組稱為**子程式 (Subroutines)**:程序 (Procedures) 和函數 (Functions)。

程序 (做某事的子程式)

程序是一個已命名的代碼塊,用於執行特定任務,但不一定向主程式回傳值

  • 適合用途: 涉及輸入/輸出或直接修改變數的任務 (例如將數據儲存到檔案,或打印選單)。
  • 語法: 使用 PROCEDURE 定義,並透過名稱直接呼叫。
函數 (計算並回傳值的子程式)

函數是一個已命名的代碼塊,用於計算數值並將該值回傳給呼叫它的運算式。

  • 適合用途: 數學計算、字串處理或檢查條件 (例如計算稅款,或查找名稱長度)。
  • 語法: 使用 FUNCTION 定義,並在運算式中使用,回傳值會取代函數呼叫的位置。
參數與引數

為了讓程序和函數更靈活,我們透過參數 (Parameters) 傳遞數據。

  • 參數 (Parameter): 定義在程序/函數標頭中,用於接收數據的識別符。
  • 引數 (Argument): 呼叫程序/函數時實際傳遞的數值或變數。

參數傳遞方式分為兩種:

1. 傳值 (Pass By Value)

  • 傳遞的是引數的「副本」。
  • 在子程式內部對參數所作的任何更改,都不會影響主程式中的原始變數 (引數)。
  • 比喻: 給某人一份你的筆記影印本。他們可以在影印本上亂畫,但你的原始筆記保持原樣。

2. 傳址 (Pass By Reference)

  • 傳遞的是引數的記憶體位址 (參照)。
  • 在子程式內部對參數所作的任何更改,都會影響主程式中的原始變數。
  • 比喻: 給某人你儲物櫃的真實鑰匙。他們可以永久更改裡面的內容。
要點 11.3: 程序執行任務;函數計算並回傳值。傳值保護原始數據;傳址允許子程式修改原始數據。

12. 軟件開發

編寫代碼 (第 11 章) 只是工作的一部分。第 12 章探討建構大型、可靠軟件系統所需的結構與紀律。

12.1 程式開發生命週期 (PLC)

程式開發生命週期 (Program Development Life Cycle, PLC) 是一套結構化的框架,描述了開發、維護及最終棄用軟件系統所需的步驟。其目的是確保質量、管理複雜性並滿足用戶需求。

PLC 階段
  1. 分析 (Analysis): 定義問題並識別用戶需求。(系統需要做什麼?)
  2. 設計 (Design): 規劃解決方案結構、算法及介面。(系統將如何實現?)
  3. 編碼 (Coding): 編寫程式代碼。
  4. 測試 (Testing): 檢查程式錯誤並確保其滿足要求。
  5. 維護 (Maintenance): 在部署後修復程式錯誤並進行更新。
開發生命週期模型

不同類型的程式需要不同的處理方法。

1. 瀑布模型 (Waterfall Model)

  • 原則: 每個階段必須在下一個階段開始前完成,嚴格向下流動。
  • 優點: 簡單、結構高度化,易於管理小型且目標明確的項目。
  • 缺點: 非常缺乏彈性;如果後期需求變更,回溯成本極高且困難。

2. 迭代模型 (Iterative Model)

  • 原則: 項目在小型、重複的循環 (迭代) 中開發。早期建立原型並隨時間精煉。
  • 優點: 允許早期用戶反饋,並能輕鬆適應變更的需求。
  • 缺點: 若管理不當,可能導致「範圍蔓延」(項目無止境地擴大)。

3. 快速應用程式開發 (RAD)

  • 原則: 透過持續的用戶參與快速建立原型,減少規劃時間。
  • 優點: 對於用戶介面至關重要且需求稍具彈性的項目,開發速度非常快。
  • 缺點: 不適用於極其複雜、大型的系統,或需要嚴格保安/安全性的情況 (如航空控制軟件)。
要點 12.1: PLC 指導軟件創作。瀑布模型刻板;迭代模型與 RAD 則具彈性,包含多次設計、編碼與測試循環。

12.2 程式設計

設計階段使用工具在編寫任何一行代碼前規劃程式結構。

結構圖 (Structure Charts)

結構圖是一種層次化圖表,用於**由上而下設計 (top-down design)**,將問題分解為更小、易於管理的子任務 (模組、程序或函數)。

  • 目的: 顯示程式的整體結構以及各模組間的關係。
  • 關鍵特徵: 明確顯示模組間傳遞的**參數/數據** (數據箭頭用圓形表示,控制旗標/狀態則用菱形表示)。
狀態轉移圖 (State-Transition Diagrams)

狀態轉移圖記錄了在不同狀態下運行的算法。

  • 目的: 用於建模當前動作取決於過去輸入歷程的系統 (例如交通燈、自動售賣機、簡單登入系統)。
  • 結構: 圓形表示**狀態 (States)**,箭頭表示**轉移 (Transitions)** (觸發狀態改變的動作或輸入)。
要點 12.2: 結構圖定義了模組間的層次與數據流。狀態轉移圖則對行為隨狀態改變的系統進行建模。

12.3 程式測試與維護

無法正確運作的程式是毫無用處的。本節探討如何發現、預防及修復錯誤。

錯誤類型
  1. 語法錯誤 (Syntax Error): 違反程式語言的語法規則。翻譯器 (編譯器/直譯器) 會捕捉到這些錯誤。
  2. 邏輯錯誤 (Logic Error): 程式成功執行,但產生錯誤的輸出,因為算法邏輯不正確。翻譯器無法捕捉這些錯誤。
  3. 執行時期錯誤 (Run-time Error): 在程式執行時發生,導致程式崩潰或異常停止。(例如:除以零,或嘗試存取不存在的陣列索引)。
測試策略與數據

測試數據的選擇:

  • 正常數據 (Normal Data): 預期輸入的數據 (在可接受範圍內)。
  • 極限/邊界數據 (Extreme/Boundary Data): 可接受範圍臨界點的數據。這是最容易隱藏錯誤的地方!
  • 異常數據 (Abnormal Data): 意圖讓程式崩潰的無效數據 (例如格式錯誤、超出範圍)。
測試方法
  • 乾跑 (Dry Run): 使用追蹤表手動逐行執行代碼 (通常由開發者在紙上完成)。
  • 走查 (Walkthrough): 開發團隊由作者帶領,手動逐行檢查代碼。
  • 白盒測試 (White-Box Testing): 基於了解程式內部結構與路徑進行測試。確保每一行代碼至少執行一次。
  • 黑盒測試 (Black-Box Testing): 僅基於規格說明與預期輸出進行測試,不考慮內部代碼結構。
  • 整合測試 (Integration Testing): 測試各模組「共同」運作時是否正確。
  • Alpha 測試: 發布前由內部人員測試。
  • Beta 測試: 發布前由真實用戶在現實環境中測試。
  • 驗收測試 (Acceptance Testing): 客戶或終端用戶確認系統滿足所有合約需求的正式測試。
  • 虛設模組 (Stub): 測試期間使用的臨時佔位模組,用以模擬尚未編寫的模組功能。
程式維護
  • 更正性維護 (Corrective): 修復使用後發現的錯誤與程式缺陷。
  • 適應性維護 (Adaptive): 修改系統以適應環境變化 (如作業系統升級)。
  • 完善性維護 (Perfective): 提升性能、效率或可維護性 (如優化慢速代碼)。
要點 12.3: 測試必須嚴謹,包括正常、極限及異常數據。邏輯錯誤最難發現。維護分為更正性、適應性及完善性三類。