/*************************************************************/
/* カレンダーの設定と出力(曜日,祝日等) */
/* 使用方法 */
/* cal y m : 西暦y年m月のカレンダを出力 */
/* cal y m d : 西暦y年m月d日の曜日,祝日情報を出力 */
/* (有効期間:1582年以降,ただし,祝日は別) */
/* coded by Y.Suganuma */
/*************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************************/
/* クラスcalendarの定義 */
/************************/
class Calendar {
int y, m; // 年と月
int m_d; // 一月の日数
int day[31]; // 曜日(0:日曜,・・・,6:土曜)
int hol[31]; // 祝日の種類
// =-1 : 祝日でない
// >=0 : 祝日番号
char h_name[5][30]; // 祝日の名前
public:
Calendar(){} // コンストラクタ
/**********************************/
/* クラスCalendarのコンストラクタ */
/* y_i, m_i : 年と月 */
/**********************************/
Calendar::Calendar(int y_i, int m_i)
{
int d, i1, k1, yo, y1, m1;
/*
年と月の設定
*/
y = y_i;
m = m_i;
/*
日にちと曜日の設定
*/
// 1日の曜日
y1 = y;
m1 = m;
d = 1;
if (m1 < 3) {
y1--;
m1 += 12;
}
yo = (y1 + (y1 / 4) - (y1 / 100) + (y1 / 400) + (13 * m1 + 8) / 5 + d) % 7;
// 一月の日数
if (m == 2) {
if (y%4 == 0 && y%100 != 0 || y%400 == 0)
m_d = 29;
else
m_d = 28;
}
else if (m == 4 || m == 6 || m == 9 || m == 11)
m_d = 30;
else
m_d = 31;
// 各日の曜日の設定
for (i1 = 0; i1 < m_d; i1++) {
day[i1] = yo;
yo = (yo + 1) % 7;
}
/*
祝日の設定
*/
for (i1 = 0; i1 < m_d; i1++)
hol[i1] = -1;
switch (m) {
// 1月
case 1:
// 元日(1月1日)
hol[0] = 0;
strcpy(h_name[0], "元日");
if (day[0] == 0) {
hol[1] = 1;
strcpy(h_name[1], "振替休日(元日)");
}
// 成人の日(1月の第2月曜日)
k1 = 0;
for (i1 = 0; i1 < m_d && k1 < 2; i1++) {
if (day[i1] == 1) {
k1++;
if (k1 == 2) {
hol[i1] = 2;
strcpy(h_name[2], "成人の日");
}
}
}
break;
// 2月
case 2:
// 建国記念日(2月11日)
hol[10] = 0;
strcpy(h_name[0], "建国記念日");
if (day[10] == 0) {
hol[11] = 1;
strcpy(h_name[1], "振替休日(建国記念日)");
}
break;
// 3月
case 3:
// 春分の日(3月20日頃)
if (y < 2100)
d = (int)(20.8431 + 0.242194 * (y - 1980) - (y - 1980) / 4) - 1;
else
d = (int)(21.8510 + 0.242194 * (y - 1980) - (y - 1980) / 4) - 1;
hol[d] = 0;
strcpy(h_name[0], "春分の日");
if (day[d] == 0) {
hol[d+1] = 1;
strcpy(h_name[1], "振替休日(春分の日)");
}
break;
// 4月
case 4:
// みどりの日(4月29日)
hol[28] = 0;
strcpy(h_name[0], "みどりの日");
if (day[28] == 0) {
hol[29] = 1;
strcpy(h_name[1], "振替休日(みどりの日)");
}
break;
// 5月
case 5:
// 憲法記念日,国民の休日,こどもの日(5月3,4,5日)
hol[2] = 0;
strcpy(h_name[0], "憲法記念日");
hol[3] = 1;
strcpy(h_name[1], "国民の休日");
hol[4] = 2;
strcpy(h_name[2], "こどもの日");
if (day[4] == 0) {
hol[5] = 3;
strcpy(h_name[3], "振替休日(こどもの日)");
}
break;
// 6月
case 6:
break;
// 7月
case 7:
// 海の日(7月20日)
hol[19] = 0;
strcpy(h_name[0], "海の日");
if (day[19] == 0) {
hol[20] = 1;
strcpy(h_name[1], "振替休日(海の日)");
}
break;
// 8月
case 8:
break;
// 9月
case 9:
// 敬老の日(9月15日)
hol[14] = 0;
strcpy(h_name[0], "敬老の日");
if (day[14] == 0) {
hol[15] = 1;
strcpy(h_name[1], "振替休日(敬老の日)");
}
// 秋分の日(9月23日頃)
if (y < 2100)
d = (int)(23.2488 + 0.242194 * (y - 1980) - (y - 1980) / 4) - 1;
else
d = (int)(24.2488 + 0.242194 * (y - 1980) - (y - 1980) / 4) - 1;
hol[d] = 2;
strcpy(h_name[2], "秋分の日");
if (day[d] == 0) {
hol[d+1] = 3;
strcpy(h_name[3], "振替休日(秋分の日)");
}
break;
// 10月
case 10:
// 体育の日(10月の第2月曜日)
k1 = 0;
for (i1 = 0; i1 < m_d && k1 < 2; i1++) {
if (day[i1] == 1) {
k1++;
if (k1 == 2) {
hol[i1] = 0;
strcpy(h_name[0], "体育の日");
}
}
}
break;
// 11月
case 11:
// 文化の日(11月3日)
hol[2] = 0;
strcpy(h_name[0], "文化の日");
if (day[2] == 0) {
hol[3] = 1;
strcpy(h_name[1], "振替休日(文化の日)");
}
// 勤労感謝の日(11月23日)
hol[22] = 2;
strcpy(h_name[2], "勤労感謝の日");
if (day[22] == 0) {
hol[23] = 3;
strcpy(h_name[3], "振替休日(勤労感謝の日)");
}
break;
// 12月
case 12:
// 天皇誕生日(12月23日)
hol[22] = 0;
strcpy(h_name[0], "天皇誕生日");
if (day[22] == 0) {
hol[23] = 1;
strcpy(h_name[1], "振替休日(天皇誕生日)");
}
break;
}
}
/*****************************************/
/* 日にち情報の取得 */
/* d : 日にち */
/* sw : =0 : 祝日でない */
/* =1 : 祝日 */
/* name : 祝日の名前 */
/* return : 曜日(0:日,・・・,6:土) */
/* (-1:エラー) */
/*****************************************/
int Calendar::Inf_day(int d, int *sw, char name[])
{
int yo = -1;
if (d < 1 || d > m_d) {
printf("***error 日にちが不適当です\n");
exit(1);
}
d--;
*sw = 0;
yo = day[d];
if (hol[d] >= 0) {
*sw = 1;
strcpy(name, h_name[hol[d]]);
}
return yo;
}
/********************/
/* カレンダーの出力 */
/* 下線は祝日 */
/*******************/
void Calendar::Out_cal()
{
int i1, i2, k = 0, k1;
printf(" 日 月 火 水 木 金 土\n\n");
while (k < day[0]) {
printf(" ");
k++;
}
k1 = -day[0];
for (i1 = 0; i1 < m_d; i1++) {
printf(" %2d", i1+1);
k++;
if (k == 7 || i1 == m_d-1) {
printf("\n");
for (i2 = 0; i2 < 7 && k1 <= m_d-1; i2++) {
if (k1 >= 0) {
if (hol[k1] < 0)
printf(" ");
else
printf("  ̄");
}
else
printf(" ");
k1++;
}
printf("\n");
k = 0;
k1 = i1 + 1;
}
}
}
};
/****************/
/* main program */
/****************/
int main(int argc, char *argv[])
{
int y, m, d, yo, sw;
char name[30];
char y_n[7][7] = {"日曜日", "月曜日", "火曜日", "水曜日",
"木曜日", "金曜日", "土曜日"};
// 引数の数のチェック
if (argc != 3 && argc != 4) {
printf("***error 年,月等を入力してください\n");
exit(1);
}
// 引数の数OK
else {
// 年,月のチェック
y = atoi(argv[1]);
if (y < 2001 || y > 2150) {
printf("***error 2001≦年≦2150\n");
exit(1);
}
m = atoi(argv[2]);
if (m < 1 || m > 12) {
printf("***error 月が不適当です\n");
exit(1);
}
// 年,月の値OK
Calendar cal(y, m);
// 日にち情報の取得
if (argc == 4) {
d = atoi(argv[3]);
yo = cal.Inf_day(d, &sw, name);
if (yo >= 0) {
printf("%d年%d月%d日 %s", y, m, d, y_n[yo]);
if (sw == 0)
printf("\n");
else
printf(" %s\n", name);
}
}
// カレンダーの出力
else
cal.Out_cal();
}
return 0;
}