AREA 021
Featuring AlphaScript

STEP 11 条件分岐

 

「条件分岐」(じょうけんぶんき)は、プログラムの実行の分岐点を作る仕組みです。 例えるなら、分かれ道とか試験の結果発表みたいなものです。(で、いいのかな?)  これにより、いつも同じタイミングで同じ命令が実行される、という束縛から解放されます。

つまり「もし○○だったら、△△しよう」というものですね。  「AlphaScriptは面白そうだら、やってみよう」というのと同じです。(え、違いました?)


そこで「条件分岐」の出番です




条件分岐は、書かれた式を計算(評価)して、その結果によってその後の大カッコ { } の中の記述を実行するかを決めます。 以下に例を示します。

if: a == 10 {

  b = 50;

}

if: が条件分岐に使うコマンドで、こう書くと a が 10 に等しい場合のみ、 { } で囲まれた b=50 が実行されます。  これを「if文」(いふぶん)と呼びます。

たとえば

if: x <= y { /* ここに何か処理を書く */ }

なら、 x が y 以下なら { } 内の記述が実行されます。

また、if文の中にif文を入れることもできます。

if: a >= 20 {

  if: a < 80 {

    b = 0;

  }

}

こう書かれていた場合、 a が 20 以上 80 未満なら b=0 が実行されます。  a が 100 だとしたら、最初の a>=20 は通過できますが、その次の a<80 の条件を満たしていないため結果的に何もしません。  { と } の対応に注目してください。

