C语言练习 | 万年历小程序

#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;
}

运行效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值