■ 曜日計算(平成13年春期午後問5)
#include <stdio.h>
/* 基本情報 平成13年春期午後問5 */
/* 日付を与えて曜日を求める副プログラム */
#define E1 -1
#define E2 -2
#define E3 -3
#define leap_year(y) ((y)%4==0 && (y)%100!=0 || (y)%400==0)
const char *table[] = { "日","月","火","水","木","金","土" };
int day_of_week(int y, int m, int d)
{
if (1900>y || y>2299 || 1>m || m>12 || 1>d || d>31) return E1;
if (d==31 && (m==2 || m==4 || m==6 || m==9 || m==11)) return E2;
if (d==30 && m==2) return E2;
if (m==2 && d==29 && !leap_year(y)) return E3;
/* ツェラーの公式 */
if (m < 3) { y--; m += 12; }
return ((y+(y/4)-(y/100)+(y/400)+((13*m+8)/5)+d)%7);
}
int main()
{
int y, m, d, r, i, size;
/* 境界値テストデータ */
char *test[] = {
"1899,12,31","1900,01,01","2299,12,31","2300,01,01",
"2001,00,01","2001,01,01","2001,12,01","2001,13,01",
"2001,01,00","2001,01,01","2001,01,31","2001,01,32",
"2001,02,28","2001,02,30","2001,02,31","2001,03,31",
"2001,04,30","2001,04,31","2001,05,31","2001,06,30",
"2001,06,31","2001,07,31","2001,08,31","2001,09,30",
"2001,09,31","2001,10,31","2001,11,30","2001,11,31",
"2001,12,31",
"1996,02,29","2000,02,29","2001,02,29","2100,02,29",
};
size = sizeof(test) / sizeof(test[0]);
for (i = 0; i < size; i++) {
sscanf(test[i], "%d,%d,%d", &y, &m, &d);
r = day_of_week(y, m, d);
if (r == E1)
printf("(%04d,%02d,%02d;E1)", y, m, d);
else if (r == E2)
printf("(%04d,%02d,%02d;E2)", y, m, d);
else if (r == E3)
printf("(%04d,%02d,%02d;E3)", y, m, d);
else
printf("(%04d,%02d,%02d;%s)", y, m, d, table[r]);
if (i % 4 == 3) putchar('\n'); else putchar(',');
}
/*
与えられた年(西暦2000年以降とする)の
体育の日(10月の第2月曜日)の日付を求める
*/
printf("\n*** 体育の日の日付を求める***\n");
printf("年を入力:"); scanf("%d", &y);
m = 10; d = 0;
while (1) {
d++;
r = day_of_week(y, m, d);
if (r == 1) {
d += 7;
printf("(%04d,%02d,%02d;%s)\n", y, m, d, table[r]);
break;
} else if (r == E1) {
printf("(%04d,%02d,%02d;E1)\n", y, m, d);
break;
}
}
return 0;
}