条件分岐 ( if 文 ) 第 2 回の講義資料で出題した練習問題や演習問題の計算は, 勿論電卓でもでき, わざわざプログラムを作ってまでするほどの計算ではありませんでした. プログラムによる計算と電卓の計算の きな違いの つが, プログラムには, 条件による処理の分岐, 繰り返しがあることです. まず今回は, 条件による処理の分岐 ( 処理の切り替え と う が適切かもしれません ) の書き について学んでいきます.
if 文の形式と意味 形式 1: if( 式 ) 文式が真のときのみ, 文を実行 形式 2: if( 式 ) 文 1 else 文 2 式が真のとき文 1を実行し, 式が偽のとき文 2を実行 式としては, 関係演算子 : α == β α の値が β と等しいとき真 α!= β α の値が β と異なるとき真 α < β αの値がβより小さいとき真 α > β αの値が βより大きいとき真 α <= β αの値がβ 以下のとき真 α >= β αの値がβ 以上のとき真 四則演算 (C 語では 0( セ ロ ) を偽,0 以外を真として扱う ) 1
例 :if( 式 ) 文 (1/2) あまり意味のあるプログラムではありませんが #include <stdio.h> int main() { int age; /* 入力 */ printf(" あなたの年齢は : "); scanf("%d",&age); /* 結果の表示 */ if(age >= 20) printf(" ビールを飲んでもいいですよ. n n"); 2
例 :if( 式 ) 文 (2/2) 前記のプログラムの if(age >= 20) printf(" ビールを飲んでもいいですよ. n"); の部分では, 変数 age の値が, たとえば,21 ならば, これは 20 以上であるから,age >= 20 が真となり, printf(" ビールを飲んでもいいですよ. n"); が実行され, ビールを飲んでもいいですよ. と表示される. 一方,age の値が,19 の場合は,age >= 20 が偽なので, 何も表示されずにプログラムを終了する. 3
複文 (1/2) if 文において, 条件が真であるときに実行する文が複数あるときは, 中括弧 { で囲む.{ で囲まれた文を複文と呼ぶ. #include <stdio.h> int main() { int age; /* 入力 */ printf(" あなたの年齢は : "); scanf("%d",&age); age >= 20 が真の時は, { で囲まれた文が順に実 /* 結果の表示 */ 行される. if(age >= 20) { printf(" ビールを飲んでもいいですよ. n"); printf(" お酒を飲んでもいいですよ. n"); 4
複文 (2/2) 中括弧を忘れると... #include <stdio.h> int main() { int age; /* 入力 */ printf(" あなたの年齢は : "); scanf("%d",&age); /* 結果の表示 */ if(age >= 20) printf(" ビールを飲んでもいいですよ. n"); printf(" お酒を飲んでもいいですよ. n"); 変数 age の値に関係なく, 赤で示した printf itf 文が実行されてしまう 字下げはプログラムの動作に影響しません. 常に TAB を使って, きれいに字下げしながらプログラムを書くようにすると, このような間違いをプログラムを書いている最中に発見できる. 5
例 : if ( 条件 ) 文 1 else 文 2 (1/2) 次のプログラムは入力した数値 ( 年齢 ) が,20 以上か,20 未満かで表示するものが変わる. #include <stdio.h> int main() { int age; /* 入力 */ printf(" あなたの年齢は : "); scanf("%d",&age); /* 結果の表示 */ if(age >= 20) printf(" ビールを飲んでもいいですよ. n"); else printf(" 飲めるのは水かジュースです. n"); 6
例 : if ( 条件 ) 文 1 else 文 2 (2/2) if ~ else 文に関しても,if の条件式が真のとき実行する文が複数ある場合は, それらの文を { で囲んで複文にする.if の条件式が偽のとき実行する文が複数ある場合も同様に, それらを中括弧で囲む. #include <stdio.h> int main() { int age; /* 入力 */ printf(" あなたの年齢は : "); scanf("%d",&age); /* 結果の表示 */ if(age >= 20){ printf(" ビールを飲んでもいいですよ. n"); printf(" お酒を飲んでもいいですよ. n"); else { printf(" 飲めるのは水かジュースです. n"); printf(" こっそり飲んでいるでしょう. n n"); 7
条件式での間違いについて (1/2) ここで, 条件式に関して犯しやすい間違いについて説明しておく. if 文の条件の式で, ある変数 ( たとえば,x ) の値と式 ( 変数一つや定数も式です ) の値が等しいという条件を, x = 式 と書いてしまう人がいる. これは慣れた人でもよく犯す間違い! 代入文は右辺を計算してその結果を左辺の変数に代入するのだが, 実は代入文も値を返し, 変数 = 式 の返す値は, 右辺の式の値.C 言語では,0 は偽,0 以外は真だから, たとえば, 条件 x = 0 は,x の値に関係なく, 偽, 条件 x = 1 は,x の値に関係なく, 真, y+z が 0 のとき, 条件 x = y+z は,x の値に関係なく偽 となり,x には右辺の値が代入されることになる! 8
条件式での間違いについて (2/2) 以下のプログラムは足し算のテストを行うプログラムのつもりである. 二つの整数を入力し, 続いて2 数の足し算の値を入力する. 入力した答えが合っていれば, 正解です. と表示し, 間違っていれば, 誤りです. と表示することを意図しているのだが, 条件式の誤りのために, 正解が 0 の場合は, 答えとして何を入力しても, 誤りです. と表示され, 逆に正解が 0 でない場合は, 答えとして何を入力しても, 正解です. と表示されてしまう! 正しいプログラムとするには, 条件式を z == x + y としなければならない. #include <stdio.h> it int main() i() { int x,y,z; printf("1 つ目の数は :"); :); scanf("%d",&x); printf("2つ目の数は :"); scanf("%d",&y); printf("%d+%d はいくつになりますか :",x,y); scanf("%d",&z); if(z = x + y) printf(" 正解です. n"); else printf(" 誤りです. n"); 9
演習 (1) (2) 整数を 2 つ入力し, その差の絶対値 ( 違い ) を表示するプログラムを作れ. 第 2 回の演習問題 2.2で作成した sho_int.c, すなわち, 整数を 2つ入力し, その商 (1 番目に入力された数 2 番目に入力された数 ) を表示するプログラムを改良して,2 番目に入力された整数が, 0 の場合 : 0 では割れません と表示する 0 以外の場合 : 商を表示する ようなプログラムを作れ. 約 15 分後に解答例を示します. 10
複雑な条件式 複雑な条件式は, 以下の演算子を組み合わせて作る.!α α でない (α が偽のとき真 ) α β α または β(α, β のうち少なくとも一方が真のとき真 ) α && β α かつ β(α, β がともに真のとき真 ) 例 a > 0 && ( b==2 b==4! (b > a) ) 例 の真偽は, a が -1 の場合 偽 a が 1 で,b が 4 の場合 真 a が 1 で,b が 3 の場合 偽 例 変数 x の値が 5 以上 10 未満のとき真となる式は, 5 <= x && x < 10 注意 : 以下は誤り. 5 <= x < 10 11
if 文の入れ子 (1/3) if ( 条件 ) 文 if ( 条件 ) 文 1 else 文 2 における, 文, 文 1, 文 2が, また if 文や if ~ else 文があっても勿論 OK. これを利用して, 複数の場合に場合分けすることができる. たとえば, 次頁のプログラム ( の断片 ) は,ten が, 80 以上, 70 以上 80 未満, 60 以上 70 未満, 60 未満 の 4 つに場合分けし, それぞれの処理 ( 表示 ) をしている. 12
if 文の入れ子 (2/3) 80 <= ten No 70 <= ten No 60 <= ten No 成績は D ですを表示 Yes 成績はAです if (80 <= ten){ を表示 printf(" 成績はAです. n"); else { Yes if(70 <= ten) { 成績はBです printf(" 成績はBです. n"); を表示 else { if(60 <= ten){ Yes 成績は C です printf(" 成績は C です. n n"); を表示 else { printf(" 成績は Dです. n"); 13
if 文の入れ子 (3/3) 前 のプログラムの断 は, 分かり易さを考えて, 書いているが, 以下のように書いても良い ( こちらの が普通 ). if (80 <= ten) printf(" 成績はAです. n"); else if(70 <= ten) printf(" 成績はBです. n"); else if(60 <= ten) printf(" 成績はCです. n"); else printf(" 成績はDです. n"); このように上手く if 文の入れ子を使うと, 以下のように, 無駄な条件判定を含む複雑な条件式を書く必要がない. if (80 <= ten) printf(" 成績はAです. n"); else if(70 <= ten && ten < 80) printf(" 成績は B です. n n"); else if(60 <= ten && ten < 70) printf(" 成績はCです. n"); else printf(" 成績はDです. n"); 14
課題 ( レポート ) (1) (2) () りんごを幾つか買うとする. りんごの値段は, 一度にたくさん買うとサービスして安くしてくれる. 10 個未満だと,1 つの値段は 100 円, 10 個以上 20 個未満だと,1つの値段は 95 円, 20 個以上だと,1つの値段は 90 円である. 買うりんごの個数を入力すると, その個数のりんごの合計の値段を表示するプログラムを作れ. 西暦を入力すると, その年が閏年ならば, 閏年です と表示し, そうでないならば, 閏年ではありません と表示するプログラムを作れ. ただし, 西暦 x 年が閏年か否かは次のようにして決まる. 基本的には,xが4で割り切れば閏年. ただし,xが4でも100でも割り切れる年は閏年としない. ただし,xが4でも100でも400でも割り切れる年は閏年. (3) 3 つの整数を入力し, それらを 3 辺とする三角形ができるならば, その面積を出力し, そうでないならば, 三角形ではありません! というメッセージを表示するプログラムを作れ ( 次ページヒント参照 ). 15
問題 (3) のヒント & 補足 三辺の長さが a, b, c である三角形がつくれるための条件は, a+b>c かつ b+c>a かつ c+a>b 三辺の長さが a, b, c である三角形の面積は, s(s-a)(s-b)(s-c) ただし,s = (a+b+c)/2 注意 : s を求める際に小数点以下が切り捨てられないようにしよう. 平方根を求める関数は,sqrt たとえば,sqrt(x+1) とすると,x+1 の平方根を返す. ただし, 引数 ( 括弧の中 ) の式は,float 型または double 型でなければならない. sqrt や sin などの数学的関数を使う場合は... プログラム先頭 ( int main() より前のどこか ) に #include<math.h> をつける. また, コンパイルするときは ( ファイル名を AB.c とする ), gcc lm AB.c ( または,gcc lm o AB AB.c) ( イチではなくエル ) 16