#include <iostream>
#include <vector>
using namespace std;
// 某年第一天是星期几
int Week_2100_1(int year)
{
int y = 2100, w = 5; // 2100 年第一天 周三
/*
** 一年365天,52周....1天
** 则,每多一年,星期数+1 // 闰年+2
** 每少一年,星期数-1 // 闰年-2
*/
int diffYear = year - y; // 相差几年
w += diffYear; // 每年头一天,星期数变化 1 个
if (diffYear > 0) diffYear -= 1; // 临界条件:比如,2104年是闰年,2015年是平年。计算2015年时需要计算2014年的润二月29号
if (diffYear <= -100) w -= 1; // 临界条件:比如,2000年不是闰年,时100的整数倍。多计算了一年。
w += diffYear / 4; // 大于2100年的闰年,上一天是闰年,多加一天
// 小于2100年的闰年,是闰年,多加一天
w -= diffYear / 100; // 100的倍数不是闰年,减去多算的闰年数
w += diffYear / 400; // 400的倍数不是闰年,减去多算的闰年数
return (w % 7 + 7) % 7; // 保证范围在 0~6
}
// leapYear:判断闰年
bool leapYear(int y)
{
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
return true;
return false;
}
// 计算总天数
int TotalDay(int* days, int month)
{
int ret = 0;
for (int i = 1; i < month; i++)
{
ret += days[i];
}
return ret;
}
// 请在下面补充代码,实现函数printMonth
void printMonth(int year, int month) {
printf("一 二 三 四 五 六 日\n"); // 标题
/*--------- 辅助数组:每月天数 -*/
int monthDays[] = { -1,31,28,31,30,31,30,31,31,30,31,30,31 }; // 每月的天数,下标从1开始
monthDays[0] = Week_2100_1(year); // 本年第一天的星期数
/*--------- 计算 -------------*/
int total = TotalDay(monthDays, month) + monthDays[0] - 1; // 总天数total, -1是为了空出一个位置填上本月的1号
if (month > 2 && leapYear(year)) total++; // 闰年,大于二月 多加一天为润二月的29号
int week = total % 7; // 该月第一天的星期数
if (week == -1) week += 7; // 特殊情况:某年的第一天,是星期天。则total-1为负数
for (int i = 0; i < week; i++) printf(" "); // 打印空格
/*--------- 打印 ------------*/
int days = monthDays[month];
if (month == 2 && leapYear(year)) days++; // 闰年二月29天
for (int d = 1; d <= days; d++)
{
printf("%2d ", d);
if ((d + week) % 7 == 0) puts(""); // 换行
}
puts("");
}
void test(int y1, int y2)
{
for (int y = y1; y <= y2; y++) {
cout << y << " " << (leapYear(y) ? "闰年" : "平年") << endl;
//cout << Week_2020_1(y) << endl; // 每年首行
printMonth(y, 1);
}
}
int main()
{
// 年、月
int y, m, d = 0;
char ch;
cout << R"(日历程序:
说明:
程序接收用户输入的 年(year)、月(month),输出对应日期的日历。
其中输入格式不固定,可以是 y/m、y\m y.m y+m y m ...,输出单月份日历
也可以是 y-m y~m 输出从一月到 m月的多个月份日历
参考:
输入 year/month, 查看本年m月日历, 如2020/1
输入 year-month,查看从本年1月-m月,如2020-5
退出:
输入任意非数字字符退出,如:,(中文逗号) ,(英文逗号) 。(中文句号) ...等
注:
输入需满足 year > 0, 0 < month <=12。输入错误日期将退出程序。如0/0
)" << "\n" << endl;
while (1)
{
cout << "请输入查询日期 year/month:" << endl;
// 输入年 月
rewind(stdin); // 清空输入缓冲区
cin >> y;
cin.get(ch);
cin >> m;
///test(y, m);
if (y < 0 || m > 12 || m < 1) break; // 非法输入
if (ch == '-' || ch == '~') { // 输出多个月的日历
for (int i = 1; i <= m; i++)
{
cout << "第" << i << "月" << endl;
printMonth(y, i);
}
}
else printMonth(y, m); // 输出该年月的日历
cout << endl;
}
return 0;
}
运行效果: