3-11 elseとelse ifでもっと分岐

分岐処理の基本である「if」に、「else」や「else if」を組み合わせることでより複雑で多彩な分岐処理を作り出すことができます。
ちょっと長いですが、このページで第3章は修了です。もうひと踏ん張りです。
  

「if」は非常に便利な処理ですが、条件式がtrueだった時にしか処理を与えることができません。
例えば前項のサンプルコード3-10_if.inoでは、if文の条件式がfalseだった場合は「また来週!」だけが表示されるだけの非常にさみしいものになっています。
もし条件式がfalseだった(=生成された乱数が「1, 2, 3, 4」のどれかだった)場合に、trueとは異なる処理をしたい場合はどうすればよいでしょうか。
  
  
🤔💭「if(randNum >= 5)のif文の下に、(randNum < 5)を条件式にしたif文を書けばよいのでは?」
  
と、とっさに思い付いた方は、とても冴えています(すばらしい!👏👏👏)
  
  
実はそれと同じ機能を、もっとシンプルな記述で実現する手段があります!
それは「if」に「else」を組み合わせて使うことです。
  

if( 分岐処理をするための条件式をここに書く ){
  条件が成立している(true)ときに実行したい処理をここに書く
  処理は何行書いてもOK
} else {
  条件が不成立(false)のときに実行したい処理をここに書く
  処理は何行書いてもOK
}
1~3行目

この部分はさっきのifそのままです。
( )内の条件式が成立した(true)場合、2~3行目内部の命令を、上から順に一行ずつ実行します。
 

4行目

ifの終結部「}」の後に else がついていて、更にその後ろから新たな{ }が発生しています。
この波かっこの中は、ifの条件式が不成立だった(false)場合に実行したい処理を書く場所です。
こちらもifと同じで、処理は何行でも書いてOKです。もちろんこの内部に更に別の分岐処理や繰り返し処理を書いて、入れ子状にするのもOKです。
{ }内の処理をすべて終了すると、elseは終了です。引き続いて8行目以降の処理が実行されます。

条件式で判定をしたときに、返す答えはtrueかfalseの二択です。
今回このif文ではelseを使うことで、条件式がtrueの場合とfalseの場合それぞれの処理を指定しました。
なので、2行目~7行目までの処理が飛ばされることは絶対にありません。trueであれば2~3行目、falseであれば5~6行目が必ず実行されます。
  

サンプルコード3-11-1_else.inoを開いてください。

long randNum;
//生成した乱数を入れておく変数です。
//乱数はlong型の整数で生成される決まりなので、longで定義しています。

void setup() {
   Serial.begin(9600);
   randomSeed(analogRead(0));
   //このプログラムでは乱数を使いたいので、そのためにまずは
   //Arduinoの、何も接続していないピンのノイズを利用して
   //疑似乱数ジェネレータを初期化します。
}

void loop() {
   randNum = random(1, 10);
   //乱数を生成して、変数randNumに入れておきます。
   //今回生成する乱数は、1~9のどれかの整数です

   if (randNum >= 5) {
     Serial.print("今回生成された乱数は");
     Serial.print(randNum);
     Serial.println("でした!");
   } else
     Serial.println("残念賞のあなたには!!!!!!!!!!!!!");
     Serial.println(" おまる が授与されます");
   }
   Serial.println("また来週!");
   delay(3000);
}

動作確認

このプログラムは、3-10_if.inoのif文に、elseの処理を追加したものです。
このプログラムをArduinoに書き込むと、下記のいずれかのメッセージがランダムに表示されます。
(今回もXには5~9の数字が入ります)

今回生成された乱数はXでした!
残念賞のあなたには!!!!!!!!!!!!!
 おまる が授与されます

その直後に

また来週!

が表示され、約3秒経過した後再度処理が繰り返されます。

コード解説

前半は3-10_if.inoと全く同じなのでif文が開始する18行目まで飛ばします。

