if文 条件分岐1

if文

今までのプログラミングは、単純に上から下へ順に全てのコードを実行していくだけでした。
実際のプログラミングでは、特定の条件によって処理を分けることが頻繁にあります。
そのためには条件分岐のための構文を使います。

最も代表的な条件分岐方法がif文です。


#include <stdio.h>

int main()
{
    char str[] = "ABCDE";
    int length = sizeof(str) - 1;

    if (length >= 6)
    {
        printf("strは6文字以上です。");
    }
    else if (length >= 3)
    {
        printf("strは3文字以上です。");
    }
    else
    {
        printf("strは3文字未満です。");
    }
    getchar();
}
strは3文字以上です。

char型配列による文字列には配列の終端にNULL文字が含まれるため、sizeof演算子は文字数+1の値を返すことに注意してください。
そのため、サンプルコードでは-1した値を変数lengthに代入しています。
(文字列の扱い方参照)

サンプルコードでは文字数の取得にsizeof演算子を使用していますが、sizeof演算子で得られるのは変数(配列)のバイト数です。
全角文字などのマルチバイト文字(2バイト以上の情報量の文字)を含む文字列では正しい文字数を得られません。
まだ正しい文字数を取得するための方法を説明していないので、ここではあえてsizeof演算子を用いています。

if(条件式){ 文 } [else if(条件式){ 文 }else{ 文 }]
条件式を満たす場合に文を実行する

if文は、指定された条件が成立するかどうかを判定し、成立する場合に{}内のコードを実行します。
成立しなかった場合は次の条件(else if)を判定します。
いずれの条件も成立しなかった場合にはelseブロック内のコードが実行されます。

「else if」を増やすことで条件を何個でも追加できます。
「else if」や「else」は省略することもできます。
以下のコードはif文の条件が成立しないので、実行しても何も表示されません。


#include <stdio.h>

int main()
{
    char str[] = "ABCDE";
    int length = sizeof(str) - 1;

    if (length >= 6)
    {
        printf("strは6文字以上です。");
    }
    getchar();
}

if文は、上から順に条件判定をしていき、最初に条件を満たした条件のブロック内の式のみを実行します。
それ以降のelse if文、およびelse文のブロックは実行されません。


#include <stdio.h>

int main()
{
    char str[] = "ABCDEFG";
    int length = sizeof(str) - 1;
    if (length >= 6)
    {
        printf("strは6文字以上です。");
    }
    else if (length >= 3)
    {
        printf("strは3文字以上です。");
    }
    else
    {
        printf("strは3文字未満です。");
    }
    getchar();
}
strは6文字以上です。

上記のコードは最初の条件を満たすので、「strは6文字以上です。」と表示されます。
二つ目の条件も満たしますが、これは実行されません。

両方実行したい場合はif文を二つ(以上)に分けて書きます。


#include <stdio.h>

int main()
{
    char str[] = "ABCDEFG";
    int length = sizeof(str) - 1;
    if (length >= 6)
    {
        printf("strは6文字以上です。\n");
    }
    if (length >= 3)
    {
        printf("strは3文字以上です。\n");
    }
    if(length < 3)
    {
        printf("strは3文字未満です。\n");
    }
    getchar();
}
strは6文字以上です。
strは3文字以上です

関係演算子

条件の判定に使うのは関係演算子という記号です。
これは数学で使う記号と似ていますが、書き方がやや異なります。

a == b
aとbは等しい
a != b
aとbは等しくない
a > b
aはbより大きい
a >= b
aはbと等しいか、大きい
a < b
aはbより小さい
a <= b
aはbと等しいか、小さい

等号「=」はふたつ連続で書きます。
これがひとつだと代入になってしまい、正しく条件判定ができません。

「!=」はノットイコールといい、左右が等しくない場合に成立します。

大なりイコール、小なりイコールは数学では「≧」「≦」を使いますが、これは全角記号なので、半角の「>」「<」と「=」を組み合わせて使用します。

論理演算子

ひとつの条件式で複数の条件判定を一度に行うには論理演算子を使用します。

a && b
aとbの両方が真の場合に真を返す
(論理積)
a || b
aまたはbが真の場合に真を返す
(論理和)
!a
aが偽の場合に真を返す
(否定)

は条件が成立、は条件が成立しない事を意味します。
それぞれTRUEFALSEともいいます。


#include <stdio.h>

