講義メモ テキスト編:p.291「DateTime構造体:clock01.cs」から p.291 DateTime構造体:clock01.cs ・構造体の中でもC/C++から引き継がれた日付時刻の機能にメソッドやプロパティを加えたDateTime構造体は活用しやすい。 ・コンソールに関する各種のプロパティやメソッドを併用することで、動きのあるコンソールアプリケーションを作成できる。 p.292(Consoleクラスの静的プロパティと静的メソッド) ・Consoleクラスには、すでに学習した静的メソッドWrite、WriteLine、ReadLineに加えて便利な静的メソッド、静的プロパティが多数提供されており、コンソールを疑似的な実行ウインドウにすることができる ・bool CursorVisible静的プロパティ:falseを設定するとカーソルが見えなくなる。チラつき防止に便利。 ・string Title静的プロパティ:コンソール名を設定できる。 ・void SetWindowsSize(int,int)静的メソッド:ウィンドウの幅と高さを文字数で指定できる ・ConsoleColor BackgroundColor静的プロパティ:ConsoleColor列挙型で背景色を指定できる。例:ConsoleColor.Yellow ・ConsoleColor ForegroundColor静的プロパティ:ConsoleColor列挙型で文字色を指定できる。 ・void Clear()静的メソッド:再描画して設定を反映する(※実行すると文字色・背景色の変更が有効になる) ・void SetCursolPosition(int,int)静的メソッド:カーソルの位置を変える。移動先は文字数。 ・bool KeyAvailable静的プロパティ:キーが押されているとtrueになる アレンジ演習:p.291 clock01.cs ・ストップウォッチにしよう ・実行すると「00:00:00」を表示してカウントを開始する ・これを実現するには、時刻を表す1000万分の1秒刻みのカウンタを返すDateTime構造体のlong Ticksプロパティを用いる ・起動時のTicks値を保持しておいて、Nowで得た時点のTicks値との差で経過時間が得られる ・この差を1000万倍すると秒になるので、これを3600で割った結果が時間、60で割った余りが秒、60で割ってから60で割った余りが分になる 作成例 //アレンジ演習:p.201 clock01.cs using System; class clock01 { public static void Main() { int oldsecond = 0; //秒が変わったどうかの判断用に現在の秒を待避しておく変数 Console.CursorVisible = false; //カーソルを消す Console.Title = "時計"; //コンソールタイトルを設定 Console.SetWindowSize(12, 3); //コンソールウィンドウの大きさを12字×3行に変更 Console.BackgroundColor = ConsoleColor.Yellow; //背景色を黄色に Console.ForegroundColor = ConsoleColor.Black; //文字色を黒色に Console.Clear(); //色の設定を反映する DateTime st = DateTime.Now; //【追加】開始時の現在時刻を得る DateTime mt; //日付時刻構造体を生成 while (true) { //無限ループ mt = DateTime.Now; //現在時刻を得る int lap = (int)((mt.Ticks - st.Ticks) / 10000000L); //【追加】経過秒数を得る int hor = lap / 3600; //【追加】経過秒数から経過時間を得る int min = lap / 60 % 60; //【追加】経過秒数から経過分を得る int sec = lap % 60; //【追加】経過秒数から経過秒を得る if (sec == oldsecond) { //【変更】秒が変わっていなければ continue; //今回のループのこれ以降をスキップ } else { //秒が変わっていれば oldsecond = sec; //【変更】次回の判断用に現在の秒を待避しておく } Console.SetCursorPosition(2, 1); //カーソル位置を2字目に戻す Console.Write("{0:00}:{1:00}:{2:00}", hor, min, sec); //【変更】時分秒を各2桁で表示 if (Console.KeyAvailable) { //何かキーが押されていたら break; //ループを抜ける(終了) } } } } アレンジ演習:p.291 clock01.cs・改 ・ミリ秒も表示するストップウォッチにしよう ・実行すると「00:00:00.000」を表示してカウントを開始する ・経過時間秒数を1万倍するとミリ秒数になるので、これを3600000で割った結果が時間、60000で割ってから60で割った余りが分、1000で割ってから60で割った余りが秒、1000で割った余りがミリ秒 ・表示ウィンドウの大きさを16×3に広げること 作成例 //アレンジ演習:p.201 clock01.cs・改 using System; class clock01 { public static void Main() { int oldmsecond = 0; //【変更】ミリ秒が変わったどうかの判断用に現在のミリ秒を待避しておく変数 Console.CursorVisible = false; //カーソルを消す Console.Title = "時計"; //コンソールタイトルを設定 Console.SetWindowSize(16, 3); //【変更】コンソールウィンドウの大きさを16字×3行に変更 Console.BackgroundColor = ConsoleColor.Yellow; //背景色を黄色に Console.ForegroundColor = ConsoleColor.Black; //文字色を黒色に Console.Clear(); //色の設定を反映する DateTime st = DateTime.Now; //開始時の現在時刻を得る DateTime mt; //日付時刻構造体を生成 while (true) { //無限ループ mt = DateTime.Now; //現在時刻を得る int lap = (int)((mt.Ticks - st.Ticks) / 10000L); //【変更】経過ミリ秒数を得る int hor = lap / 3600000; //【変更】経過ミリ秒数から経過時間を得る int min = lap / 60000 % 60; //【変更】経過ミリ秒数から経過分を得る int sec = lap / 1000 % 60; //【変更】経過ミリ秒数から経過秒を得る int mil = lap % 1000; //【追加】経過ミリ秒数から経過ミリ秒を得る if (mil == oldmsecond) { //【変更】ミリ秒が変わっていなければ continue; //今回のループのこれ以降をスキップ } else { //ミリ秒が変わっていれば oldmsecond = mil; //【変更】次回の判断用に現在のミリ秒を待避しておく } Console.SetCursorPosition(2, 1); //カーソル位置を2字目に戻す Console.Write("{0:00}:{1:00}:{2:00}.{3:000}", hor, min, sec, mil); //【変更】時分秒ミリ秒を表示 if (Console.KeyAvailable) { //何かキーが押されていたら break; //ループを抜ける(終了) } } } } p.294 練習問題 1 ヒント ・プロパティによる制限なので、クラス内でのエラー表示は不要(するならmain側で) ・偶数は整数なので、構造体のデータメンバの型をint型(またはlong型)にすると良い ・偶数しか保持できないようにするには、データメンバへの直接アクセスを禁止するためprivateにする ・このデータメンバを扱うプロパティを定義し、setにおいてvalueの値が偶数かチェックしてから代入する ・getは通常形式で良い 作成例 //p.294 練習問題 1 ex1101.cs using System; struct EvenOnly { //構造体の定義 private int x; //非公開にすることで偶数以外の直接代入を防止する public int X { //偶数のみをセットできるプロパティ get { return x; } set { x = (value % 2 == 0) ? value : x; } //偶数の場合のみセット } } class ex1101 { public static void Main() { EvenOnly eo = new EvenOnly(); //構造体オブジェクトを生成 eo.X = 6; //プロパティを用いて偶数を設定すると Console.WriteLine("偶数設定後:{0}", eo.X); eo.X = 5; //プロパティを用いて奇数を設定しようとしたが Console.WriteLine("奇数設定後:{0}", eo.X); } } 第12章 デリゲートとイベント p.295 デリゲートとは ・メソッドへの参照を保持しておいて、これを用いてメソッドを呼び出せる仕掛け ・つまり、デリゲートを通じてのメソッドの呼び出しが可能 ・C/C++における「関数へのポインタ」と同じ考え方を洗練したもの ・イベント処理などで必須のテクニック ・宣言書式: delegate メソッドの戻り値型 デリゲート名(メソッドの引数リスト); ・例:bool answer(int x){…}メソッド用のデリゲートmdならば、delegate bool md(int w) とする ・利用にはデリゲートオブジェクトの生成が必要で、この時に呼び出したいメソッドの指定もできる ・生成書式: デリゲート名 参照変数 = new デリゲート名(メソッド名); ・例:bool answer(int x){…}メソッド用のデリゲートmdならば、md mymd = new md(answer); ・デリゲート経由で指定済のメソッドを呼び出すには、参照変数を別名のように利用できる ・例: bool b = mymd(5); // answer(5)が呼ばれ戻り値が返される p.297 delegate01.cs について ・Main()メソッドの戻り値をint型にしているが、この場合、必要性はないので、いつもの通り voidにして良い ・よって「return 0;」も不要 p.297 delegate01.cs //p.297 delegate01.cs using System; delegate void MyDelegate(); class delegate01 { public static void show() { //Main()メソッドから呼ばれる静的メソッド Console.WriteLine("呼ばれました"); } public static void Main() { //直接showメソッドを呼び出す show(); //デリゲートの作成 MyDelegate md = new MyDelegate(show); //デリゲートを通してshowメソッドを実行 md(); } } テキスト編次回予告:p.298「(別のクラスにあるメソッドをデリゲートで扱う)」から