###### 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 行就使用列舉的名稱來取用陣列中的資料。
利用列舉, 我們就可以幫序號取具有說明意義的名稱, 而且也不會編錯序號。