プログラムでは、ある入力が与えられた時に処理をしたいということがあります。
ここでは、そのような処理に必要な条件分岐について説明します。
条件分岐
C言語には、入力などの条件によって、処理を分けるために、if 文という条件分岐の方法があります。
このソースコードでは、数字の5が入力されたら「入力された数字は5です」、5以外の数字が入力されたら「入力された数字は5ではありません」と表示します。
#include <stdio.h>
int main(void)
{
int a;
scanf("%d", &a);
if (a == 5) {
printf("入力された数字は5です\n");
}
else {
printf("入力された数字は5ではありません\n");
}
return 0;
}
見て欲しいのは、「if (a == 5)」 の部分です。ここで、入力された数字が代入されている変数aの値が5であるかを判定しています。
判定して、5であれば中かっこ({ }) の中のプログラムが実行されます。
そして、その後の「else」の部分は、if の条件に当てはまらなかった場合、中かっこの中のプログラムが実行されます。
if の後のかっこで囲んでいる内容は、条件式と呼ばれるものです。
この条件式が成立すると、中かっこの中のプログラムが実行されます。
else は、if 文の条件式に当てはまらなかった場合、実行される処理を書くものです。
else を書くのであれば、if の中かっこの後に必ず書く必要がありますが、if の後に必ず書くものというわけではないので、else の記述は無くても構いません。
条件式
上のソースコード中の条件式では、等しいという意味で「==」という=の記号を2つ使いました。これは、足し算や引き算などに使う+や-の記号と同じで、演算子と呼ばれるものです。
== を含めて、条件式で使うことが多い演算子を紹介します。
演算子 | 意味 |
---|---|
== | 等しい |
< | より大きい |
> | より小さい |
<= | 以上 |
>= | 以下 |
条件式はこれらを使って組み立てていきます。
さらに、3以上5以下のような条件式を組み立てるには、これらの演算子だけでは足りません。
そこで、これらの条件式の他に演算子の結果を組み合わせるための演算子があります。
演算子 | 意味 |
---|---|
&& | 論理積 |
< | 論理和 |
論理積とは、a && b のような条件式の場合、aの結果とbの結果が真(正しい)の場合に真となります。真の反対は、偽(間違い)です。なので、3 <= a && a <= 5 とすれば、aが3以上5以下の時に真となる条件式になります。
3 <= a < = 5 のように書くことはできません。
論理和とは、a || b のような条件式の場合、aの結果とbの結果の内どちらか一つでも真となるようなような場合に真となります。なので、 a == 3 || a == 5 とすれば、aが3か5の時に真となる条件式になります。
さらに、真偽を判定させる演算子があります。
演算子 | 意味 |
---|---|
! | 否定 |
aが3以上5以下以外の時に真としたい場合は、「!(3 <= && a <= 5)」のように、かっこで囲って、その前に「!」を書きます。
条件式は、主にこれらを組み合わせて作っていきます。
真と偽
== や < などは演算子ということを既に説明しました。
演算子ということなので、+ や - のように、計算をしています。
では、その計算とはどのようなものなのかというと、a == b であればaとbが等しい時に、a < b であれば a が bよりも小さい時に、結果が0以外の数字となります。逆にこれらを満たさないとき結果は0となります。
これらがどのようなことを示すのかというと、if 文のかっこの中の条件式の部分は、最終的に0か0以外を判定しているということです。
なので、if 文をこのように、条件式に0以外の数字を直接当てはめれば必ず実行されます。
#include <stdio.h>
int main(void)
{
if (1) {
printf("必ず実行されます\n");
}
return 0;
}
逆に、0とすると絶対に実行されません。
このように、C言語では条件式において、0か0以外の2つしか見ていません。
これは、C言語の根本に関わることなので、覚えておきましょう。
複雑な条件分岐
ここからは、複雑な条件分岐と条件式を扱っていきます。
例えば、入力された2つの数字の内、ひとつめが3または5かつ、ふたつめが4または6のとき「こんにちは」と表示するプログラムを考えます。
このような場合、ソースコードはこのようになります。
#include <stdio.h>
int main(void)
{
int a, b;
scanf("%d%d", &a, &b);
if ((a == 3 || a == 5) && (b == 4 || b == 6)) {
printf("こんにちは\n");
}
return 0;
}
気をつけて欲しいのが、演算子の優先順位です。
演算子ということなので、四則演算の時のように、足し算や引き算よりも掛け算や割り算の方が優先されるというようなことがあります。
今回の場合、論理和よりも論理積が優先されるため、論理和の演算をかっこで囲って、先に計算しておくようにしてあります。
もしかっこがなかった場合は、「a == 3 || (a == 5 && b == 4) || b == 6」のようにかっこが付いているのと同じになります。
さらに、この場合では、if 文をふたつ使うことによっても、同じことができます。
#include <stdio.h>
int main(void)
{
int a, b;
scanf("%d%d", &a, &b);
if (a == 3 || a == 5) {
if (b == 4 || b == 6) {
printf("こんにちは\n");
}
}
return 0;
}
一般的には、if 文の中に if 文があるようなソースコードは嫌われるため、このように書くことは多くありません。
if 文を二つ並べて使う以外にも、else の後にも if を繋げることができます。
#include <stdio.h>
int main(void)
{
int a, b;
scanf("%d%d", &a, &b);
if (a == 3 || a == 5) {
printf("おはよう\n");
} else if (b == 4 || b == 6) {
printf("こんにちは\n");
}
return 0;
}
こうすると、変数a の値が3か5の時には「おはよう」と表示し、4か6の時には「こんにちは」と表示します。
中かっこ
今まで、if () { } や else { } のように、中かっこを使用していました。
これらの中かっこには、意味があります。
実は、今まで紹介したソースコードでは中かっこが無くても正しく実行されます。
なので、中かっこがないと正しく動かない例を示しておきます。
#include <stdio.h>
int main(void)
{
int a;
scanf("%d", &a);
if (a == 5)
printf("入力された数字を発表します\n");
printf("入力された数字は5です\n");
return 0;
}
実行中に5以外の数字を入力して見ましょう。
そうすると、「入力された数字は5です」と表示されます。
5の数字を入力した場合は「入力された数字を発表します」も一緒に表示されます。
これは、中かっこがない場合だと、if や else の後のひとつの文しか実行されないということを表しています。
文とは、処理を示すものであり、条件分岐のためのif文や代入のための代入文などいくつかあり、最後がセミコロン(;)で終わっています。
(if 文は、別の文のセミコロンがあることで文となっています)
ひとつの文しか実行されないということで、「printf(“入力された数字は5です\n”);」は、if文の後のふたつめの文なので、a が 5 以外の時にも実行されます。
このことから、ミスを少なくするために、なるべく中かっこはつけておくようにしましょう。
switch文
if 文の他にも、条件分岐のための switch 文というものがあります。
switch 文の例として、うるう年ではない年の、月ごとの日にち数を答えるソースコードを用意しました。
#include <stdio.h>
int main(void)
{
int month;
scanf("%d", &month);
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
printf("31日\n");
break;
case 4:
case 6:
case 9:
case 11:
printf("30日\n");
break;
case 2:
printf("28日\n");
break;
default:
printf("1から12の数字を入力してください\n");
}
return 0;
}
switch文は、case の部分で値を判定しています。case は、case のあとに比較したい値を書いてその後に:を書きます。
注意として、caseでの判定は「等しい」という判定しかできず、以上や以下などの判定はできません。
case の比較は switch の後のかっこの中身と比較します。今回の場合は入力された数字が入っているmonthという変数です。
最初、case 1: case 3: などのように、case がいくつも続き、その後に「printf(“31日\n”);」とあります。
これは、31日と表示するよりも前の case より、1、3、5、7、8、10、12のどれか一つでも当てはまる場合に実行するということです。
次の「break;」は、switch文の処理を終わらせることを表しています。もし、break; がなければ、switch文は、まだ実行され、その後の30日や28日という文字列が表示されてしまいます。
次の case である case 4: case 6: は31日と表示するためのものと同じで、変数month が30日と表示する必要がある数字と一致するときに30日と表示して、その後の文が実行されないように break; を書きます。
case 2: も同じです。
最後の default は特殊で、どの case にも当てはまらないときに実行されます。
なので、if に対する else のようなものであると言えます。
注意として、switch 文では「等しい」という条件で比較が行われますなので、以上や以下を判断するということはできません。
そのため、使い勝手が良いのは if 文と言えます。
使い分けとしては、書きやすい方を使うのがいいでしょう。
まとめ
条件分岐を使えると、ユーザの入力を受けて処理を変えることができます。
このような処理は、非常に一般的です。
考え方自体はそれほど難しくないので、ひとつずつ覚えていきましょう。