メタボ診断プログラムの開発を通じて, 選択制御(if-else,switch-case)と 型変換について理解しよう.
制御構造とは,一連の処理の実行順序を操ることであり, 基本は次の3パターン:
「順次処理」とか「逐次処理」などともいう.
「条件分岐処理」などともいう. 無条件の分岐処理もあるので,単に「分岐処理」というのは不正確. C言語では,if-else 文や switch-case 文を使う. 今回学習する.
「繰り返し処理」ともいう.これも「条件分岐処理」の一種でもある. C言語では,while 文,do-while 文と for 文がある. 次回学習予定.
ソースコード記述方法:
if (条件式1) { // 式1 は成立しているか? ...; // 式1 が成立の場合の処理 } else if (条件式2) { // 式1 は不成立だったが,式2 はどうか? ...; // 式2 が成立の場合の処理 } else if ... { ...; } else { // すべて不成立だったら... ...; // 不成立の場合の処理 }
条件式としては,等式 x == 0 や不等式 x < 0 などを使える. 条件式に使う比較演算子の種類については教科書 p.77 を参照せよ. なお,比較や代入も計算の一種であり, 「==」や「<」も「+」や「/」と同様に演算子と呼ばれる. また,等式の演算子が「=」ではなく「==」であることに注意しよう. Cでは「=」は代入だ.
ソースコード記述方法:
switch (整数式) { // 実数式は無理 case 値1: ...; // 式 == 値1 の場合の処理 break; case 値2: ...; // 式 == 値2 の場合の処理 break; ... default: ...; // その他の場合の処理 break; }
基本的には,それぞれの場合の区切りに break を付け忘れないように注意しよう. (break を付けないと次の case に連接してしまう. この挙動を活用する場合もある.) 最後の break だけは省略しても問題ない.
計算処理ではデータ型の変化に注意が必要となる.
123/100 → 1 整数同士なら整数 123.0/100.0 → 1.23 実数同士なら実数
123.0/100 → 123.0/100.0 → 1.23 123/100.0 → 123.0/100.0 → 1.23
ただし,変数への代入では少し事情が違う.
double x = 1; → x = 1.0 格上げされる int y = 1.23; → y = 1 格上げされない
(double)1 → 1.0 (int)1.23 → 1
自動変換は便利な場合もあるが,意外な計算結果となる可能性も大きい. 自動変換には頼らないこと. C言語のプログラマは常にデータ型を意識すべき.
BMI(body mass index;ボディマス指数)は, ヒトの肥満度を表す体格指数であり, 次式のように定義されている:
BMI = 体重[kg] ÷ 身長[m]2
なお,身長の単位は cm ではなく m であることに注意しよう.
状態(体型,肥満度) | 指標(BMI値) |
---|---|
低体重(痩せ型) | 18.5未満 |
普通体重 | 18.5以上,25未満 |
肥満(1度) | 25以上,30未満 |
肥満(2度) | 30以上,35未満 |
肥満(3度) | 35以上,40未満 |
肥満(4度) | 40以上 |
いつもの通り,作業用ディレクトリを準備しよう:
$ cd $ mkdir c-0516 $ cd c-0516
とりあえず,BMI値を計算できるだけの基本プログラムを作成しよう.
ソースを編集:
$ vim bmi.c # エディタは何でも OK
#include <stdio.h> int main(void) { int cm, kg; // 身長[cm],体重[kg] を入れるよ double m, bmi; // 身長[m],BMI値 を入れるよ printf("BMIによるメタボ診断\n"); while (1) { printf("----\n"); printf("身長[cm] 体重[kg] > "); scanf("%d %d", &cm, &kg); // 身長・体重の入力 m = cm / 100; // 身長の単位変換 bmi = kg/(m*m); // BMIの計算 printf("BMI = %.1f\n", bmi); // BMIの表示 } return (0); }
コンパイル・実行:
$ cc bmi.c -o bmi
$ ./bmi
...
[Ctrl]+[C]
このソースコードのままだと,BMI 値が明らかに異常... 適切な型変換を追加し,解決しよう:
m = (double)cm / 100.0; // 整数を実数化してから計算
if-else文を利用し,体型診断の機能を追加してみよう.
... int main(void) { ... while (1) { ... printf("BMI = %.1f\n", bmi); // 体型診断 if (bmi < 18.5) { printf("低体重(やせ型)\n"); } else if (bmi < 25.0) { printf("普通体重\n"); } else { printf("肥満\n"); } } return (0); }
条件式の順序に注意しよう. 逆の順序だとどうなるか?
また,else を付け忘れるとどうなるか?
肥満度の階級を算出し, switch-case文によって階級毎にメッセージを変えられるようにしよう.
... int main(void) { ... int n; // 肥満度の階級値を入れるよ printf("BMIによるメタボ診断\n"); while (1) { ... if (bmi < 18.5) { printf("低体重(やせ型)\n"); } else if (bmi < 25.0) { printf("普通体重\n"); } else { //printf("肥満\n");// 肥満度診断 n = (int)((bmi - 25.0)/5.0) + 1; // 肥満度の階級化 switch (n) { case 1: printf("肥満(1度)\n"); break; case 2: printf("肥満(2度)\n"); break; case 3: printf("肥満(3度)\n"); break; default: printf("肥満(4度)\n"); } } } return (0); }
break を付け忘れるとどうなるか?
なお,このプログラムの動作ならば, switch なんて使わなくても実現できそうですが...:
if (n > 4) n = 4; printf("肥満(%d 度)\n", n);
一方,switch を使えば, 各 case によって異なる診断メッセージを追加できそうですね. 「がんばれ」とか「あきらめるな」とか...
余裕ある人は, 「あと何 kg 減量すれば普通体重ですよ」 みたいな処理を追加してみては? (普通体重の BMI値の上限値 25.0 とか 24.9 から 体重の上限値 b を求めてやる. 数式 b = 24.9*m*m; そして,実際の体重との差を求めれば,必要な減量幅となる.)
コンピュータ対ユーザのジャンケンゲームを作成せよ.
要求仕様:次の動作を永久に繰り返す:
実行例:
$ ./jkp
ジャンケンポン {0, 2, 5} > 5
あなたはパー 私はチョキ 私の勝ち
ジャンケンポン {0, 2, 5} > 2
あなたはチョキ 私はチョキ アイコ
ジャンケンポン {0, 2, 5} > 0
あなたはグー 私はグー アイコ
ジャンケンポン {0, 2, 5} > 5
あなたはパー 私はチョキ 私の勝ち
ジャンケンポン {0, 2, 5} > 2
あなたはチョキ 私はパー あなたの勝ち
ジャンケンポン {0, 2, 5} > 0
あなたはグー 私はチョキ あなたの勝ち
ジャンケンポン {0, 2, 5} > 3
何だそれー? 私はチョキ もう一度!!
ジャンケンポン {0, 2, 5} > [Ctrl] + [C]
ヒント:
なお,分類せずに7通り(5通り)のまま判定するとか, 差を使わずに3✕3=9通りのまま判定するのは コードが冗長すぎるので減点対象となる.
提出: