if文

| Topic path: Top / 授業 / C言語基礎 / if文

*フローチャート [#j5eef202]

プログラムによる処理の流れは、''フローチャート''(流れ図)という図で表すことができます。


|記号|名前|h
|#ref(./line.png,nolink,12.5%)|流れ線|
|#ref(./arrow.png,nolink,12.5%)|矢印|
|#ref(./terminal.png,nolink,12.5%)|端子|
|#ref(./process.png,nolink,12.5%)|処理|
|#ref(./decision.png,nolink,12.5%)|判断|

''流れ線''は、制御の流れを表します。
横のときは左から右へ、縦のときは上から下へと進みます。

''矢印''も、制御の流れを表します。
矢印の向きに進みます。
他の流れ線や矢印に合流するときにも、矢印を使います。

''端子''は、開始と終了の場所を表します。
制御の流れは、一つの開始端子から始まり、一つの終了端子で終わります。

''処理''は、その名の通り、処理を表します。
複数の処理を一つにまとめて表すこともできます。

''判断''は、条件によって制御の流れを分岐させます。



*条件分岐 [#r0c7c9fd]

次のようなプログラムを考えてみましょう
 試験の点数が60点以上なら「合格」と表示する。

つまり、点数が60点以上なら「合格」と表示し、そうでないなら何も表示しないようにします。

これをフローチャートで描くと、次のようになります。
#ref(./if1.png,nolink,12.5%);

これをC言語風にすると、次のようになります。
#ref(./if2.png,nolink,12.5%);
ここで、点数はint型の変数scoreに格納することとし、点数は適当に85点にしています。

判断のラベルが「はい」と「いいえ」から「0でない」と「0」に変わっていますが、これについてはもう少し後で説明します。



*if文 [#i9b7d164]

C言語で条件分岐を行うには、''if文''を使います。

if文は、次の形をしています。
#geshi(c){{
  if (条件) {
    処理
  }
}}

if文は、''( )''内に指定された「条件」を評価し、「条件」を満たすときだけ「処理」を行います。
「条件」を満たさないときは、「処理」を行わずに次へ進みます。

「条件」を満たすときに行う「処理」に含まれる命令文がない、または、命令文が一つだけのとき、波括弧 ''{ }'' を省略できます。
#geshi(c){{
  if (条件) 命令文;
}}
(省略しなくてもかまいません。)

「条件」には、''関係演算子''や''論理演算子''を使います。
関係演算子と論理演算子については、この下で詳しく説明します。

このif文を使ったC言語のプログラムは、次のようになります(プログラム1)。
#geshi(c){{
#include <stdio.h>

int main(void) {
  int score = 85;
  
  if (score >= 60) {
    printf("合格\n");
  }

  return 0;
}
}}

**演習1 [#oe1c6530]
プログラム1を作成し、実行結果を確認せよ。
また、点数を50点に変更し、実行結果を確認せよ。



*条件を満たさないときにも処理を行う [#saf4584a]

続いて、次のようなプログラムを考えてみましょう。
 試験の点数が60点以上なら「合格」、そうでないなら「再試験」と表示する。

これをフローチャートで描くと、次のようになります。
#ref(./else1.png,nolink,12.5%);
このように、条件を評価した結果によって、異なる処理が実行されます。

そして、これをC言語風にすると、次のようになります。
#ref(./else2.png,nolink,12.5%);

条件を満たさないときにも処理を行うif文は、次のようになります。
#geshi(c){{
  if (条件) {
    処理1
  } else {
    処理2
  }
}}
( ) 内の「条件」を評価し、条件を満たすときは「処理1」を実行し、満たさないときは「処理2」を実行します。

先ほどと同様に、「処理1」または「処理2」に含まれる命令文がない、または、命令文が一つだけのとき、波括弧 { } を省略できます。
条件を満たすときに行う処理と条件を満たさないときに行う処理に含まれる命令文が両方とも一つだけのときは、次のようになります。
#geshi(c){{
  if (条件) 命令文1;
  else 命令文2;
}}

同様に、条件を満たすときに行う処理に含まれる命令文が一つだけのときと、反対に、条件を満たさないときに行う処理に含まれる命令文が一つだけのときは、次のようになります。
#geshi(c){{
  if (条件) 命令文1;
  else {
    処理2
  }
}}
#geshi(c){{
  if (条件) {
    処理1
  } else 命令文2;
}}

