計算機実習 I

第三回 (2015 年 4 月 23 日)

制御文:条件、枝分かれ、繰り返し

http://www.sw.it.aoyama.ac.jp/2014/CP1/lecture3.html

Martin J. Dürst

AGU

© 2005-15 Martin J. Dürst 青山学院大学

今日の予定

ミニテスト

理工学部50周年記念行事

C 言語の原点

システムについて

前回の演習結果

02B1 02C1 02C2
100点 96 71 33
60点 5 23 57
エラー - 2 5
未提出 - - 1

前回の課題について

前回の補足: 優先度

実例: if (a & 1 == 1)

意図: if ((a&1) == 1) // 奇数かの判断

実体: if (a & (1==1)) (教科書 p. 388 参照)

不運の幸い: 1==1 の結果 (真) はたまたま 1 で表現 (その保証は一切ない)

結論 1: シフトやビットごと論理演算では優先度要確認

結論 2: if (a & 1) だけでも大丈夫 (偶数の場合、結果が 0 (偽)、奇数の場合、結果が 1 (真))

 

識別子の選び方

(identifier, 名前)

構文 (文法) と意味

(syntax (grammar) and semantics)

if 文の構文:

if ( 条件式 )

文法には固定部分 (上記で if()、終端記号) と置き換えられる部分 (非終端記号)

if 文の意味:

条件式を評価し、結果が真の場合、を実行 (偽の場合、を実行しない)

文の種類

括弧は積極的に使用

誤解を招く書き方:

if (score >= 60)
printf("60 点以上です。\n");
printf("あなたは合格です。\n");

誤解のない書き方:

if (score >= 60) {
printf("60 点以上です。\n");
printf("あなたは合格です。\n");
}

 

Combining if and else

if (score >= 60) {
printf("You got more than 60 points.\n");
} else {
printf("See you again next year.\n");
}

How to Write if - else if - else

if (...) {
...
}
else if (...) {
...
}
else {
...
}

 

A Bad Way to Write if - else if - else

if (...) {
...
}
else if (...) {
...
}
else if (...) {
...
}
else {
...
}

if 文の代わり: 三項演算子

(ternary operator; 条件演算子, conditional operator)

よくある一句:

if (x > y)
max = x;
else
max = y;

次が同等:

max = (x > y) ? x : y;

if 文の代わり: 条件式

&&|| で if 文のようなものが作れる:

if (score >= 60) {
grade = calculate(score);
}

の代わりに

score>=60 && (grade=calculate(score));

Cygwin で使える条件式

Example: gcc 03B1.c && ./a

Example: gcc -o 03B1 03B1.c && ./03B1

How it works:

二つの実行も上記のよう接続可能

main からの戻り値が 0 の場合は真、それ以外の場合は偽 (C 内部と逆)

switch 文の構文

switch (  ) {
case 定数1 :
処理1 ;
break;
case 定数2:
case 定数3:
処理2 ;
... break; default : 処理3 ;
break;
}

 

switch 文の注意点

break がない場合、プログラムはそのまま続く

int a = 5, b = 1;
switch (a) {
case 4:
b = 3;
break;
case 5:
b = 7;
case 6:
b *= 3;
break;
}

実行後、b の値は 21

break を意図的に使わないとき、コメントで明記

 

break の使用例

ifswitch の使い分け

主な目安:

for 文の文法

for ( 初期化; 継続条件; 次の一歩 ) {
繰り返す処理;
}

while 文の文法

while ( 継続条件 ) {
繰り返す処理;
}

forwhile の使い分け

主な目安:

do ... while

文法:

do {
繰り返す処理;
} while ( 継続条件 );

繰り返しの普遍条件

(loop invariant)

@@@check also assets/loop_invariant.html

繰り返しの普遍条件の例

(Russian peasant multiplication)

a0, b0: 最初の (被) 乗数 (入力)

sf: 最後の合計 (出力)

目的: sf = a0 · b0

普遍条件: ai · bi + si = a0 · b0

数学的帰納法の基底:
i = 0 の場合、
初期化により s0 = 0 ⇒
a0 · b0 + s0 = a0 · b0 + 0 = a0 · b0

 

繰り返しの普遍条件の例: 帰納

証明するもの: 普遍条件が 0 ≦ if の時に成立

数学的帰納法の帰納のステップ:

普遍条件が k 回目の最初に成り立てば、 k 回目の最後、すなわち k+1 回目の最初にも成立

ak · bk + sk = a0 · b0

ak が偶数の場合: a0 · b0 = ak · bk + sk = ak/2 · bk·2 + sk = ak+1 · bk+1 + sk+1 = a0 · b0 (/ は整数の割算)

ak が奇数の場合: a0 · b0 = ak · bk + sk = ak/2 · bk·2 + bk + sk = ak+1 · bk+1 + sk+1 = a0 · b0

 

繰り返しの普遍条件: 修了の証明

終了条件: ai = 0

ai+1 = ai / 2 によって、 ai が毎回半減、いずれ 0 になる

結果の確認:

ai = 0 の場合、a0 · b0 = ai · bi + si = 0 · bi + si = 0 + si = si

よって ai = 0 の場合, si が出力として正しい

今週の演習問題

部分点の評価

表示の例:

...
Your program only passed 17 out of 20 tests.
You received 72.0 out of 100 points.

 

次回の準備