万年历实训结果与分析 万年历推算

小编

下面是一份可直接用于实训报告的“万年历实训结果与分析——万年历推算”内容,可根据你的实际程序运行结果进行适当修改。

万年历实训结果与分析

一、实训结果

本次实训完成了一个万年历推算程序,能够根据用户输入的年份和月份,自动判断该年份是否为闰年,并正确输出该月的日历信息。程序可以显示指定月份的公历日历,包括星期排列、每月天数以及日期对应关系。

程序运行后,用户输入年份和月份,系统首先判断输入年份是否为闰年,然后确定该月份的天数,最后根据日期推算算法计算出该月1日是星期几,并按照日历格式输出完整月份信息。

例如输入:

```text

请输入年份:2024

请输入月份:2

```

程序输出结果如下:

```text

2024年2月

日 一 二 三 四 五 六

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

```

由于2024年是闰年,因此2月份有29天,程序能够正确显示。

再如输入:

```text

请输入年份:2025

请输入月份:6

```

输出结果:

```text

2025年6月

日 一 二 三 四 五 六

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日是星期几,然后根据该月天数依次输出日期。

1. 闰年判断

公历闰年的判断规则如下:

1. 能被4整除但不能被100整除的年份是闰年;

2. 能被400整除的年份也是闰年;

3. 其他年份为平年。

判断公式可表示为:

```c

if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)

leap = 1;

else

leap = 0;

```

例如:

- 2024年能被4整除且不能被100整除,是闰年;

- 1900年能被100整除但不能被400整除,不是闰年;

- 2000年能被400整除,是闰年。

2. 每月天数确定

平年和闰年的区别主要体现在2月份:

| 月份 | 天数 |

|||

| 1月 | 31天 |

| 2月 | 平年28天,闰年29天 |

| 3月 | 31天 |

| 4月 | 30天 |

| 5月 | 31天 |

| 6月 | 30天 |

| 7月 | 31天 |

| 8月 | 31天 |

| 9月 | 30天 |

| 10月 | 31天 |

| 11月 | 30天 |

| 12月 | 31天 |

程序中通常使用数组保存每月天数:

```c

int monthDays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

if (leap && month == 2)

days = 29;

else

days = monthDays[month - 1];

```

3. 星期推算方法

本次实训中可采用“累计天数法”进行星期推算。

以某一已知日期为基准,例如规定:

```text

1900年1月1日是星期一

```

然后计算从1900年1月1日到目标年份目标月份1日之间经过的总天数。

计算步骤如下:

1. 计算从1900年到目标年份前一年经过的总天数;

2. 计算目标年份中从1月到目标月份前一个月经过的天数;

3. 将总天数对7取余,得到目标月份1日对应的星期。

如果以星期日为一周第一天,则可根据余数调整输出位置。

示例公式:

```c

totalDays = 0;

for (i = 1900; i < year; i++) {

if (isLeapYear(i))

totalDays += 366;

else

totalDays += 365;

}

for (i = 1; i < month; i++) {

totalDays += getMonthDays(year, i);

}

week = (totalDays + 1) % 7;

```

`1900年1月1日`是星期一,如果用0表示星期日,1表示星期一,则:

```text

week = (totalDays + 1) % 7

```

即可得到目标月份1日的星期。

三、程序实现分析

本程序主要包括以下几个功能模块:

1. 输入模块

用于接收用户输入的年份和月份。

```c

printf("请输入年份:");

scanf("%d", &year);

printf("请输入月份:");

scanf("%d", &month);

```

为了保证程序稳定性,应对输入数据进行判断,例如月份应在1到12之间,年份应为正整数。

2. 闰年判断模块

通过函数判断某一年是否为闰年,提高程序结构清晰度。

```c

int isLeapYear(int year) {

if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)

return 1;

else

return 0;

}

```

3. 获取月份天数模块

根据年份和月份返回该月实际天数。

```c

int getMonthDays(int year, int month) {

int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};

if (month == 2 && isLeapYear(year))

return 29;

else

return days[month - 1];

}

```

4. 星期计算模块

计算目标年月1日是星期几。

```c

int getWeekday(int year, int month) {

int totalDays = 0;

int i;

for (i = 1900; i < year; i++) {

totalDays += isLeapYear(i) ? 366 : 365;

}

for (i = 1; i < month; i++) {

totalDays += getMonthDays(year, i);

}

return (totalDays + 1) % 7;

}

```

5. 日历输出模块

根据计算出的星期位置输出空格,然后依次输出日期。

```c

void printCalendar(int year, int month) {

int days = getMonthDays(year, month);

int week = getWeekday(year, month);

int i;

printf(" %d年%d月\n", year, month);

printf("日 一 二 三 四 五 六\n");

for (i = 0; i < week; i++) {

printf(" ");

}

for (i = 1; i <= days; i++) {

printf("%-4d", i);

if ((week + i) % 7 == 0) {

printf("\n");

}

}

万年历实训结果与分析 万年历推算

printf("\n");

}

```

四、测试结果分析

为了验证万年历推算的准确性,选取了多个年份和月份进行测试。

| 测试年份 | 测试月份 | 是否闰年 | 该月天数 | 测试结果 |

||:||:||

| 2024年 | 2月 | 闰年 | 29天 | 输出正确 |

| 2023年 | 2月 | 平年 | 28天 | 输出正确 |

| 2000年 | 2月 | 闰年 | 29天 | 输出正确 |

| 1900年 | 2月 | 平年 | 28天 | 输出正确 |

| 2025年 | 6月 | 平年 | 30天 | 输出正确 |

通过测试可以发现:

1. 程序能够正确区分平年和闰年;

2. 对2月份天数的处理正确;

3. 对每月1日星期的推算结果正确;

4. 日历输出格式基本整齐,符合常见日历显示习惯;

5. 程序逻辑清晰,功能模块划分合理。

特别是在测试1900年和2000年时,程序能正确处理“整百年”的特殊情况,说明闰年判断规则实现正确。

五、实训结果

通过本次万年历实训,掌握了日期推算的基本方法,理解了闰年判断、月份天数统计以及星期推算之间的关系。程序实现过程中,使用了循环、条件判断、数组和函数等基础知识,增强了对程序模块化设计的理解。

本次实训的重点是星期推算。只要确定一个可靠的基准日期,如1900年1月1日是星期一,再通过累计天数并对7取余,就可以推算出任意日期对应的星期。该方法思路清晰、实现简单,适合初学者理解和掌握。

总体来看,本次万年历程序能够完成预期功能,运行结果正确,具有一定的实用性。但程序仍有改进空间,例如可以增加输入、支持查询某一天是星期几、支持输出全年日历、增加农历或节假日显示等功能。