メタボ診断プログラムの開発を通じて, 選択制御(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通りのまま判定するのは コードが冗長すぎるので減点対象となる.
提出: