Arduino - 数组
Arduino - 现代数组处理
Section titled “Arduino - 现代数组处理”数组是一种基本数据结构,用于存储相同数据类型的固定大小、顺序集合。可以将其视为一排带有标签的盒子,每个盒子都存放着相同类型的值(例如,都是整数)。
理解数组概念
Section titled “理解数组概念”要访问数组中的特定元素,您需要使用其名称和索引。索引(或下标)指定了元素的位置。
- 零基索引:在C++(Arduino的编程语言)中,数组索引从0开始。第一个元素位于索引0,第二个位于索引1,依此类推。
- 最后一个元素:最后一个元素的索引始终是
arraySize - 1。
让我们可视化一个名为sensorReadings的int类型数组,其中包含5个元素:
Array name: sensorReadings
Index: [0] [1] [2] [3] [4] +-----+-----+-----+-----+-----+Value: | 452 | 455 | 450 | 458 | 454 | +-----+-----+-----+-----+-----+
// 要访问值450,您可以使用:sensorReadings[2]声明和初始化数组
Section titled “声明和初始化数组”在使用数组之前,必须先声明它,指定其类型、名称和大小。一种现代的最佳实践是使用const或constexpr变量来定义大小,以避免魔术数字并使代码更易于维护。
// 最佳实践:将大小定义为常量。const int SENSOR_COUNT = 5;
// 声明一个包含5个元素的整数数组。int sensorReadings[SENSOR_COUNT];数组可以通过多种方式初始化。
示例1:使用初始化列表进行初始化
Section titled “示例1:使用初始化列表进行初始化”最常见和简洁的方法是在声明中直接提供值。
// 编译器自动从列表中推断大小。int ledPins[] = {2, 3, 4, 5, 6};
void setup() { Serial.begin(9600);
Serial.println("Configuring LED pins...");
// 遍历数组的一种现代、安全方式:基于范围的for循环 for (int pin : ledPins) { pinMode(pin, OUTPUT); Serial.print("Pin "); Serial.print(pin); Serial.println(" configured as OUTPUT."); }}
void loop() { // 本示例中为空}示例2:使用循环进行初始化
Section titled “示例2:使用循环进行初始化”有时您需要用计算值初始化数组。for循环是实现此目的的完美选择。
const int NUM_VALUES = 10;int squaredValues[NUM_VALUES];
void setup() { Serial.begin(9600);
// 使用索引的平方(i*i)初始化数组 for (int i = 0; i < NUM_VALUES; ++i) { squaredValues[i] = i * i; }
Serial.println("Array Initialized. Contents:"); // 打印数组内容进行验证 for (int i = 0; i < NUM_VALUES; ++i) { Serial.print("Index "); Serial.print(i); Serial.print(": "); Serial.println(squaredValues[i]); }}
void loop() { // 本示例中为空}使用数组:一个实际示例
Section titled “使用数组:一个实际示例”示例3:计算传感器读数的平均值
Section titled “示例3:计算传感器读数的平均值”此程序计算存储在数组中的一系列模拟传感器读数的平均值。它演示了迭代和常见的计算。
// 传感器读数数组int sensorReadings[] = {87, 68, 94, 100, 83, 78, 85, 91, 76, 87};
// 一种健壮的计算数组大小的方法,它会随着数组的更改而调整const int NUM_READINGS = sizeof(sensorReadings) / sizeof(sensorReadings[0]);
void setup() { Serial.begin(9600);
long total = 0; // 使用'long'类型计算总和以避免大数组溢出
// 对数组内容求和 for (int i = 0; i < NUM_READINGS; ++i) { total += sensorReadings[i]; }
// 将平均值计算为浮点数 float average = (float)total / NUM_READINGS;
Serial.print("Total of array elements: "); Serial.println(total); Serial.print("Number of readings: "); Serial.println(NUM_READINGS); Serial.print("Average reading: "); Serial.println(average);}
void loop() { // 主循环为空,因为计算只执行一次。}Total of array elements: 849Number of readings: 10Average reading: 84.90常见错误与最佳实践
Section titled “常见错误与最佳实践”- 越界错误:最常见的错误是尝试访问不存在的元素(例如,在5个元素的数组中访问
myArray[5])。C++不会阻止这种情况!它会从相邻内存中读取或写入,导致难以追踪的不可预测的崩溃和错误。请始终警惕您的循环条件(< size,而不是<= size)。 - 差一错误:与零基索引相关的经典错误。忘记最后一个元素在
size - 1处通常会导致越界访问。 - 使用
sizeof计算数组长度:sizeof(array) / sizeof(array[0])模式是确定数组元素数量的标准、健壮方法。如果您从初始化列表中添加或删除元素,它会自动适应。 - 使用基于范围的
for循环:当您只需要读取数组中的每个元素时,for (int element : myArray)语法更简洁、更安全,因为它消除了越界错误的可能。
| 概念 | 描述 |
|---|---|
| 多维数组 | 数组可以有多个维度。例如,int table[3][4];创建了一个2D数组(一个网格或表格),有3行4列。这些对于表示网格、矩阵或游戏棋盘非常有用。 |
| 将数组传递给函数 | 您可以将数组传递给函数对其进行操作。通常,您会传递数组本身(它充当指向第一个元素的指针)及其大小作为单独的参数,以防止函数内部的越界访问。 |
| 现代C++容器 | 对于更高级的项目或在更强大的开发板(如ESP32)上,考虑使用C++标准库容器,如std::array或std::vector。std::array是一个固定大小的容器,内存占用与C风格数组相似,但具有更现代的接口。std::vector是一个动态数组,可以根据需要增长和收缩。 |