プログラミング(3)「制御命令」

制御命令

プログラムは上から順に実行されますが、 条件によってある処理を実行しないようにさせたい場合や、 同じことを何度も繰り返したい場合もあります。 このようなときはifやforなどの制御命令を使用します。 ここではC言語で使う主な制御命令を紹介します。


条件分岐(if,else)

特定の条件のときにだけ実行させたい処理がある場合はif文を使用します。 例えばif文は以下のように使用します。

if(i == 2){
  printf("i には 2 が入っている\n");
}

この場合、変数iが2の場合だけprintf文が実行されます。

if文の書式は

if(条件式){
  条件式が成り立つときに行われる処理
} else {
  条件式が成り立たないときに行われる処理
}

となっています。条件式には下の表にある演算子を使用できます。

演算子意味
== 等しい a == b
!= 等しくない a != b
< 小さい a < b
<= 小さいか等しいa <= b
> 大きい a > b
>= 大きいか等しいa >= b

C言語では条件式も値を持ちます。条件が成り立つときの値は1、 成り立たない場合の値は0となります。つまり、 if文は(条件式)の中が0以外のときのときはif文に続く { }に囲われた処理が実行され、0のときはelseに続く{ }の中の処理が実行されます。 elseは省略可能です。{ }も省略することが出来て、 その場合はif文の直後の一行だけが実行されます。

また、ifとelseを連続で使用することで、 いろいろな条件での処理を続けて書くことも出来ます。

if(i == 1){
  printf("i には 1 が入っている\n");
} else if(i == 2){
  printf("i には 2 が入っている\n");
} else if(i == 3){
  printf("i には 3 が入っている\n");
}

if文の中に複数の条件の論理和(OR)や論理積(AND)を使用したい場合は、 ||(OR)や&&(AND)を使用します。

演算子意味
|| 論理和a == 1 || b == 2
&& 論理積a == 1 && b == 2
! 論理否定 !(a == 1)

繰り返し(for,while)

同じ処理を何度も行いたい場合は、for文やwhile文を使用します。

for(i = 0; i < 10; i++){
  printf("i = %d\n",i);
}

この例の実行結果は

i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9

となります。for文の書式は

for(式1; 式2; 式3){
  繰り返す処理
}

となっています。動作としては、始めに式1を実行し、 式2を評価して値が0以外のときにforに続く{ }の中の処理を実行し、 式3を実行し、また式2を評価する、ということを繰り返します。

上の例では、始めにiに0を代入し、i < 10を評価します。 iが0のときはi < 10が成り立ちますのでprintfが実行され、 その後にi++でiが1増えます。次にまたi < 10を評価をして条件が成り立つ限り { }の処理を続けます。例ではiが9までこの条件は成り立ちますので、 iが0から9までの合計10回、printf文が実行されます。

while文は、for文の式2だけを使用するようなもので書式は

while(式){
  繰り返す処理
}

となります。while文は式の値が0以外のとき{ }の中の処理を実行し続けます。

i = 0;
while(i < 10){
  printf("i = %d\n",i);
  i++;
}

とすれば、for文の例と同じ処理を行うことが出来ます。 (もちろん、通常はfor文を使用しますが)

while文の条件式が処理の下に来る,do-while文というものもあります。書式は

do{
  繰り返す処理
}while(式);

となっていて、 whileと同じように式の値が0以外のとき{ }の中の処理を実行し続けます。 while文と違うのは、式が0の場合にも{ }の処理が1回行われることです。 従って、do-while文では{ }の処理が必ず1回以上実行されます。

演習

配列変数を使用して変数を10個作り、for文で10個の変数に整数値 1, 2, 3, 4, 5, 6, 7, 8, 9, 10をそれぞれ代入し表示せよ。


ジャンプ(break,continue,goto)

実行している処理を別の場所に移す場合はジャンプ命令を使用します。

ループ処理を途中で中断する場合はbreak文を使用します。

for(i = 0; i < 10; i++){
  if(type[i] == 5){
    break;
  }
  printf("%d\n",type[i]);
}

この例では、配列変数type[i]の中身が5以外のときは、printfで表示を行い、 type[i]が5の場合はループ処理を中断します。実行結果は以下のようになります。

0
1
2
3
4

ループ処理で、処理は中断するがループは中断しない場合はcontinue 文を使用します。

for(i = 0; i < 10; i++){
  if(type[i] == 5){
    continue;
  }
  printf("%d\n",type[i]);
}

この例では、配列変数type[i]の中身が5以外のときは、 printfで表示を行い、type[i]が5の場合だけ表示を行いません。 つまり、continue文が実行されるとforに処理が移ります。 実行結果は以下のようになります。

0
1
2
3
4
6
7
8
9

無条件で別の場所に処理を移す場合はgoto文を使用します。 移る先は予めラベルを用意する必要があります。

goto error;
....
error:
....

goto文を多用するとプログラムがわかりにくくなるので、 通常はgoto文を使用しません。 用途としては、 for文等のループ文が多重になったときに多重ループから抜け出す場合や、 例外処理などのときにgoto文を使用します。

for(i = 0; i < 10; i++){
  for(j = 0; j < 10; j++){
    if(i == j){
      goto out;
    }
  }
}
out:
演習
以下のプログラムは、乱数を20個表示するプログラムである。
  1. このプログラムを変更して、rが奇数のときには数字の前にoddを、 偶数の場合はevenを表示するように書き換えよ。
    (ヒント:演算子%を使用すると、割り算の余りを求めることができる。 例 10 % 3 = 1)
  2. 次に配列変数odd, evenを要素数20で作製し、 それぞれに乱数の奇数と偶数を格納せよ。 その配列変数を利用して得られた乱数を偶数、奇数別に表示せよ。
#include <stdio.h>
#include <stdlib.h>
main()
{
  int i;
  int r;
  srand(1);
  for(i = 0; i < 20; i++){
    r = rand();
    printf("%d\n",r);
  }
}