カレンダー作るのちょろすぎて草

この記事は暫定版です。

…煽り全開のタイトルですみません。

一応課題のカレンダーを表示するプログラムについて,助言と言うか手引ができたら良いかなと思ってこの記事を書いています。

コードを実際に見せることはしません。俺0点になりたくないので…

ですが部分的に「こうすると良いかもね」みたいな例を示すかもしれないのでご参考までにどうぞ。

注意

あくまでこの記事は考え方を提示するものであって,このコードをコピーして作れるように記事は組み立てていませんのでご注意ください。

みんなに落単してほしくないからそうしてます。ご理解よろしくお願いします。

あと僕も落単したくないです。

作りたいもの

最終的にはこのように表示するプログラムを作るのが目標です。

実現方法

考察

まずは実現方法について考察してみましょう。

今回の動作要件としては

・年/月を入力すると,その年のその月のカレンダーを表示する

・月初めの曜日の判定は,西暦1年1月1日を月曜日と定めたことからの加算で行う

・C言語のライブラリや関数などの機能は使ってはいけない

etc..

でした。これらの要件に沿うように,どのようにして実現するのかを考えてみます。

表示に必要な要件

まず,カレンダーを表示するために必要な要件を考えてみましょう。

・1日が何曜日か

・その月は何日までか

この2つがあればカレンダーを表示することができるはずです。

ではそれぞれの判定のしかたについて考えていきます。

1日が何曜日か

これを判定するためには,

・西暦1年1月1日が月曜日であるということ

・表示したい年月の1日が,西暦1年1月1日から数えて何日経過したか

という2つが必要になります。具体的にどのように実現するかというと,

<経過日数> % 7 = <インデントする数>

このようにすることで,頭からいくつ字下げ(インデント)をすればいいかを計算することができます。

経過日数の計算は次章で。

例えば,西暦1年1月1日は,経過日数1日なので,

1 % 7 = 1

よって下図のように,1つインデント状態(月曜日)になることがわかります。

その月が何日までか

基本この判定は毎月ごとに決まっている値(1月…31日 2月…28日 など)を配列に代入しておいて,繰り返し文を使って表示する時に配列から値を取り出すのが良いと思います。

なので,

int date[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

のようにして配列を作成しておくべきでしょう。

しかしこれだと問題があります。そうです。うるう年の存在です。

うるう年の時は,2月が29日までになりますから,1足してあげる必要があります。

配列の値を別に用意するのは面倒なので,① 入力された年がうるう年かを判定 ② 入力された月が2月かどうかを判定 ③ dateの値に1を足す とすると操作が簡単かと思います。

配列の値を直接書き換えるのは好ましくないので,一度配列の値を変数に取り出すべきでしょう。

まずは変数に取り出します。

int dateA = date[month]

そして,①,②の条件を通し,③をします。

if((year%4==0 && year%100!=0) || year%400==0){
      if(month==2){
           dateA++;
      }
}

こうすることで,「いくつまで繰り返して日付を表示すればいいか」という部分の値が完成します。

この後で dateA をfor文の実行条件に使って式を書いていきます。

経過日数を計算してみよう

先程曜日を求めるには,西暦1年1月1日からの経過日数が必要と言いました。

ではその経過日数を求めてみましょう。

経過日数は,以下のように求められます。

( <入力年>-1 ) * 365 + <入力月-1までの合計日数> + 1 + <うるう年の数>

(入力年-1)×365という操作は,入力年の1年前までの日数をカウントしています。

入力月-1までの合計日数はその名の通り。

そこに+1をするのは,例えば7月を入力したとするならば,上まででカウントされているのは6/30までなので,+1をして7/1までの合計日数にしてあげるというわけです。

うるう年の数は前章で紹介した方法を使います。

1, うるう年の数を数える

一つ変数を用意し,入力年-1年までうるう年の条件に適合するかどうかを試し,適合したら変数をインクリメントする,のような動作でカウントできます。

int leap = 0;
for(i=1;i<year;i++){
    if((year%4==0 && year%100!=0) || year%400==0){
    leap++;
    }
}

2, 入力月-1月までの合計日数を数える

先程用意した月の日数が入っている配列を利用して,入力月-1月までの合計日数を足していきます。

配列の要素は,No.0から始まっていることに注意です。

例) 6月の日数ーNo.5の位置にある

int mdaysum = 0;
for (i=0;i<month-1;i++){
    mdaysum += date[i];
}

3, 今年がうるう年かどうかを判定する

先程のうるう年判定の部分では,今年を含まずに条件を作っていました。

もし今年がうるう年なら,日数に1を加えてあげなければなりません。

そのためにまずはうるう年かどうかを判定しておきます。True(1),False(0)の形で良いと思います。

int thisLeap = 0;
if((year%4==0 && year%100!=0) || year%400==0){
    thisLeap = 1;
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です