【CSP试题回顾】201503-3-节日

CSP-201503-3-节日

关键点:格式化输出

在C++中,格式化输出通常利用iostream库中的功能,特别是iomanip头文件提供的一系列操作符。这些操作符用于控制输出格式,如宽度、填充、对齐方式等。在你提供的代码中,用于格式化输出的部分主要涉及setwsetfill操作符。

  1. setw(int n):这是一个格式化操作符,用于设置下一个输出值的宽度。在此处,n代表输出值应占用的字符数。如果实际数值的位数少于n,则根据对齐方式(默认右对齐),输出会在左侧填充空格或其他字符(如果设置了填充字符)。

  2. setfill(char c):这个操作符用于设置用于填充额外空间的字符。默认情况下,如果使用setw设置的宽度大于实际数据的宽度,空出的位置会被空格填充。setfill可以改变这个默认行为,用另一个字符来替代空格。例如,setfill('0')会使用0来填充空白。例如

    • setw(4) << setfill('0') << year:这保证了年份year以四个字符的宽度输出,不足四位的部分会用0补足。例如,如果年份是1995,它将正常输出为"1995";如果年份是205,则输出为"0205"。

解题思路

  1. 输入年份和日期规则:用户输入五个整数:a(月份),b(该月的第几个星期),c(星期几),y1(开始年份),y2(结束年份)。程序需要输出从y1年到y2年每年的a月第b个星期c的日期。

  2. 闰年判断:实现一个isLeapYear函数来判断给定的年份是否是闰年。如果年份能被400整除,或者能被4整除但不能被100整除,则该年是闰年。这对于计算二月份的天数和确定日期很重要。

  3. 计算天数总和:从1850年开始,计算到目标年份(year)之前的所有年份中每一年的天数总和。普通年有365天,闰年有366天。

  4. 月份处理:累加目标年份的月份之前的所有月份的天数。如果目标年份是闰年并且目标月份大于2月(意味着影响到二月的天数),则需要额外加一天。

  5. 计算目标月份的第一天是星期几:已知1850年1月1日是星期二,基于这一点和之前累计的天数,可以计算出目标月份的第一天是星期几。

  6. 计算目标日期:基于目标月份的第一天是星期几,计算出该月的第b个星期c是哪一天。这里需要考虑目标星期c与该月第一天星期的差,并计算出准确日期。

  7. 输出结果:对于每个年份,先检查计算出来的日期是否合法(即是否超出了该月的实际天数)。如果日期合法,则以“yyyy/mm/dd”的格式输出;如果不合法(如计算出的日期超出了该月的天数),则输出"none"。

  8. 异常处理和格式化:程序需要处理各种边界情况,如闰年的二月、每个月的天数不同等。同时,输出格式要求年、月、日分别以四位数、两位数、两位数表示,位数不足时前面补零。

完整代码

#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到7

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

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值