★if文でよくある間違い★


if文は、プログラム言語では、最初のうちからずっと後々まで使う命令です。

使い始めのころに、よくある間違いを紹介しておきます。


<sample program col008-01>

#include <stdio.h>

int main(void)
{
    int input;

    printf("整数を入力してください:");

    scanf("%d", &input);

    if (input > 0); {
        printf("入力した数は正の数です。\n");
    }

    return 0;
}

これは、コンパイルしてもエラーにならず、きちんと実行できます。

が、負の数やゼロを入力しても、「入力した数は正の数です。」と表示されます。

どこが、間違っているか分かりますか?


if文の後ろにある「{」の前を見てください。

不自然?な「;」があります。

これまでの解答例では、このようなところに「;」はありませんでした。

当然、意識してつけたものではなく、無意識につけた「;」です。

しかし、これが分かりにくいエラーなのです。

理由はいくつかあります。

本人は、正しく入力したつもりなので、まず「ぱっ」と見て判別できません。

また、プログラムの検証(テスト)の際に、横着をして、「正しいデータ」しか入力しないこともしばしばありますので、発見できないことが多いのです。

プログラムを検証する場合は、様々なデータ(といってもやたらめったらという訳ではありませんが)を入力してみる必要があります。

「整数」を入力するのであれば、最低でも「負の数」「ゼロ」「正の数」は入力しなければなりません。

※実際に公開するようなソフトであればこれだけでは駄目ですが・・・今はscanfを使っているので、アルファベット等は考えていません。


また、別の観点から見ると、「;」の使い方を理解していないことも原因の一つかも知れません。

これまで、きちんと説明していなかったので、ここで説明します。

C言語では、文の終わりを「;」で表現します。

しかし、<sample program col008-01>を見ても分かるとおり、いくつかの文には「;」が付いていません

  #include <stdio.h> の後ろ

  int main(void) の後ろ

  { の後ろ

  } の後ろ

#で始まる文は「プリプロセッサ」といって、「;」を付けません。(プリプロセッサについては後述します)

int main(void) は「関数定義」といって、これも「;」を付けません。(関数についても後述します)

{ は「ブロックの開始」です。

} は「ブロックの終了」です。

今回はこの部分が問題ですので、ブロックについて書きます。


・ブロック


ブロックの説明をしようとすると「構造化プログラミング」とか説明しなければならなくなりますが、ここでは説明を省きます。

ブロックとは、「何らかの塊」と考えてください。

では、次の例を見てください。


<sample program col008-02>

#include <stdio.h>

int main(void)
{                                /* main(関数)のブロック開始 */
    int data = 10;

    if (data > 5) {              /* if文のブロック開始 */
        printf("OK\n");
    }                            /* if文のブロック終了 */

    {                            /* ブロック開始 */
        int data2 = 3;

        printf("%d\n", data2);
    }                            /* ブロック終了 */

    return 0;
}                                /* main(関数)のブロック終了 */

まず、「main(関数)のブロック開始〜終了」は、どこからどこまでがmainというプログラムなのかを表しています。

「if文のブロック開始〜終了」は、どこからどこまでが、ifの条件が成立した時の処理なのかを表しています。

また、何も無いところでもブロックを作ることも出来ます。「ブロックの開始〜終了」

※初心者のうちに使うことはまずありませんが・・・


ここで、見ておいて欲しいことがさらにあります。

C言語では、変数の宣言はブロックの開始直後でしか出来ないということです。

逆に、<sample program col008-02>のように、何も無いところで作った「ブロック開始」の直後の変数宣言はエラーになりません。

※このことについては、スコープのところに書くつもりです。


さて、では、最初の疑問に戻ります。

ifの後に「;」があるとどのような動きになるのでしょうか?

<sample program col008-01>を少し書き換えて見ましょう。


<sample program col008-03>

#include <stdio.h>

int main(void)
{
    int input;

    printf("整数を入力してください:");

    scanf("%d", &input);

    if (input > 0);

    {
        printf("入力した数は正の数です。\n");
    }

    return 0;
}

「;」は文の終わりですから、if文の後に「;」をつけると、そこで文が終わります。

つまり、このif文は、成立した時も、不成立の時も「何もしない」if文となります。

比較はしますが、処理はしないのです。

で、行を分けましたが、「printf("入力した数は正の数です。\n");」という文の前に「{ 」があり、後ろに「 }」があります。

これは、上で書いた「ブロック」になります。

特別に何か行っているわけではありませんので、必ず「printf("入力した数は正の数です。\n");」が実行されます。

というわけで、何を入力しても、メッセージが表示されるのです。


・条件


次に、条件の書き方です。

何度も書きましたが、if (data1 > data2 > data3)のように一度に3つ以上のデータを比較することは出来ません。(と考えておいてください)

出来ないのであれば、と色々と創作される方も多いのですが、エラーが出なくても、文法的に間違っていれば、正しい答えは出ません。

例えば、「入力した数値が1〜100未満の範囲であるかどうか調べる」プログラムで、


<sample program col008-04>

#include <stdio.h>

int main(void)
{
    int input;

    printf("整数を入力してください:");

    scanf("%d", &input);

    if (input > 0, input < 100) {
        printf("入力した数は正の数です。\n");
    }

    return 0;
}

のように、「,」を使って条件をつなげたりすることを見たことが(多々)あります。


このプログラムの実行結果は、100未満の数値を入力すると(負の数であろうが)「入力した数は正の数です。」と表示されます。

「,」の前の「input > 0」は無視されています。(実際に実行してみてくださいね)

勝手に新文法を作っても、正しく動きません。

このようなプログラムを作成した場合にも、1〜100未満の数値しか試していなければ、これで出来た!と思い込んでしまうのです。


人間の世界の言語では、文法など少々アバウトでも通じたりしますが、コンピュータにアバウトは通じません。


ブラウザの戻るボタンで戻ってください。