---
# System prepended metadata

title: 13 使用列舉 (enumeration) 幫序號命名
tags: [CPP]

---

###### tags: `CPP`

# 13 使用列舉 (enumeration) 幫序號命名

使用陣列管理群組資料即使沒有要以循序的方式使用資料, 也有可以統一管理資料的好處, 不過如果單以序號來取用資料, 可能會不容易理解個別資料項目的意義, 例如若是我們只想在最亮與微微亮之間變化, 程式可以寫成以下這樣：

```cpp=
const int led_pin = 5;

struct twinkle_data {
  int pin;                // LED 腳位
  int duration;           // 亮/熄總時長
  int duration_on;        // 亮燈時長 (us)
  int total;              // 切換次數
}; 

twinkle_data twinkle_datas[] = {
  {led_pin, 100, 5, 10000}, // LED 微光 1s
  {led_pin, 100, 30, 5000}, // LED 稍亮 0.5s
  {led_pin, 100, 100, 2000} // LED 全亮 0.2s
};

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

void loop() {
  twinkle(twinkle_datas[2]); 
  twinkle(twinkle_datas[0]); 
}
```

由於是使用序號來指定資料項目, 所以如果不回頭看陣列內容, 我們並不會知道序號 2 和 0 的項目到底哪個比較亮？為了解決這個問題, 我們可以另外定義代表個別序號的變數, 並且為變數取一個具有說明意義的名稱, 例如：

```cpp=
const int led_pin = 5;

struct twinkle_data {
  int pin;                // LED 腳位
  int duration;           // 亮/熄總時長
  int duration_on;        // 亮燈時長 (us)
  int total;              // 切換次數
}; 

twinkle_data twinkle_datas[] = {
  {led_pin, 100, 5, 10000}, // LED 微光 1s
  {led_pin, 100, 30, 5000}, // LED 稍亮 0.5s
  {led_pin, 100, 100, 2000} // LED 全亮 0.2s
};

int shimmer = 0, brighter = 1, brightest = 2;

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

void loop() {
  twinkle(twinkle_datas[brightest]); 
  twinkle(twinkle_datas[shimmer]); 
}
```

第 16 行就是額外建立的變數, 並且在第 32~33 行改用變數的值當序號存取陣列內的資料。

上述作法雖然可以改進單純用序號不具說明意義的問題, 不過我們必須自己設定個別變數的值, 如果數值設定錯誤, 就會存取到錯誤的資料項目。為了解決這個問題, 可以改用[**列舉 (enumeration)**](https://en.cppreference.com/w/cpp/language/enum), 像是這樣：

```cpp=
const int led_pin = 5;

struct twinkle_data {
  int pin;                // LED 腳位
  int duration;           // 亮/熄總時長
  int duration_on;        // 亮燈時長 (us)
  int total;              // 切換次數
}; 

twinkle_data twinkle_datas[] = {
  {led_pin, 100, 5, 10000}, // LED 微光 1s
  {led_pin, 100, 30, 5000}, // LED 稍亮 0.5s
  {led_pin, 100, 100, 2000} // LED 全亮 0.2s
};

enum {
  shimmer, brighter, brightest
};

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

void loop() {
  twinkle(twinkle_datas[brightest]); 
  twinkle(twinkle_datas[shimmer]); 
}
```

第 16~18 就是列舉, 編譯器會自動幫我們從 0 開始編號, 所以 `shimmer` 會是 0、`brighter` 就是 1, 而 `brightest` 則是 2。在第 34、35 行就使用列舉的名稱來取用陣列中的資料。

利用列舉, 我們就可以幫序號取具有說明意義的名稱, 而且也不會編錯序號。