C言語でカレンダーを表示する

  • このエントリーをはてなブックマークに追加
  • LINEで送る

今日から学生は夏休みに入ります。
1期の授業の終わりに次の課題を出しました。

Q. カレンダーを表示するプログラムを作成せよ。入力は西暦年と月とする。
なお、西暦元年1月1日は月曜日である。

カレンダーを作成するためには、まず閏年(うるうどし)を考慮しなければなりません。閏年の定義は「西暦年が400で割り切れる年」又は「西暦年が4で割り切れ、かつ100で割り切れない年」です。
C言語で書くと、

if (year % 400 == 0){
<閏年である>
}
else if(year % 4 == 0 && year % 100 != 0){
<閏年である>
}

となります。
解答例では、この閏年判定は関数化してあります。
月毎の日数は基本的に2月以外は変化はないため、配列に順番に入れておきます。
2月は閏年ではないときの日数28日とします。

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

閏年の場合は、1日足して29日としています。

 if(checkUruu(year)) month_date[1]++; // 閏年の2月分

カレンダー風に表示するために1週間(7日分)表示したら改行をして、それっぽく見せます。

  if(cnt % 7 == 0) printf(“\n”);

閏年をチェックする関数(checkUruu)では、閏年だった場合、戻り値を「1」としていますが、これは閏年でない場合の28日に1日足して29日にするために使っています。

 // 日数計算
 for(i=1; i<=year-1; i++){
  total = total + 365 + checkUruu(i);
 }

このときの変数totalは、指定した西暦年の前の年までのトータル日数を計算するために使っています。その後に指定した西暦年の指定月の前の月までの日数をtotalに入れています。

 for(i=0; i<month-1; i++){
  total = total + month_date[i];
 }

total変数の目的は、月の初日が曜日によってずれるため、スペース表示を行うために使っています。
解答例は分かりやすいように月曜日から表示しています。

 for(i=1,cnt=0; i<=total%7; i++, cnt++) printf(” “); // その月の初日の曜日のずれを考慮

【C言語でカレンダー表示をするプログラム】

/*
xCalendar.c 西暦年を月を指定するとカレンダーを表示する
          09/07/07(火) Syuichi Takeda wrote.
*/
#include <stdio.h>
int checkUruu(int);  /* 閏年チェック関数: 閏年なら1を返す */
int main(void)
{
 int year, month;
 int month_date[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 int total = 0;
 int i, cnt;
 
 // 西暦年入力
 do{
  printf(“西暦年を入力して下さい “);
  scanf(“%d”, &year);
 } while(year < 1);
 
 // 月日入力
 do{
  printf(“月を入力して下さい “);
  scanf(“%d”, &month);
 } while(month < 1 || month > 12);
 
 // 日数計算
 for(i=1; i<=year-1; i++){
  total = total + 365 + checkUruu(i);
 }
 
 if(checkUruu(year)) month_date[1]++; // 閏年の2月分
 
 for(i=0; i<month-1; i++){
  total = total + month_date[i];
 }
 
 // カレンダー表示
 printf(“\n\n\t%d年\n%2d月\n”, year, month);
 printf(” 月 火 水 木 金 土 日\n”);
 for(i=1,cnt=0; i<=total%7; i++, cnt++) printf(”   “); // その月の初日の曜日のずれを考慮
               // 月曜->ずらさない 火曜->1日ずらす
 for(i=1; i<=month_date[month-1]; i++, cnt++){
  if(cnt % 7 == 0) printf(“\n”);
  printf(“%3d”, i);
 }
 printf(“\n”);
 
 return 0;
}
int checkUruu(int year) // 閏年なら1を返す
{
 if (year % 400 == 0){
  return 1;
 }
 else if(year % 4 == 0 && year % 100 != 0){
  return 1;
 }
 return 0;
}

【実行結果】

西暦年を入力して下さい 2000
月を入力して下さい 2
     2000年
 2月
月 火 水 木 金 土 日
   1  2  3  4  5  6
  7  8  9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29

意外とこのプログラムWindowsなどのカレンダーより表示できる西暦年の範囲が広くていいですよ。(Windowsのカレンダーだと2009年の時点で1980年からしか表示できない)
この解答例では曜日が月曜から始まっています。
よくあるカレンダー表示みたいに日曜日から始まるようにするには、カレンダー表示の先頭部分を以下のようにします。

 // カレンダー表示
 printf(“\n\n\t%d年\n%2d月\n”, year, month);
 printf(” 日 月 火 水 木 金 土\n”);
 for(i=1,cnt=0; i<=(total+1)%7; i++, cnt++) printf(”   “);

こういったプログラムを作る場合は、実際に紙に書いてみるといいと思います。例えば、西暦元年の1月はどうなるとか、2月になったらどうなるとか言ったように書いてみます。
すると、カレンダーのポイントは月ごとの初日に曜日がずれていくことにあると気づきます。
閏年でない場合は1年間で1日曜日がずれます。
西暦元年の1月1日は月曜日ですが、西暦2年の1月1日は火曜日となります。
閏年だと前の年と比べて、2日ずれます。
とにかく、書いてみることです。
私の場合、まずは学生には曜日を考えずにカレンダーっぽく7日ずつ表示が出来るかどうかを最初に考えさせました。
一度にプログラムすると大変ですが、少しずつプログラムして目的に近づいていくことがベストだと思います。
〓武田〓

  • このエントリーをはてなブックマークに追加
  • LINEで送る

SNSでもご購読できます。

コメントを残す