t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

Cの学習とVBAとの比較 その3 ~制御文を比べてみる

独習Cの進捗は21%。
ようやく制御文が終わったところ。

独習C

独習C

前回Cのforループが非常に強力であることを紹介した。
thom.hateblo.jp

しかしその他の制御文に関しては、後発のVBAの方が使い勝手が良いなと感じる部分もあるので比較していこうと思う。

まず、VBのDo~LoopにあたるWhile文であるが、Cでは基本的に前判定か後判定かの2種類を選べる。

前判定はこんな感じで、先に条件を満たしているか判定する。

#include <stdio.h>

int main(void)
{
    int n = 1;
    while(n <= 10) {
        printf("%d",n);
        n++;
    }
}

VBAで書くとこうなる。

Sub 前判定()
    Dim i As Integer
    i = 1
    Do While i <= 10
        Debug.Print i
        i = i + 1
    Loop
End Sub

さらにVBAではWhileの代わりにUntil文が使える。

Sub 前判定Until()
    Dim i As Integer
    i = 1
    Do Until i > 10
        Debug.Print i
        i = i + 1
    Loop
End Sub

Whileが条件を満たす間~で、Untilは条件を満たすまでという意味になる。
したがって比較演算子が逆向きになる。

Whileだけあれば記述することはできるが、文脈的にUntilを使うほうが自然なケースもある。
「10以下の場合に繰り返す」というよりも、「10になるまで繰り返す」と言ったほうが言葉として自然に感じるので、割とVBAのUntil文は気に入っている。

ちなみに、Cの後判定はこのように書く。
以下はgetcheでキーボード入力から1文字を読み取り、qならQuit、それ以外なら継続するプログラムである。

#include <stdio.h>
#include <conio.h>

main(void)
{
    char ch;
    do {
        ch = getche();
    } while(ch!='q');
}

前判定だと初回にchにたまたまqが入っていた場合に即座に終了してしまう危険性があり、qを初期化しておかなければならないが、後判定を使うと初回は必ず実行されるのでその心配はない。
VBAでは変数の初期値は決まっているが、C言語では初期化されていない変数の値は不定なので、たまたま最初からqが入っているということがありえるのだ。
(ときおりVBAでも変数宣言のあとに0を代入したり、空文で初期化したりするのを見かけるが、おそらくC言語経験者の癖である。)

Cの例とは別の処理内容になるが、VBAで後判定を書くと以下のようになる。

Sub 後判定()
    Dim i As Integer
    Do
        i = i + 1
    Loop While vbYes = MsgBox(i & "回目です。続けますか", vbYesNo)
End Sub

Until文を使うこともできるが、このケースでは「Noになるまで繰り返す」より「Yesのあいだ繰り返す」の方が自然な気がするのでWhileを使うのが良いと思う。

Sub 後判定Until()
    Dim i As Integer
    Do
        i = i + 1
    Loop Until vbNo = MsgBox(i & "回目です。続けますか", vbYesNo)
End Sub

さて、次はbreak文について。
Cのbreak文に相当するVBAの命令はExit Forあるいは、Exit Doである。
breakが単純に一つ外のループに脱出するのに対し、VBAでは明示的にForを抜けるのかDoを抜けるのかあるいはSubを抜けるのかなどを指定できる。

ちょっと変わったところでは、C言語にはContinueという文がある。
ループの途中で抜けるのではなく、強制的に次の周回に入る命令だ。

VBAでContinue文を模倣すると、こんな感じになる。

Sub Continue文の真似事()
    Do
        pw = InputBox("暗証番号を入力してください。")
        If Not pw = InputBox("確認のためもう一度入力してください。") Then
            MsgBox "一致しません"
            GoTo Continue
        End If
        Debug.Print pw; "を登録しました。"
        If vbNo = MsgBox("継続しますか?", vbYesNo) Then Exit Do
Continue:
    Loop
End Sub

上記の処理では、2回入力された暗証番号が不一致の場合、GoTo Continueで強制的にループの終端にジャンプさせている。
便利なテクニックなので、限定的なGoToの使い方としてはアリだと思う。

最後にVBAのSelect文に相当する、C言語のswitch文というのがある。
ただCのswitchは文字型かint型にしか使えず、さらに等価比較しかできないとのこと。
そこはさすがに後発のVBAの方がスマートである。

VBAのSelectではTo句で範囲指定、カンマで複数指定、Is句で大小比較ができる。

Sub Selectテスト()
    For i = 1 To 15
        Select Case i
        Case 1 To 10
            Debug.Print "A"
        Case 11, 13, 15
            Debug.Print "B"
        Case Is > 10
            Debug.Print "C"
        End Select
    Next
End Sub

また、C言語のCaseは定数でないといけないが、VBAではCaseに変数を指定しても問題ない。
※過去記事にSelectの比較テクニックを書いたので興味があればこちらも参照してください。
thom.hateblo.jp

最後に制御文についてCとVBAの比較まとめ。

Cの長所は柔軟なForとContinue文の存在。
VBAの長所は状況に応じてUntil文が使えること、Exitで何を抜けるかを指定できる点、融通のきくSelect文。

といったところで今日はお終い。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。