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未満の数値しか試していなければ、これで出来た!と思い込んでしまうのです。
人間の世界の言語では、文法など少々アバウトでも通じたりしますが、コンピュータにアバウトは通じません。
ブラウザの戻るボタンで戻ってください。