HOME >> 鉄道模型実験室 > if 文の違いについて

鉄道模型実験室 No.186  if 文の違いについて

 気なっていた 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 文を順番にチェックしている。

2) 条件に合うと波かっこ内を実行し、合わない場合は次の命令に移行している。

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) チェック条件が成立したひとつだけの命令を実行しているだけである。

2) これは、最初の if チェックから、最後の else 処理まで一つのグループとして判断しているようである。 

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 の状態だけで判断していることが分かる。

2) CH1〜CH3の状態が成立しない場合に、else 文は実行されていない。 直前の
if 文のみが関係するのか。

3) 即ち、直前のif 文のその前のif 文に対しては、else 文では関係ないようである。

3) if 文の実行順番は、記述順に実行している。

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 かを必ず報告してくる。

3) CH3 とCH4 については、どちらかが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 作成