t-hom’s diary

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

Cの学習とVBAとの比較

先日購入した以下書籍にて、C言語の学習中。

独習C

独習C

のんびりやっているので、進捗はまだ15%くらい。

円、長方形、三角形のいずれかを選択して面積を求めるプログラムを作れとのことで、やってみた。
switch文を使いたいところであるが、まだ読んだ範囲には登場せず、if-else-if階段を使えとの指示である。
いちおう、素直にこれまでのページに登場した知識のみで作成。

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

int main(void)
{
    char ch;
    float result;
    float num, num2;
    printf("input c,r,t\n=>"); /* Circle, Rectangle, Triangleの頭文字 */
    ch = getche();
    if(ch == 'c'){
        printf("\ninput diameter\n=>");
        scanf("%f",&num);
        result = (num / 2.0) * (num / 2.0) * 3.14;
    } else if (ch == 'r') {
        printf("\ninput height\n=>");
        scanf("%f",&num);
        printf("\ninput width\n=>");
        scanf("%f",&num2);
        result = num * num2;
    } else if (ch == 't') {
        printf("\ninput height\n=>");
        scanf("%f",&num);
        printf("\ninput width\n=>");
        scanf("%f",&num2);
        result = num * num2 / 2;
    } else {
        result = 0;
    }
    printf("%f", result);
    return 0;
}

以下の部分については、べき乗のやり方がわからなかったのでVBと同じ(^)を使ってみたところエラーになった。

result = (num / 2.0) * (num / 2.0) * 3.14;

調べてみると、べき乗の演算子は存在せず、mathライブラリのpowを使うとか。
この点は後発のVBAの方が優れている。

同じプログラムをVBAでも書いてみた。

Sub main()
    Dim ch As String * 1    '固定長String型
    Dim result As Single    '単精度浮動小数点型
    Dim num As Single, num2 As Single
    ch = InputBox("input c,r,t")
    If ch = "c" Then
        num = InputBox("input diameter")
        result = (num / 2#) ^ 2# * 3.14
    ElseIf ch = "r" Then
        num = InputBox("input height")
        num2 = InputBox("input width")
        result = num * num2
    ElseIf ch = "t" Then
        num = InputBox("input height")
        num2 = InputBox("input width")
        result = num * num2 / 2
    Else
        result = 0
    End If
    MsgBox result
End Sub

C言語には文字列型は存在せず、文字列は文字型(char)の配列である。
一方でVBAには文字型は存在せず、1文字だけ入る変数を用意するなら固定長String型を使う。
※Byte型でも良いが、VBAでは文字の扱いが2バイトなので面倒くさい。

長いことVBAばかりやっているとC言語の書き始めについDimと書いてしまう。
VBAの変数宣言は「Dim 変数名 As 型名」であるが、Cの変数宣言は単に「型名 変数名」とすれば良い。

VBAの変数宣言は、宣言ステートメントであることが明瞭で、読むときにわかりやすい。
一方、Cの変数宣言は必要最小限で記述するときに合理的である。
慣れの問題もあるけれど、一長一短だ。こういう言語間の違いは面白い。

また、Cでは代入演算子が=、比較演算子(等価)が==である。
VBAでは両方=で、文脈で区別される。

これはCのやり方が優れていると思う。
Cでは=が代入であることが明確なので、次のように記述するとa,b,c,dすべてに10が入る。

#include <stdio.h>

int main(void)
{
    int a,b,c,d;
    a = b = c = d = 10;
    printf("%d,%d,%d,%d\n",a,b,c,d);
    return 0;
}

まずdに10が入り、dの結果(10)がcに入り、cの結果(10)がbに入り、bの結果(10)がaに入る。
右から左に流れるように値が代入されていくのだ。

同じようにVBAでやってみよう。

Sub main()
    Dim a As Integer, b As Integer, c As Integer, d As Integer
    a = b = c = d = 10
    Debug.Print a, b, c, d
End Sub

結果はa,b,c,dすべて0である。
なぜかというと、最初の=は代入、あとの=は比較演算子として判断されてしまうから。

おそらく左から評価される次の式と等価だと思う。
a = (((b = c) = d) = 10)

まず初期値が0なので、b=cの比較はTrue(-1)
そのTrue(-1)とdが比較されてFalse(0)
次にFalse(0)と10が比較されてFalse(0)
その0がaに代入されて完了。

この点では比較と代入を明示的に使い分けられるCの方が優れている。

もうひとつ、C言語で驚いたのは、Cのelse ifは、単にelse文に続いてif文を書く場合のスタイルのひとつでしかないということ。
たとえば以下2つのコードは、単に改行位置とインデントが異なるだけで、文法的には完全に等価である。

#include <stdio.h>
int main(void)
{
    char ch = 't';
    if(ch=='c') {
        printf("Circle\n");
    } else if (ch == 'r') {
        printf("Rectangle\n");
    } else if (ch == 't') {
        printf("Triangle\n");
    } else {
        printf("Other\n");
    }
    return 0;
}
#include <stdio.h>
int main(void)
{
    char ch = 't';
    if(ch=='c') {
        printf("Circle\n");
    }
    else
        if (ch == 'r') {
            printf("Rectangle\n");
        }
        else
            if (ch == 't') {
                printf("Triangle\n");
            }
            else {
                printf("Other\n");
            }
    return 0;
}

C言語には「else if」という機能は存在せず、あくまで単品のifとelseがあるだけだ。
つまり、Cの「else if」とは、単にネストによるインデントが深くなることを避けるための記述テクニックである。
一方VBAのElseIfは、それ自体が文法の一部である。

ひょっとして、else ifテクニックの使用が一般的になったため、後発の言語で正式に文法として取り入れられたのだろうか。
このあたり、言語の進化を感じることができて面白い。

さて、次はfor文の学習である。
Cのfor文はVBAよりも強力らしいので楽しみだ。
次回もVBAと比較しながら紹介していきたいと思う。

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