【C言語】カレンダー表示プログラム(全部公開)

プログラミング知識

今回はC言語でカレンダーを表示するプログラムを作ってみます。

プログラムの仕様
  • 年月が入力されると、その年月のカレンダーを表示する。
  • 週のはじめは日曜日とする。

プログラム設計

うるう年は次のルールで決められています。

(1)4で割切れる年は、うるう年である
(2)(1)の例外として100で割切れる年は、うるう年ではない
(3)(2)の例外として400で割切れる年は、うるう年である

処理フローは次のように考えます。

  1. 年、月を入力する(年月が正しいかのチェックもする)
  2. 入力された年がうるう年かチェックする
  3. 入力された月の日数を得る
  4. 入力された月の1日の曜日を得る
  5. 表示する。

プログラミング

まずはベースになる年を決めました。ベースの年は2000年にします。2000年の1月1日は土曜日です。

各月の日付の配列も用意しておきます。うるう年用の配列も用意します。月を英語表示したかったので、月名の配列も用意しています。

#include <stdio.h>; #define BASEYEAR 2000 const char DAYS[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; const char DAYS_LEAP[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; const char MONTH_NAME[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; int main (){ int firstDay = 0; //0:saturday
Code language: C++ (cpp)

年月の入力とチェックの関数を作ります。ベースを2000年としているので、年の入力は2000まで制限します。

printf("Year-->;"); scanf("%d", &year); printf("Month-->;"); scanf("%d", &month); if (check_ym(year, month) != 0) { printf("year or month have an error.\n"); return -1; } int check_ym(int y, int m){ if (y < 2000 || m < 1 || m < 12) { return -1; } return 0; }
Code language: C++ (cpp)

入力された年がうるう年かをチェックします。うるう年の考え方は前述のとおりです。ちなみにうるう年のことはLeap yearといいます。このあとの曜日の計算でその意味が分かります。

うるう年だったらうるう年の日付配列を、それ以外なら通常の日付配列をdaysにセットします。

const char *days; /* うるう年かチェック */ if (check_leap_year(year) > 0) { days = DAYS_LEAP; } else { days = DAYS; } /* うるう年のチェック */ int check_leap_year(int y){ int leap = 0; if (y % 4 == 0) { if (y % 100 == 0) { if (y % 400 == 0) { leap = 1; //うるう年 } } else { leap = 1; //うるう年 } } return leap; }
Code language: C++ (cpp)

続いて指定された月の1日の曜日を求めます。今回は2000年1月1日(土曜日)をベースにしたので、土曜日を0として考えます。

一年は365日なので、一年後の同じ日は一日分曜日が進みます。うるう年では1日多いので、二日分曜日が進みます。このように普通の年より曜日が飛ぶので、うるう年はLeap(飛躍)Yearと呼びます。

そして所望の月まで日付を足しこみ、最後に7で割った余りを求めれば、曜日が求まります。

int get_1st_dayofweek(int y, int m, const char d[]){ int dayOfWeek = 0; //0:saturday /* 曜日は1年で1日進む */ dayOfWeek = (y - BASEYEAR); /* 曜日はうるう年では2日進む */ for (int i = BASEYEAR; i < y; i++) { dayOfWeek += check_leap_year(i); } /* 各月分の日付を足す */ for (int j = 0; j < m-1; j++) { dayOfWeek += d[j]; } /* 最後に7で割ると、その月の1日の曜日が求まる */ dayOfWeek %= 7; return dayOfWeek; }
Code language: C++ (cpp)

最後にカレンダーの表示をします。まずは1日を表示する位置まで空白を挿入します。日曜日なら空白は表示せずに土曜なら6日分空白を表示します。

そこから日付を表示していきます。土曜日まで表示したら改行を入れます。

/* 1日の曜日まで空白を挿入 */ for(int i = 0; i < (firstDay + 6) % 7; i++) { printf(" "); } /* 日付の表示 土曜日(0)で改行 */ for(int i = 1; i <= days[month-1]; i++) { printf(" %2d", i); if(firstDay == 0) { printf("\n"); } firstDay = (firstDay + 1) % 7; }
Code language: C++ (cpp)

全体プログラム

全体のプログラムは次のようになりました。

#include <stdio.h> #define BASEYEAR 2000 const char DAYS[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; const char DAYS_LEAP[12] = {31,29,31,30,31,30,31,31,30,31,30,31}; const char MONTH_NAME[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; int check_ym(); int check_leap_year(); int get_1st_dayofweek(); int main (){ int year, month; const char *days; int firstDay = 0; //0:saturday printf("Year-->"); scanf("%d", &year); printf("Month-->"); scanf("%d", &month); /* 年月が正しいかチェック */ if (check_ym(year, month) != 0) { printf("year or month have an error.\n"); return -1; } /* うるう年かチェック */ if (check_leap_year(year) > 0) { days = DAYS_LEAP; } else { days = DAYS; } /* 1日の曜日を取得 */ firstDay = get_1st_dayofweek(year, month, days); /* 年月を表示 */ printf("\t%d\n\t%s\n", year, MONTH_NAME[month-1]); /* 1日の曜日まで空白を挿入 */ for(int i = 0; i < (firstDay + 6) % 7; i++) { printf(" "); } /* 日付の表示 土曜日(0)で改行 */ for(int i = 1; i <= days[month-1]; i++) { printf(" %2d", i); if(firstDay == 0) { printf("\n"); } firstDay = (firstDay + 1) % 7; } return 0; } /* 年月が正しいかチェック */ int check_ym(int y, int m){ if (y < BASEYEAR || m < 1 || m > 12) { return -1; } return 0; } /* うるう年のチェック */ int check_leap_year(int y){ int leap = 0; if (y % 4 == 0) { if (y % 100 == 0) { if (y % 400 == 0) { leap = 1; //うるう年 } } else { leap = 1; //うるう年 } } return leap; } int get_1st_dayofweek(int y, int m, const char d[]){ int dayOfWeek = 0; //0:saturday /* 曜日は1年で1日進む */ dayOfWeek = (y - BASEYEAR); /* 曜日はうるう年では2日進む */ for (int i = BASEYEAR; i < y; i++) { dayOfWeek += check_leap_year(i); } /* 各月分の日付を足す */ for (int j = 0; j < m-1; j++) { dayOfWeek += d[j]; } /* 最後に7で割ると、その月の1日の曜日が求まる */ dayOfWeek %= 7; return dayOfWeek; }
Code language: C++ (cpp)

実行結果

実行してみると、正しく表示できました。

コメント

タイトルとURLをコピーしました