講座全体の概要
プログラミング基礎講座の第6回の後半です。講座全体の概要は以下の記事ゼロから始めるプログラミング基礎講座 第1回【講座の概要・目的】をご覧ください。
前半の内容
前半はif文での基本の条件分岐を学習しました。後半はこれを発展させたif-else文と、複合条件、ネストについて学習していきます。また、もう1つの条件分岐switch文についても簡単に紹介します。
準備として、Visual Studio で新しいプロジェクトを作成しましょう。名前は「BasicCourse6_2」とします。
if-else文について
前半で学習した単純なif文では条件を満たした場合のみ処理を行い、満たさなかった場合はなにもできませんでした。これから学習するif-else文では条件を満たした場合と、満たさなかった場合にそれぞれ異なる処理を行うことができます。
if-else文の構文は下記の通りです。各処理ブロックには複数の処理を記述でき、ブロックごとにまったく異なる処理が行えます。[ ]はその部分が省略可能であることを表しています。
if (条件式1) { 処理ブロック1 }
[else if (条件式2) { 処理ブロック2 }]
[else if (条件式3) { 処理ブロック3 }]
・
・
・
[else { 処理ブロックn }]
分岐条件の評価順序について
分岐の条件判定は上から、条件式1、条件式2、条件式3、・・・と評価されて、最初に条件を満たした部分の処理ブロックが実行されます。複数の条件を満たしていた場合でも、処理が行われるのは1つだけとなります。
else ifは複数記述が可能です。また、elseは最後に1つだけ記述可能で、それまでのいずれの条件も満たさなかった場合に処理ブロックが実行されます。elseを省略すると、いずれの条件も満たさなかった場合は何も処理が実行されません。
if-else文の具体例
説明だけだとわかりづらいと思いますので、以下に具体例を記載します。実際にプログラミングをして、デバッグ実行で動作を確認してみてください。ちなみに、連続で何度も実行したい場合は、ブラウザの更新ボタンを押すことで可能です。
namespace BasicCourse6_2.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public int ParentNumber { get; set; }
public int ChildNumber { get; set; }
public string JudgedResult { get; set; }
public void OnGet()
{
ParentNumber = RandomNumberGenerator.GetInt32(1, 14);
ChildNumber = RandomNumberGenerator.GetInt32(1, 14);
if (ChildNumber > ParentNumber)
{
JudgedResult = "ハイ";
}
else if ((ChildNumber < ParentNumber))
{
JudgedResult = "ロー";
}
else
{
JudgedResult = "ドロー";
}
}
}
}
@page
@model IndexModel
@using static IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1>子の数字 を 親の数字 と大小比較した結果を表示する</h1>
<form method="post">
<div class="form-group form-row justify-content-md-around">
<div class="form-inline">
<label asp-for="ParentNumber" class="col-form-label">親の数字</label>
<input asp-for="ParentNumber" type="text" class="form-control" readonly="readonly" />
</div>
<div class="form-inline">
<label asp-for="ChildNumber" class="col-form-label">子の数字</label>
<input asp-for="ChildNumber" type="text" class="form-control" readonly="readonly" />
</div>
</div>
<div class="form-group form-row justify-content-md-around">
<div class="form-inline">
<label asp-for="JudgedResult" class="col-form-label">結果</label>
<input asp-for="JudgedResult" class="form-control" type="text" readonly="readonly" />
</div>
</div>
</form>
</div>
どうでしょうか? 実際にデバッグ実行で1行ずつ見ていけば、動作が理解できると思います。
続いて、複合条件とネストというものについて説明していきますが、準備として画面からの入力を受け付けて処理できるようにしていきたいと思います。
これから作成するプログラムの仕様説明
ハイ・ローの入力を行うラジオボタンとコールを行うボタンを追加
いきなり難しそうな仕様を書きましたが、ちょっと仕事を意識して簡易的な仕様書風にしてみました。これから実際にプログラミングしていきますが、いくつかの段階に分けて徐々に進めていきたいと思います。
まずは入力用の新しい2つの項目を追加しましょう。それにあわせてデザインも変更します。以下のコードを参照してプログラミングしてください。
namespace BasicCourse6_2.Pages
{
public class IndexModel : PageModel
{
中略
public int ParentNumber { get; set; }
public int ChildNumber { get; set; }
public string JudgedResult { get; set; }
public int HighOrLow { get; set; } // ラジオボタン用にこれを追加。
public void OnGet()
{
中略
}
}
}
ラジオボタンの入力を数値で受け取れるようにしています。ハイの時は1、ローの時は2となることを想定しています。
@page
@model IndexModel
@using static IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1>ハイ&ロー</h1>
<form method="post">
<div class="form-group w-100">
<div class="form-inline form-row mb-2">
<label asp-for="ParentNumber" class="col-form-label col-sm-2 offset-sm-3 justify-content-end">親の数字</label>
<input asp-for="ParentNumber" type="text" class="form-control col-sm-2" readonly="readonly" />
</div>
</div>
@* ラジオボタンの追加部分 *@
<div class="form-group w-100 justify-content-center">
<div class="form-row w-100">
<label asp-for="HighOrLow" class="col-form-label col-12 justify-content-center">ハイかローを選択してコールしてください。</label>
</div>
<div class="form-check form-check-inline justify-content-center mb-2">
<div class="mx-3">
<input class="form-check-input" asp-for="HighOrLow" type="radio" value=1 id="radioHigh" required />
<label class="form-check-label" for="radioHigh">ハイ</label>
</div>
<div>
<input class="form-check-input" asp-for="HighOrLow" type="radio" value=2 id="radioLow" required />
<label class="form-check-label" for="radioLow">ロー</label>
</div>
</div>
</div>
@* ボタンの追加部分 *@
<div class="row m-0 w-100 mt-3 mb-5">
<input class="btn btn-primary col-sm-2 offset-sm-5" type="submit" value="コール">
</div>
@* コール後に表示する項目はページ下部に移動 *@
<div class="form-group w-100">
<div class="form-inline form-row mb-2">
<label asp-for="ChildNumber" class="col-form-label col-sm-2 offset-sm-3 justify-content-end">子の数字</label>
<input asp-for="ChildNumber" type="text" class="form-control col-sm-2" readonly="readonly" />
</div>
<div class="form-inline form-row mb-2">
<label asp-for="JudgedResult" class="col-form-label col-sm-2 offset-sm-3 justify-content-end">結果</label>
<input asp-for="JudgedResult" class="form-control col-sm-2" type="text" readonly="readonly" />
</div>
</div>
</form>
</div>
こちらは変更点が多いですが、classの指定はBootstrapを使用した見た目の調整なので、あまり気にせずにコピペしてもらっても結構です。
ラジオボタンはidを自分で指定しています。選択肢ごとに別のidを付けてラベルと関連付けるため、このようにしています。また、「required」を指定することでブラウザが必須入力のチェックを行ってくれます。
プログラミングができたら実行してみましょう。非表示にするべき部分も表示されているはずです。また、コールボタンを押すと数字が0になってしまうと思います。次はここを直していきましょう。
非表示部分に「hidden」を指定
namespace BasicCourse6_2.Pages
{
public class IndexModel : PageModel
{
中略
public int ParentNumber { get; set; }
public int ChildNumber { get; set; }
public string JudgedResult { get; set; }
public int HighOrLow { get; set; }
public bool ChildIsHidden { get; set; } // 子の数字と結果を非表示にするか制御するために追加。
public void OnGet()
{
ChildIsHidden = true; // 初期表示では非表示にしたいので、trueを設定。
中略
}
}
}
ページを表示する時に最初に処理されるのは「OnGet()」でしたね。ここに、初期表示時に子の数字と結果を非表示にする処理を記述していきます。
しかし、Index.cshtml.csでは見た目に関する処理(HTMLを操作する処理)ができません。そのため、ChildIsHiddenがtrueの時には関連の項目を非表示とするように、以下のIndex.cshtmlでChildIsHiddenを参照して見た目を制御します。
<div class="text-center">
<h1>ハイ&ロー</h1>
<form method="post">
中略
@{
string hiddenAttribute = string.Empty;
if (Model.ChildIsHidden)
{
hiddenAttribute = "hidden=\"hidden\"";
}
}
<div class="form-group w-100" @hiddenAttribute>
<div class="form-inline form-row mb-2">
<label asp-for="ChildNumber" class="col-form-label col-sm-2 offset-sm-3 justify-content-end">子の数字</label>
<input asp-for="ChildNumber" type="text" class="form-control col-sm-2" readonly="readonly" />
</div>
<div class="form-inline form-row mb-2">
<label asp-for="JudgedResult" class="col-form-label col-sm-2 offset-sm-3 justify-content-end">結果</label>
<input asp-for="JudgedResult" class="form-control col-sm-2" type="text" readonly="readonly" />
</div>
</div>
</form>
</div>
「子の数字」と「結果」を非表示にしたいので、その2つの要素を囲んでいる親要素のdivに
hidden="hidden"(右辺は省略できるので「hidden」とだけ記述することも可能)
を指定します。これは単にHTMLの記述方法です。
ただし今回は、「ChildIsHidden」プロパティがtrueの場合のみ指定したいので、その制御をC#で記述します。以下のように「@{ }」で囲むことでC#のコードが記述できます。
@{
string hiddenAttribute = string.Empty;
if (Model.ChildIsHidden)
{
hiddenAttribute = "hidden=\"hidden\"";
}
}
ここでは「hiddenAttribute」という変数を宣言して、if文で条件分岐して文字列を設定しています。条件式の部分がプロパティを参照していますが、今までと違って何かを比較する条件にはなっていません。
ChildIsHiddenというプロパティの型はbool型です。実は、条件式とはbool型になるものであれば何でも指定できます。意味はありませんが、trueとかfalseをそのまま指定することもできます。
今までのような比較する条件式も、条件を満たす場合にはtrue、満たさない場合はfalseというbool型の値に変換されているのです。
エスケープ文字(エスケープシーケンス)
プログラムやHTMLなどでは特別な意味をもつ特殊文字というものがあります。下の部分に注目してください。
hiddenAttribute = "hidden=\"hidden\"";
本来設定したい文字列は
hidden="hidden"
です。しかし、「"」(ダブルクォーテーション)はほとんどのプログラミング言語では文字列を表すための特別な意味を持っています。
この特殊文字を文字列の一部として記述したい場合は、特別な意味を取り除いて、ただの文字として明示する必要があります。そのために用いるのがエスケープ文字です。エスケープシーケンスとも言います。言語によって異なる場合もありますが、ほとんどの場合は¥記号と組み合わせたものがエスケープ文字として使われます。
今回の例ですと、「¥"」がエスケープ文字で、特別な意味のないただの「"」だということを表しています。
C#で宣言した変数をHTMLに埋め込む
C#部分でhiddenAttribute変数にHTMLに埋め込みたい文字列を設定できました。条件に該当しない場合は初期値のままで空文字です。あとは以下の部分でHTMLに埋め込みます。
<div class="form-group w-100" @hiddenAttribute>
C#の変数をHTML部分で参照する時には「@」を付けて記述します。Index.cshtml.csの中で宣言した変数やプロパティは「Model.」も付ける必要がありましたが、自分自身のファイル(Index.cshtml)で宣言した変数は「@変数名」で参照できます。
ここまでできたら、実行して非表示になることを確認してください。
続きは・・・
だいぶ長くなってきてしまいましたね。HTMLとCSSの知識がないと、覚えることが多くて大変ですよね。プログラミング学習といってHTML、CSSから始める方も多いようですが、それ自体はプログラミングとは言えず、時間をかけてそれだけを学習するようなものではないんですよね。JavaScriptやPHP、もちろんC#も含むプログラミングをする中で必要な部分だけ一緒に覚えていくものだと思います。実際、私が企業で勤めていた時にも、HTMLやCSSは必要なので自分で調べて使っていましたが、特にまとまった学習時間を取ったことはないです。
さて、前後半で決着をつけるのは厳しくなってしまいました。続きは休憩を挟んでからの延長戦としましょう。お疲れさまでした。
この記事へのコメントはありません。