今回は、BMIを計算して適正体重かどうかを判定し、その結果をHTMLで出力する演習を行います。
プログラムの処理の流れは、順次・選択・反復の組み合わせでできています。今回は、その中の「選択(条件分岐)」を記述する制御構文(if文、switch文)について説明します。
前回紹介したブール論理演算子などについても具体的にどのように使うかを見ていきましょう。
演算子については以下を御覧ください。
Youtubeの動画でも解説しているので、こちらもぜひ御覧ください。
演習1:BMIを計算し適正体重かを判定
演習プログラムとポイント
前回は演算子を用いてBMIを計算し、その結果をHTMLのテーブルとして出力しました。
今回は、前回の演習プログラムを発展させて、BMIの値に基づいて、「低体重、標準体重、肥満」のどれに該当するかを判定し、その結果も出力するようにしてみましょう。
以下のようにBMIの結果に応じた結果を出力します。
- BMIが18.5未満 → 低体重
- BMIが18.5以上25未満 → 標準体重
- BMIが25以上 → 肥満
このように、BMIの値に基づいてプログラムに違う処理を行わせるため、条件によって処理を選択する「if文」という構文を使います。このような条件による処理の選択を条件分岐ともいいます。
以下が、if文を用いたプログラムです。
Console.Write("身長を入力してください:");
double height = Convert.ToDouble(Console.ReadLine());
Console.Write("体重を入力してください:");
double weight = Convert.ToDouble(Console.ReadLine());
double bmi = weight / (height * height);
Console.WriteLine("<html><body>");
Console.WriteLine($"<p>あなたのBMIは{bmi:F2}</p>");//★(b)
//★(a) ↓ここからが選択(if文)↓
if (bmi < 18.5)
{
Console.WriteLine("<p><strong>低体重</strong>です<p>");
}
else if (bmi < 25)
{
Console.WriteLine("<p>標準体重です</p>");
}
else
{
Console.WriteLine("<p><strong>肥満</strong>です</p>");
}
Console.WriteLine("</body></html>");
このプログラムの前半部分は、前回の演習のプログラムと同じで、ユーザから身長、体重を入力値として受け取り、BMIの計算を行っています。
そして、プログラムの後半((a)の部分以降)では、条件によって処理を選択するためにif文を用いています。これを例にとり、if文について説明します。
結果はHTMLとして出力しています。低体重、肥満の場合には、<strong>タグを使って強調表示をするようにしています。
(b)では、書式を指定することで、計算したBMIの値を小数点数以下2桁のみ表示しています。今回、書式の使い方についても説明します。
ポイント1:選択
処理の選択を行うif文は以下のように、記述します。
if(条件式1){
条件式1が成立したときの処理
}
else if(条件式2){
条件式2が成立したときの処理
}
else if(条件式3){
条件式3が成立したときの処理
}
…
省略
…
else if(条件式N){
条件式Nが成立したときの処理
}
else{
条件式1~Nがいずれも成立しないときの処理
}
ifの後に必要に応じてelse if部分を任意の個数、最後に必要ならばelse部分を1つ記述します。
今回の演習プログラムの(a)以降の部分では、ifの後にelse if、elseがそれぞれ1つずつあり、低体重かどうか?標準体重かどうか?もしくはそれ以外(肥満)か?を判定しています。
条件式ではブール論理演算子、等値演算子、比較演算子などを用いて様々な条件を記述することができます。これらについては、前回勉強しましたね。前回の入門編(3)の記事も参考にしてください。
例えば、ifの条件式では「bmi < 18.5
」という条件が記述されていますが、これは比較演算子です。
また、「if(条件式){…}」の{ }部分をブロックと呼びます。ブロックの中には文を複数記述することができます。
その中で、if文は最も基本的かつよく使われる構文なので、しっかり覚えておきたいですね。
ポイント2:文字列と書式
次に演習プログラムの(b)をみてください。「$"あなたのBMIは{bmi:F2}"
」は文字列補完ですね。
「{bmi:F2}」で変数bmiの値を文字列へ埋め込んでおり、コロン(:)の後の「F2
」が書式となります。「F2
」は小数点以下2桁まで表示するという意味になります。
前回の演習プログラムでは、書式を指定せずにBMIの値を出力していました。
これだと、BMIの値が「21.224489795918366」といった感じで、小数点以下の全ての桁が出力され、見づらかったですね。
今回は書式を使うことで、「21.22」というふうに見やすく表示されるはずです。
書式は他にも様々なものがあります。例えば以下のように数値の前にゼロを埋め込むこともできます。これは例えばファイル名へ連番で数字をつけたいときに便利ですね。
int a = 153;
Console.WriteLine($"{a:D5}"); // 00153と表示される
書式についてより詳しく知りたい場合は、以下のMicrosoft公式リファレンスも参考にしてください。
文字列に対して何らかの演算を行い、最後に整形して出力することは、どのようなアプリケーションでも使う場面が多いため重要です。
実行結果
プログラムを実行すると、以下のようになります。
身長を入力してください:1.71
体重を入力してください:80.2
<html><body>
<p>あなたのBMIは27.43</p>
<p><strong>肥満</strong>です</p>
</body></html>
今回の入力例では、BMIは25以上となったため、「肥満」と判定されています。BMIの値も、「27.43」と小数点2桁までに整形されていますね。
このHTMLをブラウザで表示すると、以下のようになります。
講義1:プログラムの構造
演習で学んだ「選択」はプログラムの構造においてどのように位置づけられるのかをみていきましょう。
復習:プログラムの動き
以前の記事でも解説したように、プログラムは以下の図のように、入力データを受け取り、それに何らかの処理を行い、結果のデータを出力する、ということをしています。
今回の演習プログラムの場合、入力は身長・体重で、処理はBMI計算と適正体重かどうかの判定で、出力はBMIと判定結果が埋め込まれたHTMLコードとなります。
処理は、文(ステートメント)を組み合わせ記述していきます。
前回までの演習プログラムでは、プログラムは上から下へ順番に実行されていくだけでした。
しかし。より複雑な計算を行うには、今回の演習プログラムで使った選択(if文)のように、プログラムの流れを制御する仕組みが必要になります。
プログラムの構造(順次・選択・反復)
プログラムの構造は、順次・選択・反復という基本的な3つの要素に分解することができます。
- 順次:プログラムに書かれた処理を順番に実行する。
- 選択:条件式に従って、次に実行する処理を選択する。if文、switch文などを用いる。
- 反復:同じ処理を繰り返し実行する。for文、foreach文、while文などを用いる。
前回までの演習プログラムは順次のみで構成されています。今回の演習プログラムは順次と選択(if文)の組み合わせで構成されていますね。
今回の記事では「選択」について、詳しくみていきます。反復については、次の回で紹介します。
ステートメント(C#プログラミングガイド)の選択ステートメント、繰り返しステートメントについても参考にしてみてください。
プログラムの構造を順次・選択・反復の組み合わせで記述する方法論は、構造化プログラミングと呼ばれています。
構造化プログラミングは、C#に限らず多くのプログラミングにおいて採用されている考え方です。
講義2:選択
選択を記述するためにC#で用意されている、if文、switch文について紹介します。
if文
if文については、演習プログラムの解説をしたときに、基本的な内容は既に説明しました。
ここでは、いくつか補足をします。
ブロックとステートメント
演習プログラムでは、if文で条件が成立したときの処理を記述する部分はブロックで記述していましたが、文が1つだけであれば、そのまま文を記述することもできます。
//複数の文をブロックでまとめて記述
if(条件式){
文1;
文2;
文3;
}
//文が1つだけ
if(条件式)
文1;
else if部分やelse部分についても同様です。
なので、実は演習プログラムのif文は、ブロックを使わずに以下のようにも書けます。
if (bmi < 18.5)
Console.WriteLine("<p><strong>低体重</strong>です<p>");
else if (bmi < 25)
Console.WriteLine("<p>標準体重です</p>");
else
Console.WriteLine("<p><strong>肥満</strong>です</p>");
こちらの方が少し簡潔になっていますね。
しかし、機能を追加したくなり、if文の中の処理を追加しようとすると、結局はブロックを使うことになるため、基本的には1文であってもブロックを使っておく方がよいかと思います。
if文を使うときにはブロックを使うと決めておいたほうが、コード全体の統一感もありますね。
どのような書き方を選ぶかは、わかりやすさ、変更しやすさ(保守性の高さ)、開発チーム内でコーディングルールなどによって決めます。
入れ子(ネスト)
if文は、以下のように入れ子にして記述することもできます。入れ子にすることをネストするともいいます。
ある条件が成立した場合に、更に別の条件が成立するは判別する…といったときに使います。
if(条件式){
処理
if(条件式){
処理
}
else if(条件式){
処理
}
}
else{
処理
}
if文に限らず、選択や反復を行う制御構文は入れ子構造で記述することができます。
ただし、入れ子構造を多用しすぎると、コードがとても読みづらくなり、理解しにくくなってしまうこともあるため、注意が必要です。
メソッドについては、クラスの説明をするときに紹介します。
様々な条件式
条件式にはブール論理演算子、等値・比較演算子を組み合わせて記述できます。
例えば、演習プログラムを標準体重かそうでないかのみを判定するよう修正すると、以下のようになります。
if (bmi >= 18 && bmi < 25)
{
Console.WriteLine("<p>標準体重です</p>");
}
else
{
Console.WriteLine("<p>標準体重ではありません</p>");
}
「bmi >= 18 && bmi < 25」はブール論理演算子(論理積)と、比較演算子を組み合わせ使っています。bmiの値が18以上25未満であれば、この条件は成立します。
このように、演算子を組み合わせて複雑な条件を記述することも可能です。
条件演算子
if文と似たような処理を行えるものとして、条件演算子があります。前回の記事で登場しましたね。
さきほどの、標準体重かどうかのみを判定するプログラムは、条件演算子を用いて以下のようにも記述できます。
string message = bmi >= 18 && bmi < 25 ? "<p>標準体重です</p>" : "<p>標準体重ではありません</p>";
Console.WriteLine(message);
この例のように、1つの条件式が成立するかしないかのみ判定したいときに、条件演算子を使うと簡潔に記述できる場合があります。
元々の演習プログラムのように、else if部分があり、複数の条件式が成立するかを判定する必要がある場合に、条件演算子は不向きなので、if文を使うと良いでしょう。
if文については、Selection ステートメント – if
、 else
および switch
(C#プログラミングガイド) の前半部分も参考にしてください。
switch文
選択を記述するもう1つの構文としてswitch文があります。
switch文は、指定した式の計算結果がどの値と一致するかを判定し、どの値に一致するかで処理を選択したい場合に使います。
switch文は以下のような構文となります。
switch(式){
case 値1:
式が値1に一致した場合の処理
break;
case 値2:
式が値2に一致した場合の処理
break;
…
case 値N:
式が値Nに一致した場合の処理
break;
default:
式の値が値1~値Nのいずれにも一致しなかった場合の処理
break;
}
これはif文を用い、条件式で等値演算子を使うことで以下のようにも記述できます。
if(式 == 値1){
式が値1に一致した場合の処理
}
else if(式 == 値2){
式が値2に一致した場合の処理
}
…
else if(式 == 値N){
式が値Nに一致した場合の処理
}
else{
式の値が値1~値Nのいずれにも一致しなかった場合の処理
}
このようにif文でも書けるのですが、いずれかの値に一致するかを判定したい場合は、switch文を用いた方が簡潔に記述できますね。
以下は、入力された数字にもとづいて、その月の英語表記を出力するswitch文を使ったプログラム例です。
int month = Convert.ToInt32(Console.ReadLine());
switch (month)
{
case 1:
Console.WriteLine("Janurary");
break;
…省略…
case 12:
Console.WriteLine("December");
break;
default:
Console.WriteLine("1~12の範囲で入力してください");
break;
}
switch文については、Selection ステートメント – if
、 else
および switch
(C#プログラミングガイド) の後半部分も参考にしてください。
本記事では紹介しませんが、switch文はC#7.0以降、大幅に強化されて様々な記述ができるようになっています。例えば、以下のようなことが可能となっています。
- 型による分岐
- switchを式として記述
- パターンマッチング
特に、パターンマッチングはプログラムをより簡潔に書くための非常に強力な機能です。しかし、これらの話はそれだけでけっこうなボリュームがあるため、また別の機会に紹介します。
興味のある方は、パターンマッチングの概要C#ガイドを参考にしてみてください。
まとめ
今回は、選択を行うif文、switch文について学びました。
これで、ユーザから受け取ったデータに様々な計算を行い、計算結果のデータが特定の条件を満たしているかを判定し、判定結果に従って処理を選択することができるようになりました。
また、プログラムの構造は順次・選択・反復という3つの基本要素で構成されていることもわかりました。次回は、反復を行うfor文などについて説明していきます。