GoTo)と条件分岐(If)の違いを言えるGoTo を使わないほうがよいのかを説明できるIf 〜 Then 〜 Else を書けるここまでのプログラムは上から下へ一直線でした。 これからは枝分かれと後戻りが入ります。 その形を表すのが流れ図(フローチャート)です。
| 記号 | 意味 |
|---|---|
| 角の丸い四角 | 開始・終了 |
| 長方形 | 処理(計算や代入) |
| ひし形 | 判断(条件によって行き先が分かれる) |
| 矢印 | 流れの向き |
元資料 9 枚目の課題「1〜N までの総和を求める」を流れ図で書くと、こうなります。
ひし形(i <= N ?)で「はい」なら下へ、「いいえ」なら外へ抜けます。
そして下まで行ったらひし形の上に戻る ── これが繰り返しの正体です。
この「戻る」を作る道具が 2 つあります。
1 つが GoTo(この章)、もう 1 つが For や Do(第 7・8 章)です。
元資料 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 つ理由があります。
For や Do は、機械語のレベルでは結局
「条件を見て、飛ぶ」に翻訳されます(第 1 章の mov・add の世界には
For はありません)。
For は GoTo を安全な形に閉じ込めた道具だと分かると、見通しがよくなります上のプログラムは、第 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
元資料 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 End の End は
「プログラムをここで終える」という命令です。
End If(If の終わり)や End Sub(手続きの終わり)とは別のもので、
同じ単語なので混同しやすいところです。
なお、実際のプログラムで End は使わないほうがよいです。
どこからでも強制終了できてしまい、後片づけが行われません
(第 9 章の Exit Sub なら、呼び出した側に戻ってから続きを処理できます)。
上のプログラムで a = 5 を a = -5 に変えて実行すると、
5 行目のメッセージが出ないまま止まるのが確かめられます。
条件式の値は真(True)か偽(False)のどちらかです。 この型を論理型(Boolean 型)といいます(第 3 章)。 条件式を組み立てるのに使うのが、次の 2 種類の演算子です。
| 演算子 | 意味 | 使い方 |
|---|---|---|
= | 2 つの値が等しい | X = Y |
<> | 2 つの値が等しくない | X <> Y |
< | 左の値が右の値より小さい | X < Y - 5 |
<= | 左の値が右の値以下 | X <= 100 |
> | 左の値が右の値より大きい | X > Y |
>= | 左の値が右の値以上 | X >= Y |
「より小さい」と「以下」を区別してください。
i < N と i <= N の違いで、繰り返しの回数が 1 回変わります。
1 〜 N の総和で If i > N Then を If i >= N Then にすると、
N を足さないまま終わってしまいます。
プログラムの誤りで最も多いのが、この境目の 1 個ずれです。
上の Macro1 で試してみてください。
| 演算子 | 意味 | 真になるのは |
|---|---|---|
And | かつ | 両方とも真のとき |
Or | または | どちらか一方でも真のとき |
Not | でない | もとが偽のとき |
Xor | どちらか一方だけ | 真偽が食い違うとき |
これは第 1 章の論理ゲートと同じものです。
And は AND ゲート、Or は OR ゲート、
Not は NOT ゲート ──
プログラムの条件式は、最後にはCPU の中の論理回路で計算されます。
「真=電圧が高い」「偽=低い」というところまで、まっすぐつながっています。
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)を、変数に入れる」と読んでください。
条件式はそれ自体が値なので、こう書けるのです。
VBA の And と Or は、両側を必ず評価します。
たとえば 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 は両方を評価します。上の書き方で覚えてください。
GoTo は無条件に飛ぶ。使わないのが原則(読めなくなる)For や Do の正体は「条件を見て飛ぶ」ことだと知っておくIf 条件式 Then 文1 Else 文2 が 1 行の形End はプログラムの強制終了。End If・End Sub とは別物で、使わないほうがよい= <> < <= > >=)と
論理演算子(And Or Not Xor)で作る< と <= の 1 個ずれが、いちばん多い誤りの原因And・Or は両側を必ず評価する。0 で割る危険は If の入れ子で守るもとにしたのは「情報学入門(VBA)130-2019」全 25 枚です。
| 元資料 | この教材 | 種別 |
|---|---|---|
GoTo を分岐の最初に紹介し、使うべきでないという但し書きがない |
ダイクストラ「GoTo 文は有害である」(1968)以来の共通理解を明記。
そのうえでなぜ習うのか(繰り返しの正体・読める書き方の価値)を示し、
同じ計算の For 版と並べた | 不足 |
If a < 0 Then End の End が何なのか説明がない |
プログラムの強制終了であり End If・End Sub とは別物。
実務では使わない(Exit Sub を使う)ことも追記 | 不足 |
| 「簡単なアルゴリズム」の流れ図が画像 5 枚で、本文に記号の意味がない | 記号の表を置き、1 歩ずつたどれる流れ図のモデルにした | 体裁 |
関係演算子・論理演算子の表があるが、境目の 1 個ずれ(< と <=)への注意がない |
最も多い誤りとして明示し、総和のプログラムで実際に試せるようにした | 不足 |
| 論理演算子の真理値表が静止画 | A・B を切りかえられるモデルにし、第 1 章の論理ゲートと同じものだと結びつけた | 不足 |
VBA の And・Or が短絡評価をしないことに触れていない |
§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 枚目の例はすべてこのページで実行して確認しました。