---
# System prepended metadata

title: 09 利用多維陣列結合相關資料
tags: [Arduino, CPP]

---

###### tags: `CPP` `Arduino`

# 09 利用多維陣列結合相關資料

如果不只是亮度要不規律的變化, 連時間也要隨意變化, 例如先稍微亮 0.5 秒、再暗一些 1 秒, 最後全亮 0.2 秒, 可以比照亮度的做法, 另外再定義一個陣列, 紀錄對應時間的亮暗切換次數, 像是這樣：

```cpp=
const int duration = 100;                  // 單次亮/熄時長 (us)
const int led_pin = 5;                     // 內建 LED 腳位 
const int levels[3] = {30, 5, 100};        // 亮燈時長
const int totals[3] = {5000, 10000, 2000}; // 亮/熄切換次數

void twinkle(int led_pin, int duration, int duration_on, int total) {
  for(int count = 0;count < total; count++) {
    digitalWrite(led_pin, LOW);
    delayMicroseconds(duration_on);
    digitalWrite(led_pin, HIGH);
    delayMicroseconds(duration - duration_on);
  }
}
 
void setup() {
  pinMode(led_pin, OUTPUT);
}

void loop() {
  for(int i = 0; i < sizeof(levels)/sizeof(int); i++) {
    twinkle(led_pin, duration, levels[i], totals[i]);
  }
}
```

第 4 行的陣列就是對應第 3 行陣列的切換次數, 重新上傳程式後就可以看到不同亮度持續時間都不同的效果。

結果雖然正確, 不過卻有個潛在的問題, 因為兩個陣列是分開的, 就可能會發生想增加亮度變化的層次, 但卻忘了在 `totals` 陣列新增對應的切換次數。要解決這個問題, 可以使用**多維陣列 (multidimentional array)**。

## 由陣列構成的陣列

你可以把多維陣列想成是由陣列構成的陣列, 也就是陣列中的每一項資料自己也是一個陣列, 例如：

```cpp
int led_info[3][2];
```

這表示 `led_info` 是一個內含 3 項資料的陣列, 其中的每一項資料都是一個內含 2 項資料的陣列, 也就是說 `led_info` 總共內含 3×2 共 6 項資料。如果要定義多維陣列的內容, 可以用多層的大括號形式, 像是這樣：

```cpp
int led_info[3][2] = {
  {30, 5000},    // 相當於 led_info[0]   
  {5, 10000},    // 相當於 led_info[1]
  {100, 2000}    // 相當於 led_info[2]
};
```

內層的一對大括號就對應到陣列的一項資料, 你可以看到這每一項資料自己又是一對大括號定義的陣列。如果要取得最內層陣列的資料, 就要使用兩次中括號, 像是這樣：

```cpp
led_info[0][1]  // 取得 5000
led_info[1][0]  // 取得 5
```

像是這樣的陣列我們就稱它為 **2 維陣列**, **第 1 個維度**有 3 項資料, 每 1 項資料自己又是 1 個 1 維陣列, 這稱為**第 2 維**, 存放宣告陣列時標示型別的資料。多維陣列並不限於 2 維, 若有需要, 還可無限延伸。

如此我們就可以改寫剛剛使用兩個單獨陣列的程式, 把亮燈時長和亮/熄切換次數整合在單一個多維陣列了：

```cpp=
const int duration = 100;                  // 單次亮/熄時長 (us)
const int led_pin = 5;                     // 內建 LED 腳位 
const int led_info[3][2] = {
  {30, 5000},                              // 亮燈時長與亮/熄切換次數
  {5, 10000},                              // 亮燈時長與亮/熄切換次數
  {100, 2000}                              // 亮燈時長與亮/熄切換次數
};

void twinkle(int led_pin, int duration, int duration_on, int total) {
  for(int count = 0;count < total; count++) {
    digitalWrite(led_pin, LOW);
    delayMicroseconds(duration_on);
    digitalWrite(led_pin, HIGH);
    delayMicroseconds(duration - duration_on);
  }
}
 
void setup() {
  pinMode(led_pin, OUTPUT);
}

void loop() {
  for(int i = 0; i < sizeof(led_info)/sizeof(led_info[0]); i++) {
    twinkle(led_pin, duration, led_info[i][0], led_info[i][1]);
  }
}
```

1. 第 3~7 行就是剛剛舉例的陣列, 其實就是把前面例子中的兩個陣列內容整合在一起, 分別是三種亮度的亮燈時長與亮/熄切換次數。
2. 第 23 行我們使用陣列本身的大小與陣列第 1 項資料的大小來計算多維陣列中第 1 維的資料數量。
3. 第 24 行就改用取多維陣列中第 2 維陣列內的資料作為參數。

上傳後和原本的程式效果一樣。