18行目
 for (int count = 1; count <= 10; count++) {

ここも3-10と全く変わりありません。(randNum >= 5) なので、生成された乱数が「5, 6, 7, 8, 9」のどれかであればtrueです。
trueだった場合に実行される19~21行目の処理もそのままです。
処理をすべて終えたらこのif文は終了です。22~25行目はすっ飛ばして26行目に移ります。

22~25行目
} else {
   Serial.println("残念賞のあなたには!!!!!!!!!!!!!");
   Serial.println(" おまる が授与されます");
} 

ここからelseの出番です!
if文冒頭の条件式は(randNum >= 5) でした。なので、生成された乱数が「1, 2, 3, 4」のどれかであれば不成立、すなわちfalseの判定になっています。
条件式がfalse判定だった場合、19~21行目の内容はすっ飛ばし23行目から処理が始まります。
trueと同じ文言を表示しても面白くないので、elseの行では生成された乱数の値に関係なく、残念賞のメッセージを表示しています。

26行目
Serial.println("また来週!");

if文の外に出ました。if文の判定に関係なく、一律「また来週!」を表示します。

27行目
delay(3000);

人間がシリアルモニタを目で追えるよう、3秒待機させます。
28行目まで到達したらloop文の冒頭に戻り再び処理が始まります。
  
  

else文のポイント

  • ifと組み合わせて使う
  • ifの条件式がfalseの場合にも処理を与えることができる
  • elseの処理は、ifの条件式の判定がfalseであれば問答無用で実行される


  
  
  

「else」を使うことで、if文の中でtrueの時とfalseの時で2通りの処理を行えるようになりました。
でも世の中、二者択一だけではどうにもならないこともあります。
  
例えば、変数の数値が「1」の時、「2」の時、「3」の時、「それ以外」の時で処理を分けたい…
つまり3つ以上の分岐をしたい場面も出てくるはずです。そんな時はどうすればよいのでしょうか。
  
  
🤔💭「if文を書いて、elseの中にもう一つif文を入れ子にして書けばよいのでは?」
  
と、思い付いた方は、とてつもなく冴えています(この資料の残りの章全部書いてほしい!💪💪💪)
  
もちろんそれでもOKです!
ただこの流れでだいたいお察しいただけるかとは思いますが、入れ子のif文と同じことを、簡単に実現できる専用の書き方があります。
それが「else if」です。
  

if( 条件式A ){
 条件式Aがtrueのときに実行したい処理
} else if( 条件式B ){
 条件式Bがtrueのときに実行したい処理
} else if( 条件式C ){
 条件式Cがtrueのときに実行したい処理
} else {
 条件式AもBもCもすべてfalseだった場合に実行したい処理
}
1~2行目

ありふれたif文です。( )内の条件式を、他と区別するために 条件式A とします。
この条件式Aがtrueだった場合は、2行目の処理を実行してif文を終了します。
条件式Aがfalseだった場合は、{ }内は実行せず3行目のelse ifに移ります。

3~4行目

「else if」の登場です。else ifの後ろには( )があり、中には条件式Bが入っています。
条件式Aがfalseだった場合、続けてこの条件式Bの判定が行われます。
条件式Bがtrueだった場合は、後続の{ }の内部の処理を実行後、if文を終了します。
条件式Aに引き続いてBもfalseだった場合は、{ }をすっ飛ばし5行目のelse ifに移ります。

5~6行目

2つ目の「else if」です。( )内には条件式Cが入っています。
やることは3~4行目と同じです!条件式AもBもfalseなので、条件式Cの判定が行われます。
Cがtrueであれば{ }内を処理してif文終了、falseであれば7行目に移ります。

7~8行目

最後に「else」です。elseは条件式がfalseだった場合に{ }内の処理を実行する場所です。
A・B・Cの全てでfalseを叩き出した、falseの中のfalseにのみ処理が実行され、if文を終了します。
  

サンプルコード3-11-2_elseif.inoを開いてください。

long randNum;
//生成した乱数を入れておく変数です。
//乱数はlong型の整数で生成される決まりなので、longで定義しています。

