4. 条件分岐
制御構文(1)
Cプログラミング入門 基幹2 (月4)
Linux にログインして待っていること 以下のサイトを開いておくこと http://www-it.sci.waseda.ac.jp/teachers/w483692/CPR1/制御構造
control flow
•
逐次実行 o 関数は、ブロック内の文を書か れた順に実行する•
条件分岐 o 変数などがある条件を満たす場 合だけ実行する•
ループ(反復) o 条件を満たす間、繰り返し実行 する ※基本的には、条件判断と ジャンプ(実行位置の変更) があれば実現できる。構造化プログラミング
•
初期のプログラミングでは、コード内でジャンプを行う "go to" 命令が多用された o ジャンプしすぎで可読性が低いものをスパゲッティ コードと言って揶揄された•
ダイクストラが go to の有害性を主張o E. Dijkstra. “Go To Statement Considered Harmful”, In Communications of the
ACM, 11(3), 1968, pp. 147-148.
•
構造化プログラミングを提唱o E. W. Dijkstra, “Structured Programming”, In Software Engineering Techniques, NATO Scientific Affairs Division, Brussels, Belgium, 1970, pp. 84–88.
o 順次・反復・分岐によって構造を明確にすることで、 より理解しやすく正しいプログラムを書ける
制御構文
条件分岐
(今回)
if - else
switch – case
(goto)
ループ
(次回)
for
while
do - while
条件分岐 if (1)
•
キーワード if の後の丸括弧内の式の値が o 0 以外(真)なら文を実行する o 0 (偽)なら何も実行しないif
( 式 ) 文
;
if
( 式 )
{
ブロック
}
※本当は、セミコロンで終わる 部分全体を文という。また、中 括弧を含む全体をブロックとい う。しかし、この資料では、わ かりやすいようにこのような書 き方をしている。if 文の例 (1)
•
変数の値によって表示を出すかどうかを決める if(x < 0) { printf("x is negative¥n"); }if 文のスタイル
•
人によっていろんな書き方があるが、インデントなどで、 条件の対象をはっきりさせることが重要 if(x < 0) { printf("x is negative¥n"); } if(x < 0) printf("x is negative¥n"); if(x < 0) { printf("x is negative¥n"); } if(x < 0) printf("x is negative¥n"); 文が一つだけの 場合if 文の例 (2)
•
複数の文に対する条件分岐は、ブロックでなければなら ないことに注意 if(x < 0) { printf("x is "); printf("negative¥n"); } if(x < 0) printf("x is "); printf("negative¥n"); if( 式 ) { ブロック } if( 式 ) 文;比較演算子
•
成り立つ(真)なら 1, 成り立たない(偽)なら 0•
a > b a >= b a < b a <= b•
a == b a != b•
例: x に 5 が入っている場合 x > 5 5 > 5 1 ※ => 等はない ↓ >演算子の評価 ↓ 変数の評価論理演算子
•
論理積 and(かつ; 共に真なら真、それ以外は偽) o a && b•
論理和 or(または; どちらかが真なら真、それ以外は偽) o a || b•
論理否定 not(真なら偽、偽なら真) o ! a !(a > b)•
例: x の値の範囲が −4 < 𝑥 < 10 であるかどうか o (-4 < x) && (x < 10) o [間違い] -4 < x < 10 ※2つ並べない演算子も (別の意味で)あるので、 注意 ※論理演算子のほうが優先順位が低いので 括弧はなくてもいい。読みやすさを重視。if 文のよくあるミス
•
何がおかしいでしょうか?•
-Wall -Wextra などの警告オプションを付けていれ ば、指摘してくれる if(x = 3) { printf("x is 3¥n"); }例題: 平方根を求める
•
入力した実数の平方根を表示する #include <stdio.h> #include <math.h> int main(void) { double x; printf("x = "); scanf("%lf", &x); if(x < 0) { printf("x is negative¥n"); return 1; } printf("root of %f is %f¥n", x, sqrt(x)); return 0; } ※ return で返す値をエラーコードといい、通常、ゼロが正常終了で、ゼロ以外はエラーを表す。 エラーコードにどういう意味を持つかは、各プログラムが仕様書によって明確に定義する。条件分岐 if (2)
•
キーワード if の後の丸括弧内の式が o 0 以外(真)なら文1を実行し、 o 0 (偽)なら文2 を実行する•
文の代わりにブロックを指定してもよいif( 式 ) 文1
;
else 文2
;
if 文の例 (3)
•
変数の値によって表示を変える if(x != 0) { printf("x is non-zero¥n"); } else { printf("x is zero¥n"); } 条件式を単に x としても、 同じ意味になる。 なぜなら、真偽は、 非ゼロ/ゼロで判断される からである。例題: 肥満度判定
•
身長体重に応じて、肥満度を表示する #include <stdio.h> int main(void) { double t, w, BMI; printf("height[m]: "); scanf("%lf", &t); printf("weight[kg]: "); scanf("%lf", &w); BMI = w / (t*t); printf("BMI = %f¥n", BMI); /* BMI に応じて肥満度を表示 */ return 0; }例題: 肥満度判定
•
前のコードの判定部分 ... /* BMI に応じて肥満度を表示 */ if(BMI < 18.5) printf("低体重¥n");if(BMI >= 18.5 && BMI < 25.0) printf("普通体重¥n");
if(BMI >= 25.0 && BMI < 30.0) printf("肥満1度¥n");
if(BMI >= 30.0 && BMI < 35.0) printf("肥満2度¥n");
if(BMI >= 35.0 && BMI < 40.0) printf("肥満3度¥n");
if(BMI >= 40.0)
printf("肥満4度¥n"); ...
例題: 肥満度判定
•
前のコードの判定部分 (else を使った場合) ... /* BMI に応じて肥満度を表示 */ if(BMI < 18.5) printf("低体重¥n"); else if(BMI < 25.0) printf("普通体重¥n"); else if(BMI < 30.0) printf("肥満1度¥n"); else if(BMI < 35.0) printf("肥満2度¥n"); else if(BMI < 40.0) printf("肥満3度¥n"); else printf("肥満4度¥n"); ...例題: 肥満度判定
•
詳しく書くとこういう風になっている ... /* BMI に応じて肥満度を表示 */ if(BMI < 18.5) { printf("低体重¥n"); } else { if(BMI < 25.0) { printf("普通体重¥n"); } else { if(BMI < 30.0) { printf("肥満1度¥n"); } else { if ... } } }整数の複数条件分岐
•
整数の値に応じて、対応 する case ラベルにジャン プする。•
対応するラベルがない場 合は、 default ラベルへ ジャンプする。•
各 case ラベルでは、終わ りに break キーワードで switch を明示的に抜ける•
default ラベルはなくても よいswitch
(整数式)
{
case
整数
:
文
;...
break;
case
整数
:
文
;...
break;
...
default
:
文
; ...
}
※コロンswitch の例
•
たとえば、電話の音声案内で、「○○の場合は 1 を、○○の場合は 2 を押してくだ さい。」というようなものを想定している。 switch(mode) { case 0: printf("mode is 0¥n"); /* mode 0 の処理 */ break; case 1: printf("mode is 1¥n"); /* mode 1 の処理 */ break; ... default:printf("no such mode¥n"); }