課題3 で作成したmycal5.c
になると、だいぶ使い回せるような形に近づいてきた。
しかし、月のはじめの曜日や日数をいちいち与えるのはめんどうである。
できれば、年月を指定すると勝手にコンピュータが月のはじめの曜日や日数を考えてくれる方が利用者には便利である。
良ぉく考える(調べる)と、2月の日数が閏年か平年かで変化する以外は、何月かが分かればその月の日数は判る。 このような場合には、月の日数を配列に入れておいて参照することで、 その月の日数を簡単にコンピュータに指示することができる。
配列とは、同じ型の変数を順に並べておいたものである。
宣言の際に、変数名の後ろに数字をカギ括弧("[" と "]")でくくって宣言すると配列となる。
たとえば int a[5];
と宣言すると次のように、a[0]
, a[1]
, a[2]
, a[3]
, a[4]
の5つの変数が用意される。
括弧でくくられた部分は添字(subscript)と呼ばれる。
数学で出てきた数列などを表現する a0
, a1
の小さい右下の文字と同じ意味と思って良い。
添字は 0 から始まるので、用意される配列の最後は宣言の時の数字より1小さいことに注意しなければならない。
月の日数を保持する配列として、int mdays[13]
を用意し値を代入するプログラムは次のようになる。
int mdays[13]; /* 用意される最大要素の添字を12にするには要素数は13 */
/* mdays[0] は確保されるが使わない */
mdays[1] = 31;
mdays[2] = 28;
mdays[3] = 31;
mdays[4] = 30;
mdays[5] = 31;
mdays[6] = 30;
mdays[7] = 31;
mdays[8] = 31;
mdays[9] = 30;
mdays[10] = 31;
mdays[11] = 30;
mdays[12] = 31;
宣言と同時に初期化を行う場合にのみ、次のようにも書ける。
/* 用意される最大要素の添字を12にするには要素数は13 */
/* 1 2 3 4 5 6 7 8 9 10 11 12 */
int mdays[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
このようにすると、何月かが変数 m
に入っているとすると、
その月の日数はmdays[m]
で求められる。
問題は年によって変化する 2月のデータであるが、問題3 で作成した関数 leap_year
を
用いれば、mdays[2] + leap_year(year)
で求められる。
閏年も含めて、どのような月の日数でも計算できることが分かった。 ということは、年月日をすべて指定すると、ある基準日からの延べ日数が判るはずである。 さらに、曜日は7で割ったあまりで表現することができたのであるから、結局曜日も計算できることになる。
曜日を計算する方法は様々なものがあるが、ここでは、次の方法を使うことにしよう。 次の方法は西暦1600年以降の日付が与えられた場合、その日の曜日を求めるものである。
(365.25*y)
を加える(y/100)
を引く(y/400)
を加える30.6*m + 2.5
を加える
上の手法をプログラムとして表現し、関数calendar
の引数を
「年」と「月」に変更して mycal6.c として保存せよ。
できれば、「2007/11」の用にどの月のカレンダかを表示したり、
何曜日か判るようにしてみよう。
日本語を使う場合は、「ファイル(F)」→「エンコードの種類(D)」で、 あらかじめ「Unicode(UTF-8)」を選択しておく。
曜日計算の 6から 9をまとめて行うと、正しい答えを出さない場合がある。 (たとえば 2007年11月 9日を試してみよ。) なぜだろうか?
課題3 | 日程表 | 課題5 |