このif文を使ったC言語のプログラムは、次のようになります(プログラム2、if文の部分のみ)。
#geshi(c){{
  if (score >= 60) {
    printf("合格\n");
  } else {
    printf("不合格\n");
  }
}}

**演習2 [#od2e7b4a]
プログラム1をプログラム2に変更し、実行結果を確認せよ。 また、点数を50点に変更し、実行結果を確認せよ。


*3つ以上に分岐する [#jd40ab13]

さらに、次のプログラムについて考えてみましょう。
 試験の点数が60点以上なら「合格」、20点以上60点未満なら「再試験」、それ以外なら「不合格」と表示する。

#ref(./elseif1.png,nolink,12.5%);
最初の条件「点数が60点以上」を満たさないときに行われる処理が点線で囲まれたグレーの部分で、一つの条件分岐になっています。

問題文には「再試験」と表示するときの条件は「点数が20点以上60点未満」とありますが、フローチャートにおいて二つ目の条件が判定されるのは、最初の条件「点数が60点以上」を満たさないときに限られるので、必ず60点未満になります。
このため、二つ目の条件は「点数が20点以上」だけになっています。

このフローチャートをC言語風にすると、次のようになります。
#ref(./elseif2.png,nolink,12.5%);

最初の条件を満たさないときにさらに条件分岐を行うif文は、次のようになります。
#geshi(c){{
  if (条件1) {
    処理1
  } else {
    if (条件2) {
      処理2
    } else {
      処理3
    }
  }
}}

これまでと同様に、波括弧 { } の中の命令文がない、または、命令文が1つだけのときは、波括弧を省略できます。
ここでは、最初のif文の条件を満たさないときの処理が1つのif文だけので、波括弧を省略して次のよう書くことができます。
(こちらの書き方方が一般的です。)
#geshi(c){{
  if (条件1) {
    処理1
  } else if (条件2) {
    処理2
  } else {
    処理3
  }
}}


このif文を使ったC言語のプログラムは、次のようになります(プログラム3、if文の部分のみ)。
#geshi(c){{
  if (score >= 60) {
    printf("合格\n");
  } else if (score >= 20) {
    printf("再試験\n");
  } else {
    printf("不合格\n");
  }
}}

同じようにすれば、4つ以上に分岐するif文も作ることができます。


