CAPL 编程系列教程 - 第五期:复合数据类型之数组 (Array)

 CAPL 编程系列教程的第五期内容,主要讲解 CAPL 中的一种重要的复合数据类型:数组 (Array)。以下是根据文件内容整理的系统性结构:

CAPL 编程系列教程 - 第五期:复合数据类型之数组 (Array)

一、 课程回顾与本期目标

  • 回顾: 前面几期学习了 CAPL 的简单数据类型(整数、浮点数、字符)
  • 复合数据类型: 由简单数据类型组合而成的数据类型
  • 本期目标: 学习 CAPL 中的数组,理解其定义、初始化、访问和特性

二、 数组 (Array) 的基本概念

  • 定义: 数组是一组具有相同数据类型的数据的有序集合
  • 用途: 用于存储和处理多个同类型的数据,例如一个班级的成绩、一组传感器的值等
  • 内存特点: 数组在内存中占据一段连续的空间,这使得访问效率较高
  • 元素 (Element): 数组中的每一个数据项称为元素
  • 下标/索引 (Index/Subscript):
    • 数组中的每个元素都有一个唯一的编号,称为下标或索引,用于访问该元素
    • 重要: CAPL 数组的下标从 0 开始编号 。例如,一个包含 5 个元素的数组,其下标范围是 0, 1, 2, 3, 4
  • 长度 (Length): 数组中元素的总个数

三、 数组的声明与初始化

  1. 基本语法: DataType ArrayName[Length] = {value1, value2, ..., valueN};
    • DataType: 数组中所有元素的数据类型(如 int, float, char, byte 等)
    • ArrayName: 自定义的数组名称(变量名)
    • [Length]: 必须在中括号内指定数组的长度(元素的个数)
    • = {value1, ...}: (可选) 初始化列表,用花括号 {} 括起来,元素之间用逗号 , 分隔,为数组元素赋初始值
    • 示例: int scores[5] = {97, 83, 96, 99, 85}; 声明了一个包含 5 个整数的数组 scores 并赋初值
  2. 部分初始化:
    • 如果在初始化列表中提供的值少于数组声明的长度,则未被赋值的元素默认初始化为 0(或对应类型的零值,如浮点数 0.0,字符 \0
    • 示例: byte ages[3] = {19, 22}; 声明长度为 3,但只提供了 2 个初始值。ages[0] 为 19,ages[1] 为 22,ages[2] 默认为 0
  3. 禁止超长初始化: 初始化列表中的元素个数绝对不能超过数组声明的长度,否则编译时会报错
  4. 不初始化:
    • 可以只声明数组类型、名称和长度,而不进行初始化。此时,数组中所有元素的初始值默认为 0
    • 示例: float heights[4]; 声明了一个包含 4 个浮点数的数组,所有元素的初始值都是 0.0
  5. 声明位置: 与普通变量一样,数组的声明也必须放在其所在代码块的最前面

四、 访问和修改数组元素

  1. 访问语法: ArrayName[Index]
    • 使用数组名加上中括号 [] 和元素的下标 (Index) 来访问(读取或写入)特定元素的值
    • 示例 (读取): write("第四个元素为 %d", scores[3]); 访问 scores 数组中下标为 3 的元素 (即第 4 个元素 99) 并输出
    • 示例 (修改/写入): scores[0] = scores[0] - 2; 读取 scores[0] 的值 (97),减 2 后得到 95,再将 95 赋值给 scores[0]
  2. 下标越界:
    • 访问数组时使用的下标必须在有效范围内(0 到 Length-1)
    • 使用小于 0 或大于等于 Length 的下标会导致数组越界 (Array index out of bounds),这是严重的编程错误,CAPL 编译器会直接报错
    • 示例 (错误): scores[5] 访问一个长度为 5 的数组的第 6 个元素(下标为 5),这是非法的
  3. 注意: 声明数组时中括号内的数字代表长度,而访问数组时中括号内的数字代表下标

五、 字符数组与字符串

  1. 字符数组 (Character Array):
    • 数组元素类型为 char 的数组,可以存储一系列字符
    • 示例: char letters[3] = {'A', 'B', 'C'}; 声明一个包含 3 个字符的数组
    • 访问方式与其他类型数组相同:letters[0] 为 'A',letters[1] 为 'B' 等
  2. 字符串 (String) 的本质:
    • CAPL (以及 C 语言) 没有内置的 string 类型。字符串是通过字符数组来实现的
    • 一个表示字符串的字符数组,其最后一个有效字符后面会自动(或需要手动)添加一个特殊的空字符 (Null Character) \0 作为字符串结束的标记
  3. 声明字符串 (字符数组):
    • 方法一 (字符列表): char s1[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; 手动添加 \0
    • 方法二 (字符串字面量): char s2[6] = "Hello"; 使用双引号括起来的字符串字面量进行初始化,编译器会自动在末尾添加 \0
  4. 长度计算:
    • 因此,存储字符串的字符数组,其声明的长度必须至少是字符串可见字符的个数 加 1(用于存放 \0
    • "Hello" 有 5 个可见字符,需要长度为 6 的字符数组 char s2[6] 。如果长度不够 (如 char s2[5]),编译时会提示截断风险
  5. 中文字符串:
    • 在中文字符集编码(如 GBK/GB2312,对应 CAPL 中的 encoding 936)下,一个中文字符通常占用两个字节 (即需要两个 char 空间)
    • 因此,存储包含中文的字符串,字符数组的长度需要计算为:(中文字符数 * 2) + (英文字符数 * 1) + 1 (为 \0)
    • 示例: char s3[7] = "我爱你"; "我爱你" 有 3 个中文字符,需要 3*2 + 1 = 7 的长度
  6. 输出字符串: 可以使用 %s 占位符直接输出整个字符数组(字符串)变量 write("S1 为 %s", s1);
  7. 字符串作为字符数组访问: 仍然可以用下标访问字符串中的单个字符,s2[1] 就是字符 'e'

六、 获取数组长度:elCount() 函数

  • 作用: CAPL 内置函数 elCount() (evaluate count) 用于获取一个数组的长度(即元素的个数)
  • 语法: elCount(ArrayName)
  • 返回值: 返回一个整数,表示数组的长度。
  • 示例:
    • write("scores 的长度为 %d", elCount(scores)); 输出 5
    • write("letters 的长度为 %d", elCount(letters)); 输出 3
    • write("s2 的长度为 %d", elCount(s2)); 输出 6 (因为 "Hello" 包含 5 个字符 + 1 个 \0)

七、 总结与后续

  • 本期学习了 CAPL 中数组的定义、初始化、通过下标访问元素、内存布局以及与字符串的关系。
  • 掌握了 elCount() 函数获取数组长度的方法。
  • 数组是后续处理报文数据等场景的基础。
  • 后续课程将继续讲解其他复合数据类型。