情報学入門(データ演習) / 第 5 章

分岐(1)

場合によって違うことをする ── If 文と条件式

この章のねらい

1. 流れ図で考える

ここまでのプログラムは上から下へ一直線でした。 これからは枝分かれ後戻りが入ります。 その形を表すのが流れ図(フローチャート)です。

記号意味
角の丸い四角開始・終了
長方形処理(計算や代入)
ひし形判断(条件によって行き先が分かれる)
矢印流れの向き

元資料 9 枚目の課題「1〜N までの総和を求める」を流れ図で書くと、こうなります。

動かす① 流れ図をたどる(1〜5 の総和) 1 歩ずつ

ひし形(i <= N ?)で「はい」なら下へ、「いいえ」なら外へ抜けます。 そして下まで行ったらひし形の上に戻る ── これが繰り返しの正体です。 この「戻る」を作る道具が 2 つあります。 1 つが GoTo(この章)、もう 1 つが ForDo(第 7・8 章)です。

2. 無条件分岐 ── GoTo

元資料 8・11 枚目にある、いちばん原始的な分岐です。

  GoTo ラベル
  ……
ラベル:

条件を見ずに、書いた場所へ飛びます。だから「無条件」分岐です。 飛び先にはラベル(名前+コロン)を書きます。

Sub Macro1()
    Dim s As Integer
    Dim i As Integer
    Dim N As Integer

    N = 5
    s = 0
    i = 1

Loop1:
    If i > N Then GoTo Owari    ' 終わりなら抜ける
    s = s + i                   ' 足す
    i = i + 1                   ' 次へ
    GoTo Loop1                  ' 戻る

Owari:
    Cells(1, 1) = "1 から " & N & " までの合計"
    Cells(1, 2) = s
End Sub

ただし、GoTo は使わないでください。 元資料は GoTo を最初に紹介していますが、 現代のプログラミングでは避けるべきものとされています。 1968 年に E. W. ダイクストラが 「Go To Statement Considered Harmful(GoTo 文は有害である)」という文章を発表して以来、 これが共通の理解になりました。

理由は、読めなくなるからです。 GoTo があると「いまここに来る前、どこを通ってきたのか」が プログラムを見ただけでは分からなくなります。 飛び先が 10 か所あれば、10 通りの経路を全部考えないと動きを追えません。 第 9 章の構造化プログラミングは、まさにこれを避けるための考え方です。

では、なぜ習うのか。2 つ理由があります。

上のプログラムは、第 7 章で習う For を使えば 4 行で、しかも読みやすく書けます。比べてみてください。

Sub Macro2()
    Dim s As Integer
    Dim i As Integer
    Dim N As Integer

    N = 5
    s = 0

    For i = 1 To N
        s = s + i
    Next i

    Cells(1, 1) = "1 から " & N & " までの合計"
    Cells(1, 2) = s
    Cells(3, 1) = "GoTo 版は 6 行、For 版は 3 行"
End Sub

3. 条件分岐 ── 従来型の If 文

元資料 5・12 枚目の書式です。1 行で書ける形を、VBA では「従来型 If 文」と呼びます。

If 条件式 Then 文1 [Else 文2]

角かっこ [ ] は「書かなくてもよい」という意味です(実際に [ ] は打ちません)。

元資料 12 枚目の例は、そのまま動きます。

Sub Macro3()
    Dim a As Integer, b As Integer, c As Integer
    Dim k As Integer, cnt As Integer
    Dim St As String

    ' ① k が 0 でなければ数える。0 なら 0 に戻す
    k = 5: cnt = 0
    If k <> 0 Then cnt = cnt + 1 Else cnt = 0
    Cells(1, 1) = "cnt": Cells(1, 2) = cnt

    ' ② 3 つが等しいか
    a = 2: b = 2: c = 2
    If a = b And b = c Then St = "A,B,Cは等しい"
    Cells(2, 1) = "St": Cells(2, 2) = St

    ' ③ どちらかが 0 なら積は 0
    a = 0: b = 7
    If a = 0 Or b = 0 Then Cells(3, 2) = "a*b=0"
    Cells(3, 1) = "判定"

    ' ④ 負なら、そこでプログラムを終える
    a = 5
    If a < 0 Then End
    Cells(5, 1) = "a は 0 以上だったので、ここまで来ました"
End Sub

元資料 12 枚目の If a < 0 Then EndEnd「プログラムをここで終える」という命令です。 End If(If の終わり)や End Sub(手続きの終わり)とは別のもので、 同じ単語なので混同しやすいところです。

なお、実際のプログラムで End は使わないほうがよいです。 どこからでも強制終了できてしまい、後片づけが行われません (第 9 章の Exit Sub なら、呼び出した側に戻ってから続きを処理できます)。 上のプログラムで a = 5a = -5 に変えて実行すると、 5 行目のメッセージが出ないまま止まるのが確かめられます。

4. 条件式のつくり方

条件式の値は真(True)偽(False)のどちらかです。 この型を論理型(Boolean 型)といいます(第 3 章)。 条件式を組み立てるのに使うのが、次の 2 種類の演算子です。

4.1 関係演算子(relational operator)

元資料 14 枚目(値は正しい)
演算子意味使い方
=2 つの値が等しいX = Y
<>2 つの値が等しくないX <> Y
<左の値が右の値より小さいX < Y - 5
<=左の値が右の値以下X <= 100
>左の値が右の値より大きいX > Y
>=左の値が右の値以上X >= Y

