第 11 回課題「プログラミング 2」 を読んで第 11 回課題を提出しなさい.
メソッドの利用などを学習し, 最終的に以下のプログラムを作成することを目標とする.
プログラム全体を一度に設計するよりも プログラムをいくつかのまとまった機能に分けて設計するほうが効率がよい. Java ではメソッドを利用してモジュール化することができる. モジュール化の例としてうるう年を判定するメソッドを作成する.
どんな全体プログラムを設計するにせよ,ある年がうるう年かどうかを 判定するプログラム部分があれば便利だと考えられる. うるう年を判定するテストプログラムを書くことから始める. まずはうるう年の判定規則を厳密に記述しなければならない.
基本的には 4 で割り切れる年がうるう年であるが,例外として 100 で割り切れる 年はうるう年でない.さらに例外があり,400 で割り切れる年はうるう年である. 図示すると図 1 のようになる.図 1 で斜線で示された範囲の年がうるう年である.
図 1 うるう年の判定
うるう年を判定するプログラムを完成させよ. ある数で割り切れるかどうかはモジュロ演算子 "%" を利用すればよ い.例えば y % 4 の値は y が 4 で割り切れるとき,またそのときのみ 0 とな る. うるう年の判定が単に「4 で割り切れたらうるう年」 であればプログラム 25 なる.プログラム 25 の if 文の判定式を書き換え, プログラムを完成させよ. プログラムをテストせよ.テストデータとして,上の図 1 のそれ ぞれの集合に属するデータについて実行して確認せよ.
プログラム 25
class Example25{ public static void main(String args[]){ int y; y = 2004; if (y%4 == 0){ System.out.println(y+" is a leap year"); } else { System.out.println(y+" is not a leap year"); } } }
if 文の条件式などで用いられる式の判定結果は 「真」か「偽」の 2 通りの値をもつ. この型を boolean(真偽値) 型といい, boolean 型の変数を利用して記憶することができ る.記憶した真偽値は式と同様に if 文の条件式などの場所で 使うことができる. 上のプログラム 25 の条件式を一旦 boolean 型の変数 b に格納するプログラムに書き直すと以下の通りになる. b には判定結果に応じて真を表す値か偽を表す値の いずれかが格納される. print 文で真偽値を文字列 "true" か "false" に変換して出力し,確認することができる.
プログラム 26
class Example26{ public static void main(String args[]){ int y; boolean b; y = 2004; b = y % 400==0 || (y % 4 == 0 && y % 100 != 0); System.out.println("b is "+b); if (b){ System.out.println(y+" is a leap year"); } else { System.out.println(y+" is not a leap year"); } } }
プログラム 26 で, うるう年かどうかを記憶する真偽値 b を求める部分を独立したモジュールにし, 繰り返し利用しやすくする.まずどのようなモジュールを作ればよいか, 特に入力と出力とその関係を厳密に記述する. モジュールの名前は Java の既存の語に衝突しなければなんでも良いので 以下のように決める.
isLeap メソッドを作成してメインから呼び出す形に書き換えたのが以下のプロ グラム 27 である. 但し,テスト用に真偽値を出力ししていた println 文は削除した.
プログラム 27
class Example27{ public static void main(String args[]){ int y; y = 2004; if (isLeap(y)){ System.out.println(y+" is a leap year"); } else { System.out.println(y+" is not a leap year"); } } static boolean isLeap(int year){ boolean b; b = year % 400==0 || (year % 4 == 0 && year % 100 != 0); return (b); } }
この例のようにクラス内に複数のメソッドがある場合, プログラムが実行されると main メソッドが実行される. 他のメソッドはほかのメソッドから呼び出されて初めて実行される. この例では if(isLeap(y)){ の文でメソッド isLeap が int 型の変数 y の値を入力として呼び出される.
static boolean isLeap(int year){
の行で isLeap は int 型の値を入力として呼び出され, boolean 型の値を返すメソッドとして宣言されている. 入力の値,すなわち main メソッドで y に入っていた値 2004 が int 型の変数 year にコピーされ,isLeap メソッドが 実行される. メソッドに渡される入力の値を引数(ひきすう)という. isLeap 内では引数の値のコピーを格納した 変数 year の値を使用する.
b = year % 400==0 || (year % 4 == 0 && year % 100 != 0);
の右辺は真偽値をとる式で真か偽の値が設定される. 結局 year がうるう年であれば b に真が,そうでなければ偽が設定される.
return (b);
で isLeap の動作は終了し, 計算された b の値で main で isLeap が呼び出された場所を置き換えて main の続きを実行する.
isLeap 内で利用される引数変数 year は main の変数 y のコピーであるため, たとえ isLeap 内で値を変更しても main の変数 y にその影響は及ばない. これを「値渡し」という.また,return 文の括弧内に複雑な式を書いてもよい ので.isLeap は以下のように変数 b を使わずに書くこともできる.
プログラム部分 28
static boolean isLeap(int year){ return (year % 400==0 || (year % 4 == 0 && year % 100 != 0)); }
メソッド isLeap をテストしたい. 1900 年から 2004 年までについてうるう年かどうかを表示するプログラムを作れ.
ヒント: プログラム 27 の main でループを利用すればよい.
年と月の値からその月が何日まであるのかを計算するメソッドがあると 便利と考えられる.
ある月が何日まであるかを知りたい場合,
の 2 つのデータがあるれば計算できる.
すでにうるう年であるかどうか判定するメソッド isLeap があるので簡単に構成することができる.
メソッド dateofym() の仕様
入力: int year (年を表す),month (月を表す)
出力: int 型で year 年 month 月が何日まであるかを返す
上の仕様のメソッド dateofym を作成せよ. 正しく作成できれば,例えば dateofym(2004,2) の値が 29 を返す.
dateofym の宣言は以下のようになる.内容を埋め,完成させよ.
プログラム部分 dateofym
static int dateofym(int year, int month){ <year 年 month 月の日数を return する.> }
作成したメソッドをいろいろな入力でテストせよ. 例えば,System.out.println(dateofym(2004,2)); とすれば 29 が出力される. このメソッドが完成していないと以下のプログラムは動かない.