B4414 [GESP202509 三级] 日历制作

题目描述

小 A 想制作 202520252025 年每个月的日历。他希望你能编写一个程序,按照格式输出给定月份的日历。

具体来说,第一行需要输出 MON TUE WED THU FRI SAT SUN,分别表示星期一到星期日。接下来若干行中依次输出这个月所包含的日期,日期的个位需要和对应星期几的缩写最后一个字母对齐。例如,202520252025999111 日是星期一,在输出九月的日历时,111 号的个位 111 就需要与星期一 MON 的最后一个字母 N 对齐。九月的日历输出效果如下:

MON TUE WED THU FRI SAT SUN
  1   2   3   4   5   6   7
  8   9  10  11  12  13  14
 15  16  17  18  19  20  21
 22  23  24  25  26  27  28
 29  30

你能帮助小 A 完成日历的制作吗?

输入格式

一行,一个正整数 mmm,表示需要按照格式输出 202520252025mmm 月的日历。

输出格式

输出包含若干行,表示 202520252025mmm 月的日历。

输入输出样例 #1

输入 #1

9

输出 #1

MON TUE WED THU FRI SAT SUN
  1   2   3   4   5   6   7
  8   9  10  11  12  13  14
 15  16  17  18  19  20  21
 22  23  24  25  26  27  28
 29  30

输入输出样例 #2

输入 #2

6

输出 #2

MON TUE WED THU FRI SAT SUN
                          1
  2   3   4   5   6   7   8
  9  10  11  12  13  14  15
 16  17  18  19  20  21  22
 23  24  25  26  27  28  29
 30

说明/提示

对于所有测试点,保证 1≤m≤121 \leq m \leq 121m12

#include <bits/stdc++.h>
using namespace std;

// 每个月的天数(默认平年)
int days_in_month[13] = {0,
    31, 28, 31, 30, 31, 30,
    31, 31, 30, 31, 30, 31
};

// 星期几的名字
string week[7] = {"MON","TUE","WED","THU","FRI","SAT","SUN"};