**演習3 [#m3c2f1dc]
プログラム2をプログラム3に変更し、点数が85点、50点、10点のときの実行結果を確認せよ。



*関係演算子 [#m0aa9192]

if文の条件式には、多くの場合、''関係演算''を用います。
関係演算を行うための演算子を''関係演算子''といいます。

関係演算子には、次のものがあります。
|優先順位|演算子|使用例|意味|h
|7|<|a < b|左辺の値が右辺の値より''小さい''とき 1、そうでないとき 0|
|~|<=|a <= b|左辺の値が右辺の値より''小さいか等しい''とき 1、そうでないとき 0|
|~|&gt;|a > b|左辺の値が右辺の値より''大きい''とき 1、そうでないとき 0|
|~|>=|a >= b|左辺の値が右辺の値より''大きいか等しい''とき 1、そうでないとき 0|
|8|==|a == b|左辺の値が右辺の値と''等しい''とき 1、そうでないとき 0|
|~|!=|a != b|左辺の値が右辺の値と''等しくない''とき 1、そうでないとき 0|

関係演算の結果は、int型の 1 か 0 になります。

if文は、条件として指定された式を評価した結果が0のときは''偽'' (''false'')、つまり、条件を満たさない、そうでないときは''真'' (''true'')、つまり、条件を満たすと判断します。


**演習4 [#pf9209ba]
試験の点数が100点なら「満点」と表示するプログラムを作成し、実行せよ。



*関係演算を行うときの注意 [#s8293bb5]

等しいかどうかを判定する演算子が、''='' ではなく ''=='' であることに注意しましょう。
= は代入演算子です。

次のプログラムは変数xの値が1ならばYes、そうでないならNoと出力するプログラムを作るときに、関係演算子の == と間違えて代入演算子 == を使ってしまったプログラムの例です(プログラム4、if文の部分のみ)。
#geshi(c){{
  int x = 0;
  if (x = 1) {
    printf("Yes\n");
  } else {
    printf("No\n");
  }
}}

if文の条件である x = 1 の結果が 1 となり、0 でないため、条件を満たしていると判断され、Yesが出力されてしまいます。


**演習5 [#gbbb1872]
プログラム4を作成し、実行結果を確認せよ。

**演習6 [#l24f948e]
プログラム4を正しいプログラムに修正し、実行結果を確認せよ。


*論理演算子 [#xac5e680]

if文の条件が複数の条件の組み合わせとなるときは、''論理演算''を用います。
論理演算を行うための演算子を''論理演算子''といいます。

論理演算子には、次のものがあります。
|優先順位|演算子|使用例|意味|h
|2|!|!a|値が 0 のとき 1、そうでないとき 0(論理否定)|
|12|&&|a && b|左辺の値が 1 ''かつ''右辺の値が 1 のとき 1、そうでないとき 0(論理積)|
|13|&#x7c;&#x7c;|a &#x7c;&#x7c; b|左辺の値が 1 ''または''右辺の値が 1 のとき 1、そうでないとき 0(論理和)|

論理演算の結果も、int型の 1 か 0 になります。

優先順位に注意しましょう。

**演習7 [#f754f61a]
数学の試験の点数が60点以上、かつ、英語の試験の点数が60点以上なら「合格」、そうでないなら「不合格」と表示するプログラムを作成し、英語と数学の両方が85点のとき、英語が85点で数学が50点のとき、英語と数学の両方が50点のときの実行結果を確認せよ。

**演習8 [#a7ee04df]
数学の試験の点数が60点以上、または、英語の試験の点数が60以上なら「合格」、そうでないなら「不合格」と表示するプログラムを作成し、英語と数学の両方が85点のとき、英語が85点で数学が50点のとき、英語と数学の両方が50点のときの実行結果を確認せよ。


*論理演算を行うときの注意 [#of0a6155]

論理積 && と論理和 || は、普通、二つの関係演算の式を組み合わせて使います。

「変数 x の値が 0 以上 10 未満」という条件は、「x が 0 以上」かつ「x が 10 未満」として、次のように表します(プログラム5、if文の部分のみ)。
#geshi(c){{
  double x = 12.3;
  if (x >= 0 && x < 10) {
    printf("Yes\n");
  } else {
    printf("No\n");
  }
}}

次のように表すのは間違いです(プログラム6、if文の部分のみ)。
#geshi(c){{
  double x = 12.3;
  if (0 <= x < 10) {
    printf("Yes\n");
  } else {
    printf("No\n");
  }
}}
ただし、このプログラムでもコンパイルと実行はできます。
最初に 0 <= x が評価されて1になり、次に 1 < 10 が評価されて0になり、Noが出力されてしまいます。
最初に 0 <= x が評価されて 1 になり、次に 0 <= x が 1 に置き換えられ、1 < 10 が評価されて 1 になり、結果として Yes が出力されてしまいます。

また、「変数 x の値が 0 または 1 に等しい」という条件は、「x が 0 に等しい」または「x が 1 に等しい」として、次のように表します(プログラム7、if文の部分のみ)。
#geshi(c){{
  int x = -1;
  if (x == 0 || x == 1) {
    printf("Yes\n");
  } else {
    printf("No\n");
  }
}}

次のように表すのは間違いです(プログラム8、if文の部分のみ)。
#geshi(c){{
  int x = -1;
  if (x == 0 || 1) {
    printf("Yes\n");
  } else {
    printf("No\n");
  }
}}
これも、コンパイルと実行はできます。
最初に x == 0 が評価されて0になりますが、次に 0 || 1 が評価されて1になり、Yesと出力されてしまいます。
最初に x == 0 が評価されて 0 になりますが、次に 0 || 1 が評価されて 1 になり、Yes と出力されてしまいます。

また、&(アンパサンド1つ)と |(縦棒1つ)も演算子です。
&&, || と間違えないように気をつけましょう。


