CSP-201503-3-节日
关键点:格式化输出
在C++中,格式化输出通常利用
iostream
库中的功能,特别是iomanip
头文件提供的一系列操作符。这些操作符用于控制输出格式,如宽度、填充、对齐方式等。在你提供的代码中,用于格式化输出的部分主要涉及setw
和setfill
操作符。
-
setw(int n)
:这是一个格式化操作符,用于设置下一个输出值的宽度。在此处,n
代表输出值应占用的字符数。如果实际数值的位数少于n
,则根据对齐方式(默认右对齐),输出会在左侧填充空格或其他字符(如果设置了填充字符)。 -
setfill(char c)
:这个操作符用于设置用于填充额外空间的字符。默认情况下,如果使用setw
设置的宽度大于实际数据的宽度,空出的位置会被空格填充。setfill
可以改变这个默认行为,用另一个字符来替代空格。例如,setfill('0')
会使用0来填充空白。例如setw(4) << setfill('0') << year
:这保证了年份year
以四个字符的宽度输出,不足四位的部分会用0补足。例如,如果年份是1995,它将正常输出为"1995";如果年份是205,则输出为"0205"。
解题思路
-
输入年份和日期规则:用户输入五个整数:a(月份),b(该月的第几个星期),c(星期几),y1(开始年份),y2(结束年份)。程序需要输出从y1年到y2年每年的a月第b个星期c的日期。
-
闰年判断:实现一个
isLeapYear
函数来判断给定的年份是否是闰年。如果年份能被400整除,或者能被4整除但不能被100整除,则该年是闰年。这对于计算二月份的天数和确定日期很重要。 -
计算天数总和:从1850年开始,计算到目标年份(
year
)之前的所有年份中每一年的天数总和。普通年有365天,闰年有366天。 -
月份处理:累加目标年份的月份之前的所有月份的天数。如果目标年份是闰年并且目标月份大于2月(意味着影响到二月的天数),则需要额外加一天。
-
计算目标月份的第一天是星期几:已知1850年1月1日是星期二,基于这一点和之前累计的天数,可以计算出目标月份的第一天是星期几。
-
计算目标日期:基于目标月份的第一天是星期几,计算出该月的第b个星期c是哪一天。这里需要考虑目标星期c与该月第一天星期的差,并计算出准确日期。
-
输出结果:对于每个年份,先检查计算出来的日期是否合法(即是否超出了该月的实际天数)。如果日期合法,则以“yyyy/mm/dd”的格式输出;如果不合法(如计算出的日期超出了该月的天数),则输出"none"。
-
异常处理和格式化:程序需要处理各种边界情况,如闰年的二月、每个月的天数不同等。同时,输出格式要求年、月、日分别以四位数、两位数、两位数表示,位数不足时前面补零。
完整代码
#include<iostream>
#include<string>
#include<vector>
#include <iomanip>
using namespace std;bool isLeapYear(int year) {return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int daysOfMonth[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };int main() {int month, weekOrdinal, weekday, startYear, endYear;cin >> month >> weekOrdinal >> weekday >> startYear >> endYear;for (int year = startYear; year <= endYear; year++) {long long dayCount = 0; // 从1850年1月1日起的总天数for (int i = 1850; i < year; i++) {dayCount += isLeapYear(i) ? 366 : 365;}for (int i = 1; i < month; i++) {dayCount += daysOfMonth[i - 1];}if (isLeapYear(year) && month > 2) dayCount++; // 闰年且月份超过2,增加一天int firstDayOfWeek = (2 + dayCount) % 7; // 当前年月的1号是星期几if (firstDayOfWeek == 0) firstDayOfWeek = 7; // 调整星期的值,使其从1到7int dayOfMonth = 1 + (weekOrdinal - 1) * 7; // 当月的目标日期int offset = weekday - firstDayOfWeek; // 需要调整的天数if (offset < 0) offset += 7;dayOfMonth += offset;// 检查日期是否存在(注意闰年)if (dayOfMonth > (month == 2 && isLeapYear(year) ? 29 : daysOfMonth[month - 1])) {cout << "none" << endl; // 日期不存在}else {cout << year << "/" << setw(2) << setfill('0') << month << "/" << setw(2) << setfill('0') << dayOfMonth << endl;}}return 0;
}