ところで、1つ前の例では1行にまとめましたが、 通常if文を書くときは見やすくするため、 { と } でそれぞれ改行し、{ }内はインデント(字下げ)します。 ( { の前にも改行を入れる人もいますね)  if文を2つ組み合わせたときの例を見ていただければその効果がよくわかると思います。  ただ、全体が短い文のときは、逆に1行にまとめた方が見やすい・・・かもしれません。

この辺は個人の好みもあります。 作者は2,3個のif文を1行に書いたりすることもあります。(^^;


真偽の極意

a==b などの条件式の結果には、式が成立したときには 真(しん)、成立しなかったときは 偽(ぎ)という呼び方があります。  こう聞くと、何だか難しそうですが、実は意外と簡単なことです。  AlphaScript には次のような法則があります。

「真」の正体は数値の0.0以外、「偽」の正体は数値の0.0です。

そして、「真」だと判定された式は、1.0になります!

つまりこういうことです。

1 + 2

まず、この式の答えは? ・・・もちろん 3 ですね。

10 < 20

では、この式は? 普通の数学ではこのような計算式はありませんが、プログラミングの世界には存在します。  10 は 20 より小さいので、式が成立 → ということは「真」 → 真なら1.0になる・・・ということで、この式を計算すると、1.0になります。

10 > 20

これだと、式が成立しないので偽となり、数値の 0.0 として扱われます。

これでif文の意味がはっきりします。  if はその後に書かれている式を計算し、結果が 0.0 以外ならその後の記述を実行し、0.0なら実行しない、ただそれだけのことです。  極端な話、 if:1 などと書けば{ }内が必ず実行されるif文になります。

また、真偽(しんぎ)の仕組みをうまく使えば、こんなやり方も可能です。

cnt = 0;  // カウント用の変数(countの略)

cnt += ( a == 50 );  /* 本来は if: a == 50 { cnt += 1; } と書かなければいけない */
cnt += ( b == 50 );  /* 上に同じらしい */
cnt += ( c == 50 );  /* 上に同じらしい */

// ここに来たとき、cntには個数が入っているはずだ!!

これは、変数 a,b,c の中に 50 に等しいものが何個あるかを数えるスクリプトです。  条件式の結果も数値になるのだから、普通の計算式として使ってしまおう、というスマートな作戦(?)です。  if文を3回書くよりコンパクトですし、こちら方が処理時間も早いので、2つの意味で効率が良いです。 (まあ、こういう特殊な書き方を嫌う人もいるかもしれませんが・・・・・いや、確実にいます)


あとついでに、ひとつ注意。

20 > a > 10

a が 15 だとすると、この式の結果は・・・??  ぱっと見たところ、 15 は「20未満で10より大きい」から、真(=1.0)になるような気がしますが・・・。  残念ながらそうはいかないです。(-_-;)

それは、比較演算子が2つの数値を比べること以外できないのが原因です。  この式の場合、計算順序は ( 20 > a ) > 10 となります。  まず左の 20 > a の部分の結果を求め、その後で > 10 の比較を行うので、結果は 1 > 10 と同じ。  というわけで、偽になってしまうのです。

AlphaScript に限らず、普通のプログラミング言語ならこの書き方はエラーになるか、結果がおかしくなってしまいます。  上記のような判定をしたいときは、次に説明する複合条件を使ってください。

また、比較演算子も左から順に処理されていきますので、 比べる左右の項が単一の値ではない場合、カッコで囲まないと結果がおかしくなります。  例えば、 a+b と c-d が等しいかを調べたいときは、 (a+b)==(c-d) と書くのが正しいです。

これについては、他のプログラミング言語ならちゃんと順番を考慮して処理されるでしょう。  それでも、比較する左右の式は明示的に ( ) で囲むようにしている人も多いようです。  計算用の演算子と比較用の演算子は性質が異なるので、それをはっきり区別させるためだと思われます。  そういう習慣を馴染ませるのには、この言語は最適かもしれません。(^^;


複合条件

if: a > 20 {
  if: a < 80 {

  }
}

このように、2つの数値を1回比べるごとにif文を書くのは面倒、というかすっきりしませんよね。  そこで使えるのが、複合条件の演算子、 & | です。  上記の例を & を使って書き直してみます。

if: ( a > 20 ) & ( a < 80 ) {

}

if文がひとつになり、見やすくなりました♪  & は左にある式と右にある式の結果が両方とも真なら真、そうでなければ偽となります。  比較演算子と同様に、左右の式はカッコで囲むことに注意してください。

| の場合は、左右の式のどちらかが真なら真になります。

if: ( a < 20 ) | ( a > 80 ) {

  // a が 20 未満か 80 より大きければ合格!

}

でも、 AlphaScript の場合、最初の例のように if を複数つづけて書いたほうが望ましい場合もあります。  というのは、 & で式をくっつけたとき、左側の式の結果が偽となり、 もう成立する可能性がなくなっていても、右側の式まで計算してしまうことからです。  たとえば a が 10 のとき、 (a>20)&(a<80) と書いてあったとすれば、 a は 20 以下なので、左側の式の時点でこの条件が成立することはあり得ないです。  これだと、わざわざ右側の式を計算するのがもったいないと言えるのです。  | を使ったときに、式の途中で成立が確定してしまった場合も同様です。

また、 abs(a)==100 のように条件式に関数を含んでいた場合、 条件判定が行われる度に、含まれる関数が必ず実行されることにも注意してください。  上記の abs関数 は結果を求める以外、特に何もしないので問題ないですが、 関数によっては呼び出すだけで何か動作してしまうものもあります。

まあ、ほとんどは複合条件でOKですが、 if を複数に分けて書くことにも意味はある、と覚えておいてくださいね。(^^


もうひとつのif文

if文と一緒に使われる文として、else文があります。 (elseの意味がわからないときは英和辞典にアタック!(笑))  else文は、前にあるif文の条件式を計算した結果が偽なら通過できる分岐です。  また、elseではなく elseif と書くと、さらに別の条件を付けることもできます。  例を示したほうがわかりやすいでしょうね。

if: mode == 1 { /* モード1  ふにゃふにゃ */ }else
if: mode == 2 { /* モード2  ぐにゃぐにゃ */ }else
if: mode == 3 { /* モード3  ボヨヨ〜ン! */ }

上記のスクリプトには、elseif文が2回使われています。  でもこれを見ると、後ろに else が2個付いているだけに見えますが・・・?  これは、コードの見やすさを追求した書き方です。  AlphaScript では、改行は無視されますので、後ろの else と前の if がくっついて、elseif になるのです。  基本的に elseif 文は上記のような書き方で統一しています。

そして、これを実行すると、変数 mode が 1 になっていて最初のif文を通過した場合、それ以降、後につづけて書かれたelseif文を無視します。  例のように同じ変数の内容によって処理を振り分けるとき、 1つでも該当するものが見つかれば、残りの判定は飛ばしても関係ないので、elseif文が役に立ちます。  mode==1 が成立するなら ==2 や ==3 が同時に成立するはずがないですからね。  これを全部if文による判定で書いても一応動きますが、どんな場合も1つ1つ判定していくので効率が悪いです。  なので、最初の1つは if 、2つめ以降は elseif にしてください。 (なお、状態によって処理を振り分けるのには、ラベルを複数宣言し、違う識別番号を付ける方法もあります)

単純に「そうでなかった場合」の処理をしたいときに使えるのが else です。

if: a > 0 {

  // a はゼロより大きいぞ!

} else {

  // a はゼロかマイナス値だぞ!

}

if文の式が成立すれば、その後にあるelse文も無視されます。  逆に成立しなければ else の場所までジャンプします。  else 文には条件が無いので、そこまで来れば何も判定せずに成立となります。  if〜elseif〜else という形でもよく使われます。

では最後に、このステップの卒業試験です。  このスクリプトを実行した後の変数 n の値は?  (カッコの中が先ですよ〜)

$ n;

n = 0;

if: ( ( 100 <= 80) | ( 50 > 25 ) ) & ( 300 > 303 )                  { n = 1; }else
if: ( ( 0 == 1 ) | ( 2 == 3 ) | ( 4 == 5 ) ) | ( 128 <> 128 )       { n = 2; }else
if: ( ( 90+50 ) > 100 ) & ( ( 500/4 ) > 100 ) & ( ( 25*5 ) > 100 )  { n = 3; }else
                                                                    { n = 4; }

答えは、 4+((2+3)-8)+(12-9)-1 です。(合ってます?)

 

ページ一覧に戻る  次のステップへ!

Copyright (c) Rabit 2005-2012 all rights reserved.