switch文はすっきりしたコードが書きやすく愛用していたのですが、なかなか気付きにくいエラーに遭遇したため備忘録用に。
エラー1: 内部で変数を宣言
switch文の内部で変数を宣言する際には注意が必要です。
下のプログラムでは、途中で分岐処理が止まってしまいました(写真左)。
//悪い例(写真左)
//switch文のみ抜粋
int i = random(3); //0~2のランダム値(整数)
switch (i) {
case 0:
Serial.println("零郎"); //i=0の処理
break;
case 1:
String itiro = ("一郎"); //変数を宣言!・・・・(悪い例)
Serial.println(itiro); //i=1の処理
break;
case 2:
Serial.println("二郎"); //i=2の処理
break;
}
このエラーの厄介なところは、コンパイルが通常通り完了してしまうことです。
また、変数を宣言した部分の処理(上の場合は i=1 の処理)まで実行されてしまうことも、エラーに気付きにくい要因となっています。
対処法
- 関数に直接値を書き込む。
- switch文の外で変数を宣言する。
-
if()
やwhile()
などで入れ子にして宣言する。
//良い例(写真右)
int i = random(3); //0~2のランダム値(整数)
String itiro = "一郎"; //switch文の外で宣言
switch (i) {
case 0:
Serial.println("零郎"); //関数に直接入れる
break;
case 1:
Serial.println(itiro); //switch文の外で宣言した変数を使用
break;
case 2:
if(1) {
String ziro = "二郎"; //入れ子構造の中で宣言
Serial.println(ziro);
}
break;
エラー2: 同じ値を参照
case
で同じ値を参照するとエラーになります。
//悪い例
switch(i){
case 0 || 1:
Serial.println("0または1だよ"); //0か1の時の処理
break;
case 1:
Serial.println("1だよ"); //1の時の処理("1"が処理被り → エラー!)
break;
}
こちらは、Arduino IDE側でエラーを検知してくれるため、すぐに分かります。
同様の処理をするための方法は色々とありますが、無理やり"switch-case"形式で書くと可読性が悪化する可能性があるため、他の手段も模索しましょう。
//良い例
//1.break;を除く方法(エラーの原因になりやすく非推奨)
switch(i){
case 0:
Serial.println("0または1だよ"); //0の時の処理(break; が無いので、そのままcase 1:へ)
case 1:
Serial.println("1だよ"); //1の時の処理
break;
}
//2.case内で分岐
switch(i){
case 0 || 1:
Serial.println("0か1だよ"); //0か1の処理
if(i == 1){
Serial.println("1だよ"); //1の処理
}
break;
}
エラー3: String型を取り扱う
case
でString
(文字列型)クラスを参照するとエラーになります。
//悪い例
String str = "morning";
switch(str){
case "morning":
Serial.println("おはよう"); //str=="morning"の処理(エラー!)
break;
case "noon":
Serial.println("こんにちは"); //str=="noon"の処理(エラー!)
break;
}
こちらも、Arduino IDE側でエラーを検知してくれます。
String型はchar型を発展した配列ですので、caseに単体の定数しか入れることのできないArduino IDEでは扱うことができないようです。
よって、同様の処理を行いたい場合はif()文を使用することになります。
//良い例
String str = "morning";
if(str == "morning"){
Serial.println("おはよう"); //str=="morning"の処理(エラー!)
}
else if(str == "noon"){
Serial.println("こんにちは"); //str=="noon"の処理(エラー!)
}