/* a8-2-3.c */
#include <stdio.h>

void calendar(int y, int m);
int month_last_day(int y, int m);
int week_of_day(int y, int m, int d);
int is_leap_year(int y);

int main(void)
{
	int year, month;

	printf("西暦を入力してください。＞ ");
	scanf("%d", &year);
	printf("月を入力してください。＞ ");
	scanf("%d", &month);

    /* カレンダーの表示 */
    calendar(year, month);

    return 0;
}

/*** カレンダーの表示 ***/
/* （仮引数）y:西暦年　m:月　（返却値）なし */
void calendar(int y, int m)
{
    int i, e, w;

    w = week_of_day(y, m, 1);		/* 1日の曜日を求める */
    e = month_last_day(y, m);		/* 月の最終日を求める */
    
    printf("  ** %d年%d月 **\n", y, m);
    printf(" 日 月 火 水 木 金 土\n");
    printf("---------------------\n");
       
    for (i = 1; i <= w; i++) {		/* 1日まで空白で埋める */
        printf("   ");
	}
    for (i = 1; i <= e; i++) {		/* 最終日まで表示する */
        printf(" %2d", i);
        if ( (i + w) % 7 == 0) {	/* 土曜日で改行する */
            putchar('\n');
		}
    }
}

/*** 曜日を求める ***/
/* （仮引数）y:西暦年　m:月　d:日　（返却値）曜日 0=日 1=月 2=火 3=水 4=木 5=金 6=土 */
int week_of_day(int y, int m, int d)
{
	if(m == 1) {
		y = y - 1;
		m = 13;
	}
	else if(m == 2) {
		y = y - 1;
		m = 14; 
	}

	return (5 * y / 4 - y / 100 + y / 400 + (26 * m + 16) / 10 + d ) % 7;
}

/*** 月の最終日 ***/
/* （仮引数）y:西暦年　m:月　（返却値）月の最終日 */
int month_last_day(int y, int m)
{
	int d = 0, last[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

	if (m == 2) {
		d = last[m-1] + is_leap_year(y);    /* 閏年なら+1 */
	}
    else if (m >= 1 && m <= 12) {
        d = last[m-1];
	}

	return d;
}

/*** 閏年の判定 ***/
/*（仮引数）y:西暦年　（返却値）1:閏年　0:閏年以外 */
int is_leap_year(int y)
{
	int rc = 0;

    if (y % 4 == 0  &&  (y % 100 != 0 || y % 400 == 0)) {
		rc = 1;
	}

	return rc;
}