「より小さい」と「以下」を区別してください。 i < Ni <= N の違いで、繰り返しの回数が 1 回変わります。 1 〜 N の総和で If i > N ThenIf i >= N Then にすると、 N を足さないまま終わってしまいます。 プログラムの誤りで最も多いのが、この境目の 1 個ずれです。 上の Macro1 で試してみてください。

4.2 論理演算子(logical operator)

元資料 15 枚目
演算子意味真になるのは
Andかつ両方とも真のとき
Orまたはどちらか一方でも真のとき
Notでないもとがのとき
Xorどちらか一方だけ真偽が食い違うとき
動かす⑤ 論理演算子の真理値表 A・B を切りかえる

これは第 1 章の論理ゲートと同じものです。 And は AND ゲート、Or は OR ゲート、 Not は NOT ゲート ── プログラムの条件式は、最後にはCPU の中の論理回路で計算されます。 「真=電圧が高い」「偽=低い」というところまで、まっすぐつながっています。

4.3 実際に組み立ててみる

Sub Macro4()
    Dim nen As Integer
    Dim gakusei As Boolean
    Dim kane As Integer

    nen = Cells(1, 2).Value
    gakusei = (Cells(2, 2).Value = "はい")   ' 比較の結果を Boolean に入れる
    kane = Cells(3, 2).Value

    ' 学生割引:学生であって、かつ 25 歳以下
    If gakusei And nen <= 25 Then Cells(5, 1) = "学生割引が使えます" Else Cells(5, 1) = "学生割引は対象外"

    ' 入場できるか:18 歳以上、または 学生
    If nen >= 18 Or gakusei Then Cells(6, 1) = "入場できます" Else Cells(6, 1) = "入場できません"

    ' 足りないか:Not で書く
    If Not (kane >= 5000) Then Cells(7, 1) = "5000 円には足りません"

    ' 条件式そのものを見てみる
    Cells(9, 1) = "gakusei の中身"
    Cells(9, 2) = gakusei
    Cells(10, 1) = "nen <= 25 の値"
    Cells(10, 2) = (nen <= 25)
End Sub

gakusei = (Cells(2,2).Value = "はい") の行に = が 2 つあります。 最初の =代入、 括弧の中の =比較です(第 3 章)。 「比較した結果(True か False)を、変数に入れる」と読んでください。 条件式はそれ自体が値なので、こう書けるのです。

4.4 短絡評価に頼らないこと

VBA の AndOr は、両側を必ず評価します。 たとえば If b <> 0 And a / b > 1 Then と書いても、 b が 0 のときに a / b も計算されてエラーになります (C や Python なら左が偽の時点でやめてくれます。これを短絡評価といいます)。 VBA では次のようにIf を入れ子にして守ります。

If b <> 0 Then
    If a / b > 1 Then Cells(1,1) = "1 より大きい"
End If

※ この教材の処理系は左が偽なら右を見ませんが、 本物の VBA は両方を評価します。上の書き方で覚えてください。

5. まとめ

  1. 流れ図のひし形が判断。そこから戻る矢印が繰り返しになる
  2. GoTo無条件に飛ぶ。使わないのが原則(読めなくなる)
  3. ただし ForDo の正体は「条件を見て飛ぶ」ことだと知っておく
  4. If 条件式 Then 文1 Else 文2 が 1 行の形
  5. End はプログラムの強制終了。End IfEnd Sub とは別物で、使わないほうがよい
  6. 条件式は関係演算子= <> < <= > >=)と 論理演算子And Or Not Xor)で作る
  7. <<= の 1 個ずれが、いちばん多い誤りの原因
  8. VBA の AndOr両側を必ず評価する。0 で割る危険は If の入れ子で守る

章末問題

付録:元資料からの修正一覧

もとにしたのは「情報学入門(VBA)130-2019」全 25 枚です。

元資料この教材種別
GoTo を分岐の最初に紹介し、使うべきでないという但し書きがない ダイクストラ「GoTo 文は有害である」(1968)以来の共通理解を明記。 そのうえでなぜ習うのか(繰り返しの正体・読める書き方の価値)を示し、 同じ計算の For 版と並べた不足
If a < 0 Then EndEnd が何なのか説明がない プログラムの強制終了であり End IfEnd Sub とは別物。 実務では使わないExit Sub を使う)ことも追記不足
「簡単なアルゴリズム」の流れ図が画像 5 枚で、本文に記号の意味がない 記号の表を置き、1 歩ずつたどれる流れ図のモデルにした体裁
関係演算子・論理演算子の表があるが、境目の 1 個ずれ<<=)への注意がない 最も多い誤りとして明示し、総和のプログラムで実際に試せるようにした不足
論理演算子の真理値表が静止画 A・B を切りかえられるモデルにし、第 1 章の論理ゲートと同じものだと結びつけた不足
VBA の AndOr短絡評価をしないことに触れていない §4.4 として追加(0 で割るエラーを避ける If の入れ子)不足
IIf 関数の例が 130 と 135 の両方に載っている(重複) 第 6 章に集約重複

元資料で正しかったこと。 GoTo ラベル の書式、従来型 If の書式 If 条件式 Then 文1 [Else 文2]、12 枚目の 4 つの例 (If k <> 0 Then cnt = cnt + 1 Else cnt = 0 など)、 関係演算子 6 個と論理演算子の表、 「条件式の値は論理型(Boolean)である」という説明 ── いずれも正確です。 12 枚目の例はすべてこのページで実行して確認しました。