歡迎來到程式設計概念!
各位未來的程式設計師,大家好!這個章節是真正有趣的地方。我們將從理解電腦如何運作(硬體與資料)轉變為向電腦發出具體、循序漸進的指令——這正是程式設計的核心所在!
學習這些基本概念將使你能夠設計、編寫並理解任何演算法,為 Paper 2 的實作解題作好萬全準備。如果剛開始覺得程式碼很陌生,請別擔心;我們會將所有內容拆解成易於理解的部分。讓我們開始吧!
8.1 程式設計概念:建構基礎
8.1.1 變數與常數
你可以將變數與常數想像成電腦記憶體中具有名稱的儲存盒。
變數 (Variables)
變數是指記憶體中的一個位置,用於儲存一個在程式執行期間可以改變的值。
範例:玩家的「分數」(Score) 會隨著遊戲進行而改變。
常數 (Constants)
常數是指記憶體中的一個位置,用於儲存一個在程式執行期間不能改變的值。
範例:圓周率 (\(\pi\)) 的值或固定的「稅率」(TaxRate)。
在虛擬碼 (pseudocode) 中,我們使用關鍵字來宣告它們:
- 變數宣告:
DECLARE TotalScore : INTEGER - 常數宣告:
CONSTANT MaxAttempts ← 3 - 賦值: 我們使用賦值運算子
←將數值放入變數中。
TotalScore ← 100
8.1.2 基本資料型態 (Data Types)
當你宣告變數或常數時,必須告訴電腦它將儲存什麼類型的資料。這有助於電腦配置正確數量的記憶體空間並防止錯誤。
比喻:資料型態就像是給容器貼標籤——如果標籤寫著「水」,你就絕對不會嘗試把電存進去!
你需要掌握的基本資料型態包括:
- INTEGER (整數): 一個整數(正數、負數或零)。沒有小數點。
字面值:5, -100, 0 - REAL (實數/浮點數): 可以包含小數部分的數字。
字面值:3.14, -0.5, 4.0 - CHAR (字元): 單個字母、數字或符號。需用單引號包圍。
字面值:'A', '7', '@' - STRING (字串): 一系列字元(文字)。需用雙引號包圍。
字面值:"Hello World", "CS0478" - BOOLEAN (布林值): 只能是 TRUE(真)或 FALSE(假)的邏輯值。
字面值:TRUE, FALSE
如果你要儲存某人的年齡,請使用 INTEGER。如果要儲存姓名,使用 STRING。如果要在檢查燈是亮著(ON)還是熄滅(OFF),請使用 BOOLEAN。
8.1.3 輸入與輸出 (I/O)
程式需要與使用者互動。這是透過 I/O 指令來處理的。
- INPUT (輸入): 從使用者(通常是鍵盤)讀取資料並將其存入變數。
語法:INPUT <變數>
範例:INPUT UserName - OUTPUT (輸出): 將資料或訊息顯示給使用者(通常是螢幕)。
語法:OUTPUT <數值/變數>
範例:OUTPUT "Hello, ", UserName
8.1.4 (f) 運算子 (Operators)
運算子是用來執行計算或比較的特殊符號。
算術運算子 (Arithmetic Operators)
用於執行數學運算:
- + (加法)
- - (減法)
- * (乘法)
- / (除法,結果為 REAL)
- ^ (次方,例如 \(2^3\))
- DIV: 整數除法(返回商數,捨棄餘數)。
範例:DIV(10, 3) 返回 3 - MOD: 取餘數(返回整數除法後的餘數)。
範例:MOD(10, 3) 返回 1
記憶小技巧: MOD 是除完後的「餘數」或「剩餘部分」。DIV 是除法中「完整包含了幾次」。
關聯運算子 (Relational Operators)
用於比較兩個數值,並始終返回一個 BOOLEAN 結果(TRUE 或 FALSE)。
- = (等於)
- < (小於)
- <= (小於或等於)
- > (大於)
- >= (大於或等於)
- <> (不等於)
邏輯運算子 (Logical Operators)
用於結合多個布林條件。
- AND: 僅當所有條件皆為 TRUE 時,結果才為 TRUE。
- OR: 只要至少有一個條件為 TRUE,結果即為 TRUE。
- NOT: 反轉條件(TRUE 變為 FALSE,FALSE 變為 TRUE)。
範例:IF (Age > 18) AND (IsCitizen = TRUE) THEN...
8.1.4 控制結構:順序、選擇、迭代
(a) 順序 (Sequence)
順序是最簡單的控制結構。指令按照它們出現的順序,一個接一個地執行。這是程式的預設流程。
範例:
1. Total ← 0
2. Number1 ← 10
3. Total ← Total + Number1
(b) 選擇 (Selection)
選擇允許程式根據條件(布林測試)來決定執行哪個程式碼區塊。
IF 陳述式
用於一種或兩種可能的結果:
IF <條件> THEN
<陳述式>
ELSE
<陳述式>
ENDIF
CASE 陳述式
用於根據單一變數的值有多種可能的結果時。
INPUT Grade
CASE OF Grade
'A' : OUTPUT "優異"
'B' : OUTPUT "良好"
OTHERWISE OUTPUT "需改進"
ENDCASE
巢狀陳述式 (8.1.5)
巢狀陳述式 (Nested statement) 是指將一個選擇或迭代結構完整放置在另一個結構內部。這對於複雜邏輯至關重要。
考試中通常不需要編寫超過三層的巢狀結構。
巢狀 IF 範例:
IF Score > 50 THEN
IF Score > 90 THEN // 巢狀 IF
OUTPUT "頂尖成績!"
ELSE
OUTPUT "及格"
ENDIF
ELSE
OUTPUT "不及格"
ENDIF
(c) 迭代 (Iteration/Looping)
迭代意味著多次重複一段程式碼。主要有三種類型:
1. 計數循環 (FOR Loop)
當你準確知道循環需要運行多少次時使用。
- 它會自動初始化、檢查並遞增(或遞減)計數器變數。
FOR Counter ← 1 TO 10
OUTPUT "循環次數: ", Counter
NEXT Counter
2. 前置條件循環 (WHILE Loop)
在循環執行之前先檢查條件。如果條件初始即為 FALSE,則循環內部的程式碼將永遠不會執行(執行零次)。
WHILE <條件> DO
<陳述式>
ENDWHILE
3. 後置條件循環 (REPEAT UNTIL Loop)
在循環執行之後才檢查條件。這保證了循環內部的程式碼至少會執行一次。循環會持續進行,直到條件變為 TRUE 為止。
REPEAT
<陳述式>
UNTIL <條件>
常見錯誤提醒: WHILE 循環在條件為 TRUE 時持續運行。REPEAT UNTIL 循環則是「直到」條件變為 TRUE 時停止(也就是說,只要條件還是 FALSE,它就會繼續運行)。
8.1.4 (d, e) 累加、計數與字串處理
(d) 累加與計數 (Totalling and Counting)
這是循環內常用的兩種模式:
- 計數 (Counting): 追蹤某個事件發生了多少次。通常將計數變數初始化為 0,並在每次事件發生時加 1。
範例:NumberOfStudents ← NumberOfStudents + 1 - 累加 (Totalling/Accumulation): 維持數值的累積總和。通常將總數變數初始化為 0,並在每次出現新數值時將其加上。
範例:TotalSales ← TotalSales + CurrentSaleValue
(e) 字串處理 (String Handling)
這是用於操作文字(STRING 資料)的標準函式。
- LENGTH(<識別碼>): 返回字串中的字元數量。
範例:LENGTH("Cat") 返回 3。 - LCASE(<識別碼>): 將字串或字元轉換為小寫。
- UCASE(<識別碼>): 將字串或字元轉換為大寫。
- SUBSTRING(<識別碼>, <開始位置>, <長度>): 返回字串的一部分。你需要指定開始位置以及要包含的字元數量。
注意:虛擬碼通常使用 1 作為第一個字元的起始位置,但課程大綱確認在不同程式系統中可能使用 0 或 1。請遵循你題目中使用的慣例,若未指定則使用 1。
範例:SUBSTRING("Program", 3, 4) 返回 "ogra"。
8.1.6 程序、函式與變數範圍
隨著程式越來越大,我們需要將其拆解成較小、可重複使用的程式區塊。
程序 (Procedures) 與函式 (Functions)
程序和函式都是可重複使用的副程式,但它們有一個關鍵區別:
- 程序 (Procedure): 一個執行任務但不會返回數值的已命名程式區塊。它是透過 CALL 關鍵字來呼叫的。
範例:CALL DisplayMenu() - 函式 (Function): 一個執行任務並必須返回單一數值到呼叫點的已命名程式區塊。它通常作為運算式的一部分使用。
範例:Area ← CalculateArea(5, 10)
參數 (Parameters)
參數是傳遞給程序或函式的數值,以便副程式可以使用它們。它們就像是副程式的輸入。
// 定義一個帶有一個參數的程序
PROCEDURE Line(Size : INTEGER)
// ... 使用 Size 的陳述式 ...
ENDPROCEDURE
// 呼叫程序
CALL Line(60)
你可能需要處理最多帶有三個參數的程序與函式。
區域與全域變數 (Local and Global Variables)
範圍 (Scope) 是指程式中變數可以被存取的區域。
- 全域變數 (Global Variable): 在程式的最開始(主程式體)宣告。它可以在程式的任何地方被存取與修改,包含在程序與函式內部。
- 區域變數 (Local Variable): 在特定的程序或函式內部宣告。它只能在該副程式內部使用。一旦副程式結束,區域變數就會被銷毀。
就像是一張只有你自己能讀的祕密臨時便條紙。
為什麼要用區域變數? 它們可以防止意外干擾。如果兩個不同的程序都使用了名為 i 的變數,如果 i 分別在兩個程序內宣告為區域變數,它們就不會衝突。
8.1.7 函式庫常式與 8.1.8 可維護的程式
8.1.7 函式庫常式 (Library Routines)
這些是程式環境中內建的預寫函式,可以節省你的時間。除了字串函式、MOD 和 DIV 之外,你需要知道的主要函式還有:
- ROUND(<識別碼>, <位數>): 將一個 REAL 數值四捨五入到指定的小數位數。
範例:ROUND(3.14159, 2) 返回 3.14 - RANDOM(): 返回一個介於 0 到 1 之間的隨機 REAL 數值(包含 0 和 1)。
要生成 1 到 10 之間的隨機整數:Value ← ROUND (RANDOM() * 10, 0)
8.1.8 建立可維護的程式
所謂可維護的程式,是指讓其他人(或未來的自己)能夠輕鬆理解、偵錯與更新的程式。
關鍵特性包括:
- 有意義的識別碼: 為變數、常數、程序和函式使用描述性的名稱(例如使用 MaximumScore 而不是 MS)。
- 註解: 使用 // 來加入註解,解釋程式碼的功能,特別是針對複雜的部分。
- 使用程序與函式: 將程式碼拆解成邏輯上的子部分,使主程式流程更簡潔。
8.2 陣列:儲存資料列表
8.2.1 陣列的宣告與使用
陣列 (Array) 是一種資料結構,用於儲存固定數量且類型相同的項目,並透過索引(一個數字)來存取。
比喻:陣列就像是一排編號的郵箱,每個郵箱按順序排列。
1. 一維 (1D) 陣列
一維陣列是一個簡單的清單或向量。
宣告:
DECLARE StudentNames : ARRAY[1:30] OF STRING // 30 個元素,索引由 1 到 30
使用: 元素使用方括號 [ ] 來存取。
StudentNames[1] ← "Ali" // 將 "Ali" 放入第一個位置 OUTPUT StudentNames[5] // 輸出位置 5 的數值
2. 二維 (2D) 陣列
二維陣列是一個清單的清單,通常可視為表格或網格(列與欄)。
宣告:
DECLARE Board : ARRAY[1:3, 1:3] OF CHAR // 一個 3x3 的網格(類似圈圈叉叉遊戲)
使用: 第一個索引通常是列 (Row),第二個是欄 (Column)。
Board[2, 3] ← 'X' // 將 'X' 放入第 2 列第 3 欄
8.2.2 & 8.2.3 陣列與迭代的使用
由於陣列索引是連續的數字,陣列幾乎總是與迭代(循環)一起處理,特別是 FOR 循環。
這讓你能夠有系統地讀取或寫入陣列中的每個元素。
// 將數值寫入陣列(從使用者輸入讀取)
FOR Index ← 1 TO 30
INPUT StudentNames[Index]
NEXT Index
// 從二維陣列中讀取數值(需要巢狀迭代)
FOR Row ← 1 TO 3
FOR Column ← 1 TO 3
OUTPUT Board[Row, Column]
NEXT Column
NEXT Row
8.3 檔案處理:永久儲存
8.3.1 檔案的目的
當程式執行時,變數儲存在臨時的 RAM(主記憶體)中。當程式關閉後,這些資料就會消失。
將資料存入檔案的目的是為了將資料永久保留(在二次儲存裝置如硬碟中),以便程式下次執行時能夠提取。
8.3.2 檔案操作
在虛擬碼中處理檔案時,必須遵循特定步驟:
步驟 1: 開啟檔案 (OPEN)
- 你必須指定模式:FOR READ(讀取現有資料)或 FOR WRITE(建立新檔案或覆蓋現有檔案)。
OPENFILE "Scores.txt" FOR READ
步驟 2: 讀取 (READ) 或寫入 (WRITE) 資料
- READFILE: 從檔案中讀取單一資料項目或一行文字,並存入變數。
READFILE "Scores.txt", PlayerName // 讀取一個項目/行到 PlayerName
WRITEFILE "Scores.txt", NewScore
步驟 3: 關閉檔案 (CLOSE)
- 當完成操作後,必須 CLOSE 檔案以確保所有資料正確儲存,並且檔案不會再被其他程式鎖定。
CLOSEFILE "Scores.txt"