void setup() {
   Serial.begin(9600);
   randomSeed(analogRead(0));
   //このプログラムでは乱数を使いたいので、そのためにまずは
   //Arduinoの、何も接続していないピンのノイズを利用して
   //疑似乱数ジェネレータを初期化します。
}

void loop() {
   Serial.println("菌類占い はじまるよ~~~!!");
   delay(1000);
   randNum = random(1, 8);
   //乱数を生成して、変数randNumに入れておきます。
   //今回生成する乱数は、1~7のどれかの整数です

   if (randNum == 1) { //乱数が1だった場合
     Serial.println("今週のあなたの運勢は 大吉 です!!");
     Serial.println("クローゼットの中に松茸が生えるでしょう");
   } else if (randNum == 2){ //乱数が2だった場合
     Serial.println("今週のあなたの運勢は 吉 です!!");
     Serial.println("ひじからしいたけが生えます");
   } else if (randNum == 3){ //乱数が3だった場合
     Serial.println("今週のあなたの運勢は 凶 です!!");
     Serial.println(" きくらげに きをつけろ ");
   } else { //1、2、3以外の乱数が生成された場合
     Serial.println("今週のあなたの運勢は 大凶 です!!");
     Serial.println("粘菌で十分です");
   }
   Serial.println("また来週!");
   delay(3000); 
}

動作確認

今回のコードも生成された乱数によって処理を分岐し、異なるメッセージを表示するものです。
else ifを使うことで分岐先は4つ、つまり4種類のメッセージが表示されます。

そしてどんなメッセージが表示されたとしても、最後に

また来週!

が表示され、約3秒経過した後再度処理が繰り返されます。

コード解説

if文が開始する20行目までは、おさらいしかないので飛ばします。

20行目
if (randNum == 1) { //乱数が1だった場合

if文開始です。まずは一つめの条件式です。
(randNum == 1) なので、生成された乱数が「1」であればtrueです。
trueだった場合は21~22行目の処理を順番に実行してif文終了。33行目に移ります。
falseの場合は21~22行目を飛ばして23行目に移ります。

23行目
} else if (randNum == 2){ //乱数が2だった場合

最初のelse ifです!
二つめの条件式は(randNum == 2) です。なので、生成された乱数が「2」であればtrueです。
条件式がtrue判定だった場合、24~25行目の内容を実行してif文終了、falseの場合は26行目に飛びます。

26行目
} else if (randNum == 3){ //乱数が3だった場合

次もelse ifです!
条件式は(randNum == 3)です。乱数が「3」であればtrueで、27~28行目の内容を実行して
if文を終了、falseの場合は29行目に飛びます。

29行目
} else { //1、2、3以外の乱数が生成された場合

最後にelseが待ち構えています。
先に出てきた3つの条件式の全てでfalse判定がついた場合は、最終的にここに行きつきます。
elseの{ }内の処理を実行してif文を終了します。

33行目
Serial.println("また来週!");

if文の外に出ました。if文の判定に関係なく、一律「また来週!」を表示します。

34行目
delay(3000);

人間がシリアルモニタを目で追えるよう、3秒待機させます。
28行目まで到達したらloop文の冒頭に戻り再び処理が始まります。
  
  
今回のサンプルコードでは、randNumというひとつの変数の値だけをチェックし処理を分岐しました。
そうではなく、else ifした先で別の変数を参照して分岐を発生させることも、もちろん可能です。
また今回のサンプルコードのように、ひとつの変数の値の違いだけをチェックして複数分岐をしたい場合は、else ifを連発する他にも「switch case」文を利用することもできます。(ぜひ調べてみてね!)
  
  

else ifのポイント

  • ifと組み合わせて使う
  • ifの条件式がfalseの場合に、更に条件を与えて判定をすることができる
  • elseも組み合わせることができる
  • ひとつの変数の値の違いだけをチェックして複数分岐をしたい場合は「switch case」もあるよ