プログラミング C 05 - Soft Forum P.C. Club

制御構造(control structure)

今までやったのは入力はありますが, 事前に全部programを書く側が指示しています. これでは何のためのprogramかわかりません. そこで制御構造です.

いままでのprogramはすべて上から順番に実行されました. これでは例えば1000回1を足すという計算をさせるためには1000回+するよう書かないといけません. 制御構造は選択, 繰り返しをprogramにさせることができ, 上から順番にしか実行できなかったprogramの順番を自在に『制御』することができます.

選択

選択はif文によって行うことができます.

#include <stdio.h>
int main(int argc, char **argv) {
  int i = 10;
  if (i > 0) {
    // iが0より大きければ, { }の中に入る.
    printf("%s\n", "i > 10 == true");
  }
  return 0;
}

if文は

if ( 式 ) 文

という構造を持ち, 式がtrue, 真であるときに文を実行します.

さて, true / falseの概念を説明します.

真偽値(boolean)及び関係演算子(relational operator)

true / falseはそのとおり真偽を表す値です. ifの式がtrueのとき実行されるといいました. これには, 関係を表す演算子が必要です.

たとえば,

10 > 100

は関係演算子>を使った式で, 数学の>と同様, a > bでbよりaが大きいときにtrueになります. 上の式は10が100より大きいはずがないのでfalseです.

演算子説明数学
>a > bでaがbより大きいときtrue>
<a < bでaがbより小さいときtrue<
>=a >= bでaがbと同じもしくはbより大きいときtrue
<=a <= bでaがbと同じもしくはbより小さいときtrue
==a == bでaとbが同じときtrue=
!=a != bでaとbが違うときtrue

数学の演算子で見れば結構そのままですね.

また, C言語の世界では, 真偽値は数値です. これが0ならfalse, 0以外ならtrueという風になっています.

つまり

int i = 0;
if (i) {
  printf("%s\n", "実行されない");
}

となります.

選択2

以上を踏まえると...

#include <stdio.h>
int main(int argc, char **argv) {
  int i = 10;
  if (i > 0) {
    // iが0より大きければ, { }の中に入る.
    printf("%s\n", "i > 10 == true");
  }
  return 0;
}

の意味がわかりますね.

#include <stdio.h>
int main(int argc, char **argv) {
  int i;
  scanf("%d", &i);
  if (i > 0) {
    // iが0より大きければ, { }の中に入る.
    printf("%s\n", "i > 10 == true");
  }
  return 0;
}

scanfを使えば, 入力に応じてif文の中を実行するかどうかを選択することができます. ここにきて場合わけを行うことができるようになりました.

else

elseを使うと, if文をもれたものをひろうことができます.

#include <stdio.h>
int main(int argc, char **argv) {
  int i;
  scanf("%d", &i);
  if (i > 0) {
    // i > 0がtrueなら, この{ }の中に入る.
    printf("%s\n", "i > 10 == true");
  } else {
    // i > 0がfalseなら, この{ }の中に入る.
    printf("%s\n", "i > 10 == false");
  }
  return 0;
}

また, 何回も条件を調べたいときにelse ifが使えます.

#include <stdio.h>
int main(int argc, char **argv) {
  int i;
  scanf("%d", &i);
  if (i > 10) {
    // i > 10がtrueなら, この{ }の中に入る.
    printf("%s\n", "i > 10 == true");
  } else if (i > 0){
    // i > 0がtrueなら, この{ }の中に入る.
    printf("%s\n", "i > 0 == true");
  } else {
    // どちらもfalseなら.
    printf("%s\n", "false");
  }
  return 0;
}

if/else文について豆知識

ぶら下がりBlock

非常に大切なif文. 実際のprogramではif文を使わないということはまずありません.

いままでこうかいていました.

if (i > 0) {
  printf("%s\n", "i > 10 == true");
}

じつはifの構文は

if ( 式 ) 文

なので,

if (i > 0)
   printf("%s\n", "i > 10 == true");

こうかいても大丈夫です. { }のことを複文, もしくはBlockといい,

{
  文;
  文;
  文;
}

という風に複数の文をまとめて一つの文(Block Statement)とします.

ただし, 書けるからといって{}を抜かすのは, 実はC言語においては特有の問題を持ってくるので(macro展開でblock扱いの問題. これはdo-while(0)で囲むという解決法有り), よほど短い文でない限りは{ }をつけて書くようにすべきです.

また, elseの後も文なので1文であれば{}を省略できますが, こういう風な問題を生みます.

if (i > 0)
  if ( i > 10)
    printf("in\n");
else
  printf("else\n");

このelseはif (i > 0)とif (i > 10)のどちらにかかるのでしょうか? 実際には二番目のif文にかかるのですが, このように書かれると最初のif文にかかってそうに見えます. 非常に読みにくく, わかりにくいbugを生み出す温床になります.

代入演算子との取り違い

あるあるbugというものがprogram関連にはあって, つまり「こういうbug. あるあるー」という風なbugです. この一つに代入演算子と関係演算子のequalを取り違えるというものがあります.

int i = 0;
if ( i = 20) {
  printf("実行されないとおもいきや...\n");
}

上の例の場合i==20を=と書き間違いました. iは0のつもりなので0==20はfalseでprintfは実行されないつもりで書いていますが, これは実行されてしまいます. なぜなら=でiに20が代入されて, i = 20の部分の値は20だからです. 0以外はtrueというC言語の世界ではこれはtrueです.


これはいろいろ言われていて, 一部では,

int i = 0;
if ( 20 == i ) {
  printf("実行されないとおもいきや...\n");
}

とかくといいといわれた時期もありました. これなら, もしprogrammerが間違って,

int i = 0;
if ( 20 = i ) {
  printf("実行されないとおもいきや...\n");
}

と書いても, 20にiを代入することはできないので, compileでエラーになってわかるといわれたからです.

しかし現在, これはすでに時代遅れなやり方で, C言語でconstが使える今使うべきではありません. constについては後々解説します. とりあえず, 上のようなやり方は, 心の隅にとどめて, 実用しないようにしましょう. 書くと「何この時代遅れなcodeは」と鼻で笑われる可能性があります.

論理演算子(logical operator)

演算子説明俗にいう
&&a && b で aとbがtrueのときtrue. それ以外でfalseand
||a || b で aとbがどちらかtrueのときtrue, どちらもfalseでfalseor
!!a で trueとfalseがひっくり返るnot

logical and / logical or / logical notといいます.

計算機基礎とか, 情報数学概論とかやったことある方は, あれかと思うかもしれません.

これを使うと.

int i = 12;
if ( i > 0 && i < 20 ) {
  printf("iは0より上20より下\n");
}

とできます.

論理演算子の短絡評価

論理演算子のlogical andとlogical orは短絡評価という性質があります.

例えば,

true || (?);

orは片方がtrueならもうtrue確定なので, (?)のほうは見なくてもこれはtrue確定なわけです. また,

false && (?);

andは両方trueでtrueなので, 片方がfalseならもうfalse確定です. これも(?)のほうはみなくても確定してます.

このような場合, 高速化のためprogramは(?)を実行しません. これを短絡評価といいます.

Soft Forum P.C. Club