コンパイルエラーを出したくない(C言語)

8日目 ← : → 10日目

どうも2年生のcrispydounutです。HNに深い意味はありません。
色々不慣れですがよろしくお願いします。
実は僕は1世代前の広報担当だったりするのですが何もしてなかったです(てへぺろ)
つい最近世代交代して、今年の広報担当はやる気があるようでブログに活気が出ていていいですね。
しかも1年生に技術的に優秀な人が多くて頼もしい限りです(そういう人たちはいつ勉強してきたのでしょうか…)。とりあえず1年生の間だけでも技術の継承がなされて欲しい今日この頃です。

さて本題に移りましょう。僕は情報工学科なのですが、その影響で細々としたC言語のプログラムを一定数書いてきました。そこで、コンパイルエラーなどプログラミングのミスを多くしてきたので、備忘録もかねて紹介したいと思います。早速ですが、下のコードの間違い探しをしてみましょう。なお、コンパイルエラーが出ない間違いもあります。わざとらしいコードになっているというのは百も承知ですが、冗長になっても仕方ないので(ということで)。
これは自然数nを入力し、n!, (n-1)!, … , 1!を出力してる(つもり)のプログラムです。以下、面倒なので入力に不備はないものとします。あと、WordPressの都合上、半角スペースがなくなってしまう事件が起きることが予想されるので、今回はスペースは気にしないでください(暴論)。解決しました。机上デバッグをしてみましょう。


#include <stdio.h>

#define FACT(n) (n == 0 ? 1 : n * FACT(n - 1))

int main(void)
{
    unsigned int n, i;
    printf("Input n : ");
    scanf("%d", &n);
    for  (i = n; i > 0; i--)  {
        printf("%d! = %d\n", n, FACT(n));
    }
    return 0;
}

間違えているところは(多分)2か所あります。
まず1か所目はFACT(n)の部分。関数形式のマクロでは再帰関数は使えません。マクロの置き換わり方を考えれば当然ですね(?)。2か所目はfor文のi > 0の部分。iが符号なし整数と宣言されているのでこれでは無限ループに陥ってしまいます。この罠に1回友達が引っかかっていて、僕も気づけませんでした。無限ループに陥ってしまうのはよくあることですが、パソコンに優しくなさそうなのでループの条件には十分気を付けましょう。次のプログラムに移ります。

これは自然数nを入力させ、n個の素数を表示させるプログラムです。malloc関数でdataのメモリを確保し、素数列を入れます。また、data[0]に予め最小の素数である2を格納しています。因みにprinumは素数候補となる数値です。これ以上詳しい説明はなくても分かる様な簡単な間違いなので割愛します(もっとも、かなり強引な部分があるので説明したくないです笑)。簡単な間違い≠すぐに見つかる間違いだと思うので、頑張って見つけてみてください。間違いは2箇所あります。繰り返しますが、コンパイルエラーが出るところとは限らないです。


#include <stdio.h>

int main(void)
{
    int *data, i, j;
    int prinum = 3;
    int n;

    printf("Input n : ");
    scanf("%d", &n);

    data = malloc(sizeof(int) * n);
    data[0] = 2;
    printf("Prime Number 1 : %d\n", data[0]);

    for (i = 1; i < n; i++) {
        for (j = 0;j < i && prinum * prinum >= data[j] * data[j];) {
            switch (prinum % data[j]) {
            case 0:
                j = 0;
                prinum++;
                break;
            defalt:
                j++;
                break;
            }
        }
        data[i] = prinum;
        printf("Prime Number %d : %d\n", i + 1, data[i]);
        prinum++;
    }
    free(data);
    return 0;
}

見つかりましたか?
1つ目はmain関数の前にあります。
そう、stdlib.hがインクルードされていませんね。malloc関数やfree関数、exit関数などを使うときは忘れずにインクルードしましょう。
2つ目は明らかに無理やり詰め込んだswitch文の中にあります。
defalt:部分です。正しくはdefault:ですね笑。なぜこんな間違いを紹介したか分かりますか???
ヒントはしつこくしていた但し書きです。つまり、コンパイルエラーが出ないからです。おそらくgoto文のラベルとして認識されているからです。しっかりとオプションで指定したりしていたら警告だしてくれたと思うんですが、僕が作っていた時は警告も出なかったため、なかなか気づきませんでした。まさかそんな間違いをしているとは思わなかったですし…。と言うわけでこの記事の本題は終わりです。

それなりに量があると見せかけてほとんどがソースコードという本記事ですが、いかがでしたでしょうか?なんか「そこかよ!」って感じのイライラするような内容だったような気がします(まあプログラマってきっとイライラとの格闘なんでしょうし…….)。まあ最初で言った通り、初めてで不慣れなんです……..。まあちょっとでも興味を持って読んでいたいただけたなら幸いです。ここまで読んでいただきありがとうございました。

お わ り

広告

コンパイルエラーを出したくない(C言語)」への2件のフィードバック

  1. ピンバック: かわロボ 進捗状況 | 慶應義塾大学ロボット技術研究会

  2. ピンバック: Unityでマイクロマウスをシミュレートしたい | 慶應義塾大学ロボット技術研究会

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中