**演習7 [#rc3bf3da]
プログラム5を作成し、実行結果を確認せよ。
また、プログラム5をプログラム6に変更し、実行結果を確認せよ

**演習8 [#k43a7630]
プログラム7を作成し、実行結果を確認せよ。
また、プログラム7をプログラム8に変更し、実行結果を確認せよ


----
*インデントのスタイル(おまけ) [#b57e2e1b]

if文の中に含まれる命令文を書くときは、インデントのレベルを一段深くします。

インデントには、タブか空白を用います。
タブは、ソフトウェアによって8文字分になったり、4文字分になったり、設定できたりします。

どちらを用いても構いませんが、いつもおなじものを使用しましょう。
私は、横幅を取らないように、空白2文字分としています。
(このセクションのサンプルでは、インデントが目立つように4文字分にしています。)

また、インデントのスタイルにも''K&Rスタイル''、''BSDスタイル''、''Javaスタイル''などがあります。

どのスタイルを用いても構いませんが、このうちのどれかのスタイルを選んで、いつも同じものを使用しましょう。
私は、行数が少なくなるスタイルがいいので、Javaスタイルを使っています。


**K&Rスタイル [#be468109]
C言語のバイブル『K&R』で用いられているスタイルです。
-main関数の { は新しい行の先頭に置きますが、それ以外の { は行の最後に置きます。
-{ } の中に含まれる行はインデント・レベルを一段深くします。
-} は新しい行の先頭に置き、インデント・レベルを対応する { の行に合わせます。

#geshi(c){{
int main(void)
{
    int i = 0;
    if (i > 0) {
        printf("Yes\n");
    } else {
        printf("No]n");
    }
    return 0;
}
}}

**BSDスタイル [#v9a956b2]
UNIXの一つであるBSDのコードで用いられているスタイルです。
-{ は新しい行の先頭に置き、インデント・レベルを直前の行に合わせます。
-{ } の中に含まれる行はインデント・レベルを一段深くします。
-} は新しい行の先頭に置き、インデント・レベルを対応する { の行に合わせます。

#geshi(c){{
int main(void)
{
    int i = 0;
    if (i > 0)
    {
        printf("Yes\n");
    } else
    {
        printf("No]n");
    }
    return 0;
}
}}


**Javaスタイル [#ibeb1833]

オブジェクト指向言語Javaで用いられているスタイルです。
-{ は行の最後に置きます。
-{ } の中に含まれる行はインデント・レベルを一段深くします。
-} は新しい行の先頭に置き、インデント・レベルを対応する { の行に合わせます。

#geshi(c){{
int main(void) {
    int i = 0;
    if (i > 0) {
        printf("Yes\n");
    } else {
        printf("No]n");
    }
    return 0;
}
}}



*条件に関係演算と論理演算を用いないif文(おまけ) [#j1cf7daf]

if文は、条件として指定された式を評価した結果が0のときは''偽'' (''false'')、つまり、条件を満たさない、そうでないときは''真'' (''true'')、つまり、条件を満たすと判断します。

結果がint型の値になる式であれば、if文の条件として使うことができます。

たとえば、次のif文は、条件の値が常に0なので、if文に含まれる処理が実行されることはありません。
#geshi(c){{
  int f = 0;
  if (f) {
    printf("Hello World!\n");
  }
}}
プログラムの一部を実行しないようにするためにこのテクニックを用いることがあります。
(コメント・アウトするとコンパイル時に無視されてしまいますが、こうしておくとコンパイル時に無視されないので、構文が正しいことを確認できます。)

反対に、次のif文は、条件の値が常に1なので、if文に含まれる処理は必ず実行されます。
#geshi(c){{
  if (1) {
    printf("Hello World!\n");
  }
}}
条件式を後で考えて、先に条件を満たすときの処理のプログラムを作りたいときなどに、このテクニックを用いることがあります。

また、if文は、条件式を評価した結果が「0でない」ときは真、つまり条件を満たすと判断されるので、その結果がint型であれば0または1のいずれかでなくてもかまいません。

次のif文は、条件式 a * b の結果が0でなければ「Yes」と表示し、0であれば「No」と表示します。
#geshi(c){{
  if (a * b) {
    printf("Yes\n");
  } else {
    printf("No\n");
  }
}}
aとbの値が0または1のとき、このif文の結果は、論理積 a && b を用いたif文の結果と同じになります。



----
*まとめ [#j02ef059]

C言語で''条件分岐''を行うには、''if文''を使います。

条件には、普通、''関係演算子''を用い、その結果はint型の 1 または 0 になります。

複数の条件を組み合わせるときは、''論理演算子''を用います。
論理演算子の結果もint型の 1 または 0 になります。

条件の式を評価した結果が 0 のとき、条件を満たしていないと判断され、そうでないとき、条件を満たしていると判断されます。


----
*練習問題 [#ua6c66aa]

if文の練習問題は[[こちら>/授業/C言語基礎/if文/練習問題]]
トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS