気なっていた if 〜 if 〜 文、 if 〜 else 〜 文、 if 〜 else if 〜 文の違いを確認しておきたいと思います。
先回の「ロータリスイッチのコード化」(2021/1/16)で工作した装置を使用して、if 文の記述構成の実験を行った。 ダイヤル選択情報をデコードする場合、どの様に判断すれば良いのか考えて時に、if 〜 if 〜 文、 if 〜 else 〜 文、 if 〜 else if 〜 文の違いに戸惑いつつ、結局、各チャネル情報の AND によって判断する方式を選択した.。 しかし、疑問な点は実験で確かめるとハッキリするだろうと考えて、実験を実施してみることにした。
■ 実験の準備
実験装置は工作した操作盤とパソコンを使った実施した。 実験の様子を下に示す。
操作盤の中の状態を下に示す。 ロータリスイッチとコード化基板、および、Arduino Nano Every を示す。
操作盤には、ロータリスイッチを回すダイヤルと、その横には押しボタン式のスタートボタンを設けている。
// Every-if-1 // 2021.1.14 // Arduino Nano Every を使用する。 #define STRT 10 #define CH1 9 #define CH2 7 #define CH3 5 #define CH4 3 void setup() { pinMode(STRT,INPUT); pinMode(CH1,INPUT); pinMode(CH2,INPUT); pinMode(CH3,INPUT); pinMode(CH4,INPUT); Serial.begin(9600); }
■ 実験の方法
Arduino Nano Every に右に示すスケッチを書き込み、ダイヤルを所定の位置にセットして、スタートボタンを押す。 すると、その結果をシリアル通信によってパソコンに送られてくるので、シリアルモニタによってその内容を確認する。
スケッチの void loop() { } 部分は、それぞれの実験内容に応じて書き換えを実施しています。
************************************************************
まず、出力された信号の真理値表をまとめておきます。 なお、たびたび述べますが、回路は負論理で構成されているので、ロータリースイッチの端子が選択された場合(ONの場合)、信号はLOWレベルとなります。 回路図等は先回の報告を参照ください。
Dial 1 | Dial 2 | Dial 3 | Dial 4 | Dial 5 | Dial 6 | Dial 7 | Dial 8 | Dial 9 | Dial 10 | Dial 11 | Dial 12 | |
CH1 | HIGH | LOW | HIGH | LOW | HIGH | LOW | HIGH | LOW | HIGH | LOW | HIGH | LOW |
CH2 | HIGH | HIGH | LOW | LOW | HIGH | HIGH | LOW | LOW | HIGH | HIGH | LOW | LOW |
CH3 | HIGH | HIGH | HIGH | HIGH | LOW | LOW | LOW | LOW | HIGH | HIGH | HIGH | HIGH |
CH4 | HIGH | HIGH | HIGH | HIGH | HIGH | HIGH | HIGH | HIGH | LOW | LOW | LOW | LOW |
■ まずは手始めに
選択ダイヤルを1番から順番に回して操作し、この実験方法を確認しました。 簡単な if 文とし、その結果より、実験方法は良好と判断しました。
void loop() の記述 |
ダイヤル | モニタ表示 |
void loop() { if (digitalRead(STRT)==HIGH){ if (digitalRead(CH1)==LOW){ Serial.println("CH1=ON"); delay(1000); } else { Serial.println("CH1=OFF"); delay(1000); } } } |
diall 1 | CH1=OFF |
diall 2 | CH1=ON | |
diall 3 | CH1=OFF | |
diall 4 | CH1=ON | |
diall 5 | CH1=OFF | |
diall 6 | CH1=ON | |
diall 7 | CH1=OFF | |
diall 8 | CH1=ON | |
diall 9 | CH1=OFF | |
diall 10 | CH1=ON | |
diall 11 | CH1=OFF | |
diall 12 | CH1=ON |
■ if 〜 if 〜 文の記述
最初に、もぐらたたき方式の基本形である下記のような if 文を順番に記述した場合の挙動を確認しよう。
void loop() { if (チェック1) { 処理1 } if (チェック2) { 処理2 } if (チェック3) { 処理3 } if (チェック4) { 処理4 } }
実験結果を表にまとめた。
void loop() の記述 |
ダイヤル設定 | シリアルモニタの表示 | 考 察 内 容 |
---|---|---|---|
void loop() { if (digitalRead(STRT)==HIGH){ if (digitalRead(CH1)==LOW){ Serial.println("CH1=ON"); delay(1000); } if (digitalRead(CH2)==LOW){ Serial.println("CH2=ON"); delay(1000); } if (digitalRead(CH3)==LOW){ Serial.println("CH3=ON"); delay(1000); } if (digitalRead(CH4)==LOW){ Serial.println("CH4=ON"); delay(1000); } } } |
diall 1 | --- (表示なし) | 1) if 文を順番にチェックしている。 3) if 文の実行順番は、記述順に実行している。 |
diall 2 | CH1=ON | ||
diall 3 | CH2=ON | ||
diall 4 | CH1=ON CH2=ON |
||
diall 5 | CH3=ON | ||
diall 6 | CH1=ON CH3=ON |
||
diall 7 | CH2=ON CH3=ON |
||
diall 8 | CH1=ON CH2=ON CH3=ON |
||
diall 9 | CH4=ON | ||
diall 10 | CH1=ON CH4=ON |
||
diall 11 | CH2=ON CH4=ON |
||
diall 12 | CH1=ON CH2=ON CH4=ON |
すなわち、この記述では、出てきたモグラは順番に、かつ、全てたたく ことになります。
■ if 〜 else if 〜 else 〜 文の記述
次に、else を入れた下記のような if 〜 else if 〜 else 〜 文を記述した場合の挙動を確認しよう。
void loop() { if (チェック1) { 処理1 } else if (チェック2) { 処理2 } else if (チェック3) { 処理3 } else if (チェック4) { 処理4 } else { 処理5 } }
実験結果を表にまとめた。
void loop() の記述 |
ダイヤル設定 | シリアルモニタの表示 | 考 察 内 容 |
---|---|---|---|
void loop() { if (digitalRead(STRT)==HIGH){ if (digitalRead(CH1)==LOW){ Serial.println("CH1=ON"); delay(1000); } else if (digitalRead(CH2)==LOW){ Serial.println("CH2=ON"); delay(1000); } else if (digitalRead(CH3)==LOW){ Serial.println("CH3=ON"); delay(1000); } else if (digitalRead(CH4)==LOW){ Serial.println("CH4=ON"); delay(1000); } else { Serial.println("CH=all OFF"); } } } |
diall 1 | CH=all OFF CH=all OFF CH=all OFF ・・・・・・・・・・ CH=all OFF |
else { } の中で delay 文を書き忘れたため、スタートボタンが反応している間はどんどん表示される。 スタートボタンはポンと押しただけであるが、 loop内の巡回は早い事を実感する。 |
diall 2 | CH1=ON | 1) チェック条件が成立したひとつだけの命令を実行しているだけである。 3) そして実行するのは、最初に成立した命令のみである。 |
|
diall 3 | CH2=ON | ||
diall 4 | CH1=ON | ||
diall 5 | CH3=ON | ||
diall 6 | CH1=ON | ||
diall 7 | CH2=ON | ||
diall 8 | CH1=ON | ||
diall 9 | CH4=ON | ||
diall 10 | CH1=ON | ||
diall 11 | CH2=ON | ||
diall 12 | CH1=ON |
すなわち、この記述では、出てきたモグラは、最初にチェックしたモグラだけをたたく と言うことになります。 その他のモグラは無視されています。
■ if 〜 else 〜 文の記述
次に、else 文は、どこまでの範囲を対象するのかを確認するため、else を入れた下記のような if 〜 else 〜 文を記述した場合の挙動を確認しよう。
void loop() { if (チェック1) { 処理1 } if (チェック2) { 処理2 } if (チェック3) { 処理3 } if (チェック4) { 処理4 } else { 処理5 } }
else 文を複数のif 文の最後に記述し、その効力がどこまでの上流を対象にしているのかを確認する。 また、上記の失敗を修正するために delay 命令を追記している。
void loop() の記述 |
ダイヤル設定 | シリアルモニタの表示 | 考 察 内 容 |
---|---|---|---|
void loop() { if (digitalRead(STRT)==HIGH){ if (digitalRead(CH1)==LOW){ Serial.println("CH1=ON"); delay(1000); } if (digitalRead(CH2)==LOW){ Serial.println("CH2=ON"); delay(1000); } if (digitalRead(CH3)==LOW){ Serial.println("CH3=ON"); delay(1000); } if (digitalRead(CH4)==LOW){ Serial.println("CH4=ON"); delay(1000); } else { Serial.println("CH=all OFF"); delay(1000); } } } |
diall 1 | CH=all OFF |
1) dial 1 〜 dial 8 までは、CH4 はOFFなので、HIGH の状態である。 従って、else 命令は直前の CH4 の状態だけで判断していることが分かる。 |
diall 2 | CH1=ON CH=all OFF |
||
diall 3 | CH2=ON CH=all OFF |
||
diall 4 | CH1=ON CH2=ON CH=all OFF |
||
diall 5 | CH3=ON CH=all OFF |
||
diall 6 | CH1=ON CH3=ON CH=all OFF |
||
diall 7 | CH2=ON CH3=ON CH=all OFF |
||
diall 8 | CH1=ON CH2=ON CH3=ON CH=all OFF |
||
diall 9 | CH4=ON | ||
diall 10 | CH1=ON CH4=ON |
||
diall 11 | CH2=ON CH4=ON |
||
diall 12 | CH1=ON CH2=ON CH4=ON |
すなわち、この記述では、else の直前の if 命令としか連携していないと判断出来ます。 それ以前の命令とは独立していると考えられますので、if 〜 else 〜 文はひと塊の命令と考えておくべきでしょう。 もし、複数の命令とセットにするならば、前記のように else if 〜 文で記述する必要があるようです。
■ else文、else if文が混在している場合
次に、if 文の中に、else 文、else if 文が混在している場合はどの様な動きを示すのだろうか?
void loop() の記述 |
ダイヤル設定 | シリアルモニタの表示 | 考 察 内 容 |
---|---|---|---|
void loop() {
if (digitalRead(STRT)==HIGH){
if (digitalRead(CH1)==LOW){
Serial.println("CH1=ON");
delay(1000);
}
if (digitalRead(CH2)==LOW){
Serial.println("CH2=ON");
delay(1000);
}
else {
Serial.println("CH2=OFF");
delay(1000);
}
if (digitalRead(CH3)==LOW){
Serial.println("CH3=ON");
delay(1000);
}
else if (digitalRead(CH4)==LOW){
Serial.println("CH4=ON");
delay(1000);
} else {
Serial.println("CH3 or 4=OFF");
}
}
}
|
diall 1 | CH2=OFF CH3 or 4=OFF |
1) CH1 はONの時だけしか報告してこない。 2) しかし、CH2 はON か OFF かを必ず報告してくる。 4) if 、else 文の実行順番は、記述順に実行している。 |
diall 2 | CH1=ON CH2=OFF CH3 or 4=OFF |
||
diall 3 | CH2=ON CH3 or 4=OFF |
||
diall 4 | CH1=ON CH2=ON CH3 or 4=OFF |
||
diall 5 | CH2=OFF CH3=ON |
||
diall 6 | CH1=ON CH2=OFF CH3=ON |
||
diall 7 | CH2=ON CH3=ON |
||
diall 8 | CH1=ON CH2=ON CH3=ON |
||
diall 9 | CH2=OFF CH4=ON |
||
diall 10 | CH1=ON CH2=OFF CH4=ON |
||
diall 11 | CH2=ON CH4=ON |
||
diall 12 | CH1=ON CH2=ON CH4=ON |
この実験結果より、if 〜 else 〜 文は一つのセットであり、複数の命令とセットにするならば、前記のように else if 〜 文で記述する必要があると言う上記の考察内容を補足することが出来たと考えます。
■ まとめ
なんだかこの構文を理解したつもりです。 しかし、今年79才となった後期高齢者にとっては、ややこしい内容となってしまいました。 最良の手は、このようなややこしい構文には、手を出さないようにすることだと思っています。
寄り道をしてしまいましたが、次回は、卓上レイアウトの自動運転工作に戻る事にします。
2021/1/17 作成