printf()
文の中でも式は評価される。従って、
前置演算(++,--
)は printf()
文が実行される前に評価され、
後置演算子は printf()
文が実行された後に評価される。
ハンドアウトでは取り上げなかったが、その他の演算子としてビット演算子がある。ビット演算子とはビット単位でデータ操作をするものであり、オペランドは整数に限られる。ビット演算子には以下のものがある。
演算子 | 意味 |
---|---|
& | ビットごとの論理積 |
| | ビットごとの論理和 |
^ | ビットごとの排他的論理和 |
~ | ビットごとの反転(1 の補数) |
この他、先に挙げた >>,<<
もビット演算子である。
ビット演算子のサンプルプログラムを以下に示す。
bit_operator.c
。
bit_operator2.c
。
ビットごとの排他的論理和 ^
は、暗号回路に用いられる。ある
ビット列を鍵となるビット列との排他的論理和で暗号化した場合、もう一度同
じ鍵との排他的論理和を用いると元のビット列が復号化される。
課題 3 の排他的論理和を求める問題で、
x = ( p + q ) % 2;
及び
x = ( p - q ) * ( p - q );
の二つは秀逸であった。前者は両変数の和を 2 で割った余りが 1 である場合真となり他は偽となるため、排他的論理和の演算になっている。後者は、両変数の差の 2 乗が 1 である場合に真であるので、 (0,0), (1,1) の場合には 0 * 0 となって偽になる。一方、(0,1), (1,0) の場合には 1 であるから真となる。
変数の型を変換する演算子をキャスト演算子という。用法は
(型) 式
となる。例えば int
型の変数を double
型に変換する場合などである。例えば 例
4.11 cast.c
のように用いる。
順次、選択、繰り返し、の 3 つの要素だけからなっているプログラミングメソッドを構造化プログラミングという。この 3 つの要素さえあれば後述する goto
文は不要である。
if ()
文if (){...} else {...}
文switch{...}
文while(){...}
文do {...} while();
文for(;;)
文if ()
文
if
文は、
if (条件式)
文;
のように用いる。条件式が真(0でない)場合、文が実行される。条件式が真である場合、
実行される文が複数ある場合は、それらを中括弧({}
)で括る。例えば、
if (total > 0) {
++count;
printf("合計値は正です。\n");
}
などのように用いる。
通常、{}
で囲んだ文は読みやすくするためインデントする。
インデントが適切でないと可読性が下がるばかりでなく、バグの原因となる。
Emacs の C モード(拡張子が .c のファイルを編集している時)では、オートインデンテーションが
オンとなり、2 文字分の空白が挿入される。
even-odd.c
int
型の整数 a, b を入力し, b が 0 でなければ a/b と a % b を表示するプログラムを作れif-else
文
if
文は else
を伴って、2 分岐型の処理をおこなわせることができる。書式は、
if (条件式)
文;
else
文;
である。例えば、
if (year % 4 == 0)
printf("Olympic game will be held!\n");
else
printf("Olympic game won't be held\n");
などとする。ここで次のような、閏年を判定するプログラムを考えてみよう(閏年は西暦年が 4 で割り切れる年であり、ただし 100 で割り切れる年は平年であり、ただし 400 で割り切れる年は閏年である)。
if (year % 4 == 0)
if ( year % 100 == 0 )
if ( year % 400 == 0 )
printf("Leap year\n");
else
printf("Not leap year\n");
else
printf("Leap year\n");
else
printf("Not leap year\n");
このプログラムは if
が 3 つ、else
が 3 つ出てくる。
どの if
が、どの else
に対応しているのかわかりずらい。
更に、閏年の時だけ count
という変数を増加させるコードを追加すること
を考えると、このコードは破綻を来す。
/* 間違ったプログラム */
if (year % 4 == 0)
if ( year % 100 == 0 )
if ( year % 400 == 0 )
printf("Leap year\n");
count++;
else
printf("Not leap year\n");
else
printf("Leap year\n");
count++;
else
printf("Not leap year\n");
このコードは正しく動作しない。正しく動作させるためにはカッコを用いて、
if (year % 4 == 0) {
if ( year % 100 == 0 ) {
if ( year % 400 == 0 ) {
printf("Leap year\n");
count++;
} else {
printf("Not leap year\n");
}
} else {
printf("Leap year\n");
count++;
}
} else {
printf("Not leap year\n");
}
と、しなければならない。プログラムを美しく書く習慣は、保守性を高め、思 わぬバグを未然に防ぐ効果を持っている。正しくインデントして美しくコード を書く習慣を身に付けなければならない。
scanf()
で入力し、その年が閏年であるかどうかを判定するプログラム leap_year.c
を作れolympic.c
を作れdrill.c
を作れsign.c
を作れswitch
文
switch
文は if, else
文を幾つも重ねた文と同じ役割をする
多重分岐文である。
switch(式) {
case 定数式1:
文;
...
break;
case 定数式2:
文;
...
/* break が無ければ下の文が実行される */
case 定数式3:
文;
...
break;
deafult :
文;
...
break;
}
なお、各 case
の最後につける break
文は必須ではない。
break
文は制御を次の処理に移すための命令であって、なければ直下
の文が実行されることになる。
switch.c