// 判断闰年
bool isLeap(int year) {
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

int main() {
    int m;
    cin >> m;

    int year = 2025;

    // 如果闰年,2月变成29天
    if (isLeap(year)) days_in_month[2] = 29;

    // 2025/1/1 是星期三 (WED)
    int first_day = 2; // 0=MON,1=TUE,2=WED,...

    // 累加前几个月的天数,得到m月1日的星期
    int offset = 0;
    for (int i = 1; i < m; i++) offset += days_in_month[i];
    int start_day = (first_day + offset) % 7;

    // 打印表头
    for (int i = 0; i < 7; i++) {
        cout << week[i];
        if (i < 6) cout << " ";
    }
    cout << "\n";

    // 打印空格(对齐)
    for (int i = 0; i < start_day; i++) cout << "    ";

    int days = days_in_month[m];
    for (int d = 1; d <= days; d++) {
       
        
        if(d < 10) cout << "  "; 
		else if(d <= 31) cout << " ";
		cout << d;
		if((start_day + d) % 7 == 0) cout << "\n";
		else cout << " ";
		
    }
    cout << "\n";

    return 0;
}

🧩 一、题目理解

输入一个月份 m,输出 2025 年该月的日历表(包含星期列和日期排列)

🧠 二、解题思路总览

1️⃣ 准备数据

  • 每个月的天数;
  • 星期名称;
  • 判断闰年(2 月可能变 29 天)。

2️⃣ 计算该月 1 日是星期几

  • 先知道:2025 年 1 月 1 日是星期三;
  • 然后累加从 1 月到 m-1 月的天数;
  • 对 7 取模即可得到该月 1 日的星期。

3️⃣ 打印日历

  • 先输出星期标题;
  • 根据 start_day 打印空格对齐;
  • 按顺序打印每一天;
  • 每 7 天换一行。

🧱 三、代码结构详细讲解


🧩(1)定义每月天数

int days_in_month[13] = {0,
    31, 28, 31, 30, 31, 30,
    31, 31, 30, 31, 30, 31
};

📘 说明:

  • 索引从 1 到 12,方便直接用月份访问;
  • 默认按照平年天数(2 月 28 天)。

🧩(2)星期名定义

string week[7] = {"MON","TUE","WED","THU","FRI","SAT","SUN"};

📘 用字符串数组存储星期名,方便输出表头。

🧩(3)判断闰年函数

bool isLeap(int year) {
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

📘 标准闰年判断规则:

  • 能被 400 整除 → 闰年;
  • 能被 4 整除但不能被 100 整除 → 也是闰年;
  • 其余情况 → 平年。

🧩(4)主程序部分

int m;
cin >> m;

int year = 2025;

读入月份,并设置目标年份。

🧩(5)若闰年则修改 2 月天数

if (isLeap(year)) days_in_month[2] = 29;

2025 年不是闰年,但代码写得通用。

🧩(6)确定已知信息

int first_day = 2; // 2025/1/1 是星期三 -> 对应 week[2]

📘 设定规则:

  • 0=MON, 1=TUE, 2=WED, ...

🧩(7)计算该月 1 日的星期

int offset = 0;
for (int i = 1; i < m; i++) offset += days_in_month[i];
int start_day = (first_day + offset) % 7;

📘 逻辑说明:

  • offset 是前面几个月的天数总和;
  • 每过 7 天,星期循环一次;
  • 所以 (first_day + offset) % 7 就是目标月 1 日对应的星期。

🧩(8)打印星期表头

for (int i = 0; i < 7; i++) {
    cout << week[i];
    if (i < 6) cout << " ";
}
cout << "\n";

📘 输出:

MON TUE WED THU FRI SAT SUN

🧩(9)打印空格对齐(该月第一天前的空位)

for (int i = 0; i < start_day; i++) cout << "    ";

📘 每个日期占 4 格(宽度相当),所以空出 start_day 个位置。

🧩(10)循环输出日期

int days = days_in_month[m];
for (int d = 1; d <= days; d++) {
    if(d < 10) cout << "  "; 
    else if(d <= 31) cout << " ";
    cout << d;

    if((start_day + d) % 7 == 0) cout << "\n";
    else cout << " ";
}
cout << "\n";

📘 输出逻辑:

数字前补空格以对齐(个位数字加两个空格);

每 7 天换一行;

通过 (start_day + d) % 7 == 0 判断是否到周日换行。

🧮 四、运行示例

5

输出(2025 年 5 月日历):

MON TUE WED THU FRI SAT SUN
             1   2   3   4
  5   6   7   8   9  10  11
 12  13  14  15  16  17  18
 19  20  21  22  23  24  25
 26  27  28  29  30  31

🧾 五、程序特点与可改进点

优点 改进建议
✅ 通用性强,可改年份 可输入年份 year 而非固定 2025
✅ 格式对齐、整齐美观 可使用 setw(3) 控制宽度更优雅
✅ 模块清晰、逻辑简洁 可打印月份标题如 “=== MAY 2025 ===”
✅ 计算起始星期灵活 可扩展为全年日历打印器

🧭 程序功能(万年历)

  • 用户输入年份与月份(例如 2025 10
  • 程序自动计算该月第一天是星期几
  • 1900年1月1日为星期一
#include <bits/stdc++.h>
using namespace std;

// 判断闰年
bool isLeap(int year) {
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

// 每个月的天数(默认平年)
int days_in_month[13] = {0,
    31, 28, 31, 30, 31, 30,
    31, 31, 30, 31, 30, 31
};

// 星期几名称
string week[7] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};

int main() {
    int year, month;
    cout << "请输入年份: ";
    cin >> year;
    cout << "请输入月份(1-12): ";
    cin >> month;

    // 计算从 1900/1/1 到目标年月1号的总天数
    long long days = 0;

    // 累加完整年份的天数
    for (int y = 1900; y < year; y++) {
        days += isLeap(y) ? 366 : 365;
    }

    // 累加本年内前几个月的天数
    for (int m = 1; m < month; m++) {
        if (m == 2 && isLeap(year))
            days += 29;
        else
            days += days_in_month[m];
    }

    // 计算目标年月1日是星期几
    // 1900/1/1 是 MON -> 余数为 0
    int start_day = days % 7; // 0=MON,1=TUE,...,6=SUN

    // 打印标题
    cout << "\n      " << year << "年" << month << "月\n";
    for (int i = 0; i < 7; i++) {
        cout << week[i];
        if (i < 6) cout << " ";
    }
    cout << "\n";

    // 打印前导空格
    for (int i = 0; i < start_day; i++) cout << "    ";

    int total_days = (month == 2 && isLeap(year)) ? 29 : days_in_month[month];

    // 打印日期
    for (int d = 1; d <= total_days; d++) {
        cout << setw(3) << d << " ";
        if ((start_day + d) % 7 == 0) cout << "\n";
    }
    cout << "\n";

    return 0;
}

请输入年份: 2025
请输入月份(1-12): 10

      2025年10月
MON TUE WED THU FRI SAT SUN
          1   2   3   4   5
  6   7   8   9  10  11  12
 13  14  15  16  17  18  19
 20  21  22  23  24  25  26
 27  28  29  30  31
请输入年份: 2000
请输入月份(1-12): 2

      2000年2月
MON TUE WED THU FRI SAT SUN
  1   2   3   4   5   6   7
  8   9  10  11  12  13  14
 15  16  17  18  19  20  21
 22  23  24  25  26  27  28
 29
请输入年份: 2023
请输入月份(1-12): 2

      2023年2月
MON TUE WED THU FRI SAT SUN
          1   2   3   4   5
  6   7   8   9  10  11  12
 13  14  15  16  17  18  19
 20  21  22  23  24  25  26
 27  28
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