計算機実習 I

第三回 (2014 年 4 月 24 日)

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

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

Martin J. Dürst

AGU

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

今日の予定

ミニテスト

C 言語の位置づけ

先週の演習について

先回の補足: 優先度

実例: 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, 名前)

if 文の構文 (文法)

(syntax of the if statement (grammar))

if ( 条件式 )
    

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

文法は形だけ、意味 (動作) は別

if 文の意味

(semantics of the if statement)

条件式を評価し、結果が真であればを実行し、偽であればを実行しない。

文の種類

括弧は積極的に使用

誤解を招く書き方:

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

誤解のない書き方:

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

 

ifelse の組み合わせ

if (score >= 60) {
    printf("60 点以上です。\n");
} else {
    printf("来年また会いましょう。\n");
}

if - else if - else の書き方

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

 

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 で使える条件式

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

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

効果:

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

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 を意図的に使わないとき、コメントで明記

 

ifswitch の使い分け

主な目安:

for 文の文法

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

while 文の文法

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

forwhile の使い分け

主な目安:

do ... while

文法:

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

繰り返しの普遍条件

(loop invariant)

繰り返しの普遍条件の例

(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 が偶数の場合: ak · bk + sk = ak/2 · bk·2 + sk = a0 · b0 (/ は整数の割算)

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

よって、sk+1 = sk + ( ak が奇数の場合のみ) bk

ak+1 = ak / 2; bk+1 = bk · 2

 

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

終了条件: ai = 0

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

結果の確認:

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

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

今週の演習問題

部分点の評価

表示の例:

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

 

次回の準備