制御構造1(選択)

メタボ診断プログラムの開発を通じて, 選択制御(if-else,switch-case)と 型変換について理解しよう.

教科書の該当範囲:第4章,第6章

基礎知識

制御構造

制御構造とは,一連の処理の実行順序を操ることであり, 基本は次の3パターン:

第1回授業で見た通り 「アルゴロジック」にも説明があったよね.
選択制御文
型変換

計算処理ではデータ型の変化に注意が必要となる.

自動変換は便利な場合もあるが,意外な計算結果となる可能性も大きい. 自動変換には頼らないこと. C言語のプログラマは常にデータ型を意識すべき.

BMI について

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

メタボ診断プログラムの開発

Step 1. BMI値を計算してみる

とりあえず,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;	// 整数を実数化してから計算

Step 2. 体型を診断してみる

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 を付け忘れるとどうなるか?


Step 3. 肥満度を診断してみる

肥満度の階級を算出し, 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]

ヒント:

提出:

勝敗判定のより高度なアルゴリズムについて... ジャンケンのアルゴリズム

(c) 2018, yanagawa@kushiro-ct.ac.jp