int main()
{
    char str1[] = "ABCDE";
    char str2[] = "FGHIJ";
    int length1 = sizeof(str1) - 1;
    int length2 = sizeof(str2) - 1;

    if (length1 >= 3 && length2 >= 3)
    {
        printf("両方3文字以上");
    }
    else
    {
        printf("どちらか、または両方が3文字未満");
    }
    getchar();
}

このコードを実行すると、「両方3文字以上」と表示されます。

否定は条件判定の真と偽を反転させます。


#include <stdio.h>

int main()
{
    char str[] = "AB";
    int length = sizeof(str) - 1;

    if (!(length >= 3))
    {
        printf("strは3文字未満");
    }
    else
    {
        printf("strは3文字以上");
    }
    getchar();
}

このコードのlength >= 3は成立しませんが、否定によって真偽が反転されるので、最初のifブロックが実行されます。

!length >= 3と記述すると、変数lengthを否定することになるので注意してください。
ちなみに整数値を否定した場合は、0以外を否定すると0に、0を否定した場合は0以外になります。
0を否定した場合に具体的に何の数値になるかはC言語では決められていません。


int length = 2;

if (!(length >= 3)) {
	//「2 < 3」と同義なので実行される
}

if (!length >= 3) {
	//2を否定した場合は0と評価されるので実行されない
}

短絡評価(ショートサーキット)

論理演算子で複数の条件を同時に判定するとき、前半の条件式を判定するだけで条件式全体の条件を満たす/満たさないが決定できる場合があります。
例えば以下のような場合です。


//「0 == 1」は成立しないので
//後半の条件式が何であろうとこのif文は実行されない
if(0 == 1 && 1 == 1) {}

//「1 == 1」は成立するので
//後半の条件式が何であろうとこのif文は実行される
if(1 == 1 || 0 == 1) {}

前半だけで条件式全体の結果が判定できる場合、後半の条件判定を行う必要はありません。
このような場合、C言語では後半の条件式は実行されず処理がスキップされます。
これを短絡評価(ショートサーキット)といいます。

短絡評価はプログラムの高速化に繋がるので基本的には便利な機能です。
しかし「処理がスキップされることがある」ということを考慮しないと意図しない動作となる場合があります。


int Func()
{
	int ret = 0;
	//何らかの処理…
	return ret;
}

int main()
{
	int a, b;
	if((a = Func()) == 0 || (b = Func()) == 0) {
		printf("%d\n", a);
		printf("%d\n", b);
	}
}

上記コードでは、関数Funcの実行結果をそれぞれの変数に代入し、さらにその値を条件判定に使用しています。
(代入式を評価すると、代入された値が返されます)
このコードで最初の条件式(変数aへの代入)が真になる場合、後半の条件式(変数bへの代入)を実行する必要はなく、短絡評価となりif文が実行されます。
つまり、変数bには何も値が代入されないままif文が実行される可能性があり、if文中で変数bの値を使用するとエラーになります。

このようなコードはVisual Studioではコンパイル時エラーにしてくれますが、全てのコンパイラがそうとは限りません。
別の処理で変数を初期化(代入)していたり、そもそも変数を使わないような処理だとコンパイラはエラーを検出できません。


if(Func1() == 0 && Func2() == 0) {}

関数Func1と関数Func2が必ず実行されなければならない場合に、上記のようなコードにしてしまうと意図した通りの動作にはならないので注意が必要です。

数値の真偽判定

C言語の条件式には数値を指定することもできます。


#include <stdio.h>

int main()
{
    if (0)
    {
        printf("0\n");
    }
    if (1)
    {
        printf("1\n");
    }
    if (-1)
    {
        printf("-1\n");
    }
    getchar();
}
1
-1

数値を条件判定すると、0は偽0以外は真と判断されます。
このサンプルコードのように直接数字をif文の条件に記述することはほとんどありませんが、変数の値をチェックして条件分岐することはよくあります。


#include <stdio.h>

int main()
{
    int number;

    //関数の実行結果を受け取る
    number = Func();
    
    if (number)
    {
        printf("0\n");
    }
    else
    {
        printf("0以外\n");
    }
    getchar();
}

ブロックの省略

if文やelse文で実行したい文が一行で済む場合はブロックの記述は省略できます。


if(num == 0)
{
    printf("Hello");
}
else
{
    printf("Bye");
}

//↓のように書ける

if(num == 0)
    printf("Hello");
else
    printf("Bye");

//改行も必須ではない
if(num == 0) printf("Hello");

if (num == 0) printf("Hello");
else printf("Bye");