欢迎来到编程概念的世界!
你好,未来的程序员!这一章节是真正充满乐趣的开始。我们将从理解计算机如何工作(硬件和数据),转向为计算机提供具体的、分步骤的指令——这就是编程的全部意义所在!
掌握这些基础概念将使你能够设计、编写并理解任何算法,为你应对 Paper 2 中实际的问题解决题型打下坚实的基础。如果代码一开始看起来有些陌生,不必担心;我们会将一切拆解成易于理解的部分。让我们开始吧!
8.1 编程概念:构建基石
8.1.1 变量与常量
可以将变量和常量想象成计算机内存中带有标签的存储盒。
变量 (Variables)
变量是一个内存位置,用于存储在程序执行期间可以改变的值。
示例:玩家的得分(Score)会随着游戏进行而改变。
常量 (Constants)
常量是一个内存位置,用于存储在程序执行期间不能改变的值。
示例:圆周率 (\(\pi\)) 的值或固定的税率(TaxRate)。
在伪代码中,我们使用关键字来声明它们:
- 变量声明:
DECLARE TotalScore : INTEGER - 常量声明:
CONSTANT MaxAttempts ← 3 - 赋值: 我们使用赋值运算符
←将值存入变量。
TotalScore ← 100
8.1.2 基本数据类型
当你声明一个变量或常量时,必须告知计算机它将存储哪种数据类型。这有助于计算机分配正确的内存空间并防止错误。
类比:数据类型就像是容器上的标签——如果标签写着“水”,你就不会试图往里装电了!
你需要掌握的基本数据类型包括:
- 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。如果你要检查灯是“开”还是“关”,使用 BOOLEAN。
8.1.3 输入与输出 (I/O)
程序需要与用户交互。这通过 I/O 命令来处理。
- INPUT(输入): 从用户(通常是键盘)读取数据并将其存储在变量中。
语法:INPUT <变量>
示例:INPUT UserName - OUTPUT(输出): 向用户显示数据或信息(通常是屏幕)。
语法:OUTPUT <值>
示例:OUTPUT "Hello, ", UserName
8.1.4 (f) 运算符
运算符是用于执行计算或比较的特殊符号。
算术运算符(计算)
用于执行数学运算:
- + (加法)
- - (减法)
- * (乘法)
- / (除法,结果为 REAL 实数)
- ^ (乘方,例如 \(2^3\))
- DIV: 整除(返回商,舍弃余数)。
示例:DIV(10, 3) 返回 3 - MOD: 取模(返回整除后的余数)。
示例:MOD(10, 3) 返回 1
记忆窍门: MOD 是除法后的“剩菜”(余数)。DIV 是除法能完全进入多少次。
关系运算符(比较)
用于比较两个值,始终返回一个 BOOLEAN 结果(TRUE 或 FALSE)。
- = (等于)
- < (小于)
- <= (小于等于)
- > (大于)
- >= (大于等于)
- <> (不等于)
逻辑运算符(组合条件)
用于组合多个布尔条件。
- 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 "Excellent"
'B' : OUTPUT "Good"
OTHERWISE OUTPUT "Needs Improvement"
ENDCASE
嵌套语句 (8.1.5)
嵌套语句是指一个选择或迭代结构完全包含在另一个结构内部。这对于处理复杂逻辑至关重要。
考试中你不需要编写超过三层嵌套的语句。
嵌套 IF 示例:
IF Score > 50 THEN
IF Score > 90 THEN // 嵌套 IF
OUTPUT "Top result!"
ELSE
OUTPUT "Pass"
ENDIF
ELSE
OUTPUT "Fail"
ENDIF
(c) 迭代结构 (Iteration/Looping)
迭代意味着重复执行一段代码多次。主要有三种类型:
1. 计数循环 (FOR)
当你明确知道循环需要运行多少次时使用。
- 它会自动初始化、检查并增加(或减少)计数器变量。
FOR Counter ← 1 TO 10
OUTPUT "Loop number: ", Counter
NEXT Counter
2. 前置条件循环 (WHILE)
条件在循环运行之前进行测试。如果条件初始为 FALSE,循环内部的代码将永远不会执行(执行零次)。
WHILE <条件> DO
<语句>
ENDWHILE
3. 后置条件循环 (REPEAT UNTIL)
条件在循环运行之后进行测试。这保证了循环内部的代码至少会执行一次。循环会一直重复,直到条件变为 TRUE 为止。
REPEAT
<语句>
UNTIL <条件>
常见错误提醒: WHILE 循环只要条件为 TRUE 就会运行。REPEAT UNTIL 循环会一直运行直到条件变为 TRUE(即:只要条件为 FALSE 就会持续运行)。
8.1.4 (d, e) 求和、计数与字符串处理
(d) 求和与计数
这是循环中常见的两种模式:
- 计数: 跟踪某事发生的次数。通常将计数变量初始化为 0,每当事件发生时加 1。
示例:NumberOfStudents ← NumberOfStudents + 1 - 求和(累加): 保持数值的运行总和。通常将总数变量初始化为 0,每当出现新值时将其加到变量中。
示例:TotalSales ← TotalSales + CurrentSaleValue
(e) 字符串处理
这些是用于处理文本(STRING 数据)的标准函数。
- LENGTH(<标识符>): 返回字符串中的字符数。
示例:LENGTH("Cat") 返回 3。 - LCASE(<标识符>): 将字符串或字符转换为小写。
- UCASE(<标识符>): 将字符串或字符转换为大写。
- SUBSTRING(<标识符>, <开始位置>, <长度>): 返回字符串的一部分。你需要指定起始位置和要包含的字符数。
注意:伪代码通常使用 1 作为第一个字符的起始位置,但大纲确认在编程系统中可能使用 0 或 1。请遵循题目中的惯例,如果未指定则使用 1。
示例:SUBSTRING("Program", 3, 4) 返回 "ogra"。
8.1.6 过程、函数与变量作用域
随着程序规模扩大,我们会将它们拆分成更小的、可复用的代码块。
过程与函数
过程(Procedure)和函数(Function)都是可复用的子程序,但它们有一个关键区别:
- 过程: 一个命名代码块,执行一项任务但不返回值。使用 CALL 关键字调用。
示例:CALL DisplayMenu() - 函数: 一个命名代码块,执行一项任务并必须返回一个值到调用它的地方。它作为表达式的一部分使用。
示例:Area ← CalculateArea(5, 10)
参数 (Parameters)
参数是传递给过程或函数的值,以便子程序使用。它们充当子程序的输入。
// 定义一个带有一个参数的过程
PROCEDURE Line(Size : INTEGER)
// ... 使用 Size 的语句 ...
ENDPROCEDURE
// 调用该过程
CALL Line(60)
你可能会接触到最多三个参数的过程和函数。
局部变量与全局变量
作用域 (Scope) 指的是程序中可以访问变量的区域。
- 全局变量: 在程序最开始(主程序体中)声明。它可以在程序的任何地方访问和修改,包括在过程和函数内部。
- 局部变量: 在特定的过程或函数内部声明。它只能在该子程序内部使用。一旦子程序执行完毕,局部变量就会被销毁。
就像是一张只有你自己能读的秘密草稿纸。
为什么要使用局部变量? 它们可以防止意外冲突。如果两个不同的过程都使用名为 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 之间(包含 0,不含 1)的随机 REAL 数。
若要生成 1 到 10 之间的随机整数:Value ← ROUND (RANDOM() * 10, 0)
8.1.8 创建可维护的程序
可维护的程序是指他人(或以后你自己)容易理解、调试和更新的程序。
关键特性包括:
- 有意义的标识符: 为变量、常量、过程和函数使用描述性名称(例如,用 MaximumScore 而不是 MS)。
- 注释: 使用 // 添加备注来解释代码的作用,尤其是复杂的部分。
- 过程和函数的使用: 将代码拆分为逻辑子部分使主程序流更清晰。
8.2 数组:存储数据列表
8.2.1 数组的声明与使用
数组是一种数据结构,用于存储固定数量的相同数据类型的项,并通过索引(数字)进行访问。
类比:数组就像是一排完全相同的邮箱,每个邮箱都有顺序编号。
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' // 在第 2 行,第 3 列放入 'X'
8.2.2 & 8.2.3 数组与迭代结合
由于数组索引是连续的数字,数组几乎总是配合迭代(循环)来处理,特别是 FOR 循环。
这使你能够系统地读取或写入数组的每个元素。
// 将值写入数组(读取用户输入)
FOR Index ← 1 TO 30
INPUT StudentNames[Index]
NEXT Index
// 从 2D 数组读取值(需要嵌套迭代)
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 文件操作
在伪代码中操作文件,必须遵循特定步骤:
第一步:打开文件 (OPEN)
- 必须指定模式:FOR READ(读取现有数据)或 FOR WRITE(创建新文件或覆盖现有文件)。
OPENFILE "Scores.txt" FOR READ
第二步:读取或写入数据 (READ / WRITE)
- READFILE: 从文件中读取单个数据项或一行文本,并将其存入变量。
READFILE "Scores.txt", PlayerName // 读取一个项/行到 PlayerName 中
WRITEFILE "Scores.txt", NewScore
第三步:关闭文件 (CLOSE)
- 完成后,必须 CLOSE 文件以确保所有数据正确保存,并且文件不再被其他程序占用。
CLOSEFILE "Scores.txt"