プログラミングの基本である条件分岐や繰り返し処理をCで学びます。
前回は、開発環境の使い方について説明しました。これから何度も、Cでプログラムを書いたり、読んだりします。そのときにいつも役立つ便利な方法について解説しましたので、まだ開発環境を使いこなせていないという方は、今後の記事を読む前にぜひ前回の記事をおさらいしてみて下さい。
今回は、プログラムの実行(処理の流れ)を制御するための文を説明します。条件によってプログラムの実行を制御することは、プログラムに欠かせない要素です。Cの制御に関する文法を理解して使いこなせるようになれば、文字通りプログラムの実行を思ったように制御できますので、しっかり動きを確認しましょう。
これまでのプログラムは上から下へ必ず順番に実行され、最後の文の実行が終了するとプログラムの実行が終了しました。if文を使うと、この実行の流れを変えることができます。
if文の書式は次のようになっています。
if (制御式) 文
制御式についてはこのあとに詳しく説明しますが、簡単に言うと、後ろにある文を実行する条件を記述したものです。制御式の値が真であれば文を実行しますし、そうでなければ文を実行しません。
「真(しん)である」とは、条件が成立していることを言います。数値の1同士を比較した「1 == 1(1と1は等しい)」は真ですし、1と2を比較した「1 == 2(1と2は等しい)」は真ではありません。真ではないことを「偽(ぎ)である」とも言います。
if文の後ろには、制御式が真のときに実行される文を書きます。そしてさらにその後ろに、制御式が真ではないときに実行される文を書くこともできます。これは次のように書きます。
if (制御式) 文 else 文
このようにif文を利用することによって、条件によって実行の流れを制御することができます。
制御式は条件を記述するための式です。次のいずれかの条件を満たす式は、条件式としてif文に使用することができます。
【*1】ポインタ型については今後の連載で説明する予定です。
これらはつまり、制御式の評価結果は、「整数型」「浮動小数点型」「ポインタ型」のいずれかの値を持つということを言っています。例えば、式「1 + 1」は整数型を持つので、制御式です。「1.2 + 1.3」も浮動小数点型となりますので、同じように制御式となります。
そして、これらの値が「0」(数字のゼロ)と等しくなければ真、「0」と等しければ偽となります。つまり制御式を短く書くと、次のようになります。
if (1) /* 1は0と等しくない(=真)ので、ここに書いた文は実行されます。 */ if (2) /* 2も0と等しくない(=真)ので、ここに書いた文は実行されます。 */ if (0) /* 0は偽ですので、ここに書いた文は実行されません。 */
このように制御式には、数値や四則演算を使った式を書くことができます。もちろん、「制御式の結果が真ならば後ろの文が実行される」、と覚えても問題ありませんが、一歩踏み込んで「0以外ならば実行される」と覚えておくと便利な場面がたくさんあります。
しかしながら、制御式として、「AとBが等しいか」や「AよりBの方が大きいか」といった判定条件を書くことも多いでしょう。このような条件を記述するために、等価演算子、関係演算子、論理演算子といった演算子が用意されています。次に、これらの演算子について説明します。
等価演算子は、2つのオペランドが等しいか、あるいは等しくないかを判定します。それぞれ“==”と“!=”という演算子で、演算結果は1(真)または0(偽)になります。
演算子 | 演算結果 | |
---|---|---|
a == b | オペランドaとオペランドbが等しければ1(真)、そうでなければ0(偽) | |
a != b | オペランドaとオペランドbが等しければ0(偽)、そうでなければ1(真) | |
if (0 == 0) /* 1(真)となり、ここに書いた文は実行されます。 */ if (0 == 1) /* 0(偽)となり、ここに書いた文は実行されません。 */ if (0 != 0) /* 0(偽)となり、ここに書いた文は実行されません。 */ if (0 != 1) /* 1(真)となり、ここに書いた文は実行されます。 */
等価演算子はif文と組み合わせなければ使えない、ということはありません。他の演算子と同じように、式を書くことができるところに使うことができます。
int f = (0 == 1);
int型の変数fの値は、0になります。以降に説明する関係演算子や論理演算子も、同じようにどこにでも式として書くことができます。
「int a=1; if (a==1) printf("a==1\n");」のようなプログラムを書きたいとします。ところが、タイプミスをして「int a=1; if (a=1) printf("a==1\n");」と書いてしまったとしましょう。「(a==1)」を「(a=1)」と間違えてしまったのですが、このプログラムはコンパイルできますし、出力されたプログラムは実行できます。これは、「a=1」の評価結果が「1」となるためです。等価演算子を打ち間違えて代入演算子にしてしまったことをコンパイル時に検出するには「(1==a)」のようにリテラルを左辺へ書くようにするという方法があります。ただし、「if (a==1) ... 」を「aが1なら ... する」と読んでいると「if (1==a) ... 」は「1がaなら ... する」となり、ものすごく違和感があるということで、この書き方を嫌う人もいます。個人的には「1==a」は「1とaが等しい」と読んでいるので、「if (1==a) ... 」は「1とaが等しいなら ... する」となり、それほど違和感を持っていません。この手の間違いはコンパイル時に見つからないと意外と見つけるのが大変なので、この程度の工夫で対応できるなら活用した方が楽だと考えています。読者の皆さんは、どちらでしょう。
関係演算子は、2つのオペランドのうち、どちらか一方が大きい、あるいは小さいことを判定します。演算結果はやはり、1(真)または0(偽)になります。
演算子 | 演算結果 | |
---|---|---|
a < b | オペランドaがオペランドbより小さければ1(真)、そうでなければ0(偽) | |
a > b | オペランドaがオペランドbより大きければ1(真)、そうでなければ0(偽) | |
a <= b | オペランドaがオペランドbより小さいか等しければ1(真)、そうでなければ0(偽) | |
a >= b | オペランドaがオペランドbより大きいか等しければ1(真)、そうでなければ0(偽) | |
なお、“=>”や“=<”のように等号を先に書くことは、そのような演算子が存在しないためできません。
論理演算子は、オペランドを2つとるものと、1つだけとるものがあります。
演算子 | 演算結果 | |
---|---|---|
a && b | オペランドaとオペランドbの両方が0と等しくなければ1(真)、そうでなければ0(偽) | |
a || b | オペランドaとオペランドbのいずれかが0と等しくなければ1(真)、そうでなければ0(偽) | |
! a | オペランドaが0と等しければ1(真)、そうでなければ0(偽) | |
ひねくれたような説明に見えるかもしれませんが、言っていることは明確です。“&&”は、いずれのオペランドも真であったときに、結果が真となります。「〜、かつ(and)、〜」と言い換えると覚えやすいでしょう。
同じように“||”は、どちらかのオペランドが真であったときに、結果が真となります。つまり、「〜、または(or)、〜」と言い換えられます。
オペランドを1つしか取らない“!”は、真と偽を入れ替えます。つまり、オペランドが真であれば偽、偽であれば真となります。
Copyright © ITmedia, Inc. All Rights Reserved.