引言

这次期末的程序设计题整体来说难度不大,但是在第一题部分函数设计与实现上出了点问题,处理细节时没考虑周全。在离校前,打算把这题目单独拎出来再好好分析一下orz

题目总览

问题1

设计一个成员函数NextDay,能实现将日期变更为下一天日期

分析

  • 需要考虑闰年的情况
  • 需要考虑二月的情况
  • 需要考虑月份跨年的情况
  • 需要考虑日期跨月的情况

问题解决

void NextDay(int &year, int &month, int &day)
{
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
{
if (day == 31) //跨月
{
day = 1;
month++;
}
else
{
day++;
}
}
else if (month == 4 || month == 6 || month == 9 || month == 11)
{
if (day == 30) //跨月
{
day = 1;
month++;
}
else
{
day++;
}
}
else if (month == 2)
{
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) //闰年
{
if (day == 29) //跨月
{
day = 1;
month++;
}
else
{
day++;
}
}
else
{
if (day == 28) //跨月
{
day = 1;
month++;
}
else
{
day++;
}
}
}
if (month == 13) //跨年
{
month = 1;
year++;
}
}

问题2

设计一个成员函数WeekDay,能判断当前日期是星期几

分析

其实这种类型的问题,我第一次参加NOIP初赛时遇到过类似的,到了大学就忘记咋写了QAQ

参考了一下网上大佬们的思路,这边介绍一种解题方法:

基姆拉尔森计算公式

y:年份
m:月份 //注意:这里的m取值范围为[3,14] 例如:某年的1,2月份当作去年的13,14月份
d:该月的第几天
[]:向下取整,只保留整数部分
W = D%7:是结果,代表一周中第几天, 0 为周日

基姆拉尔森计算公式实际上是对蔡勒公式进一步的优化:

蔡勒公式只适合于1582年(中国明朝万历十年)10月15日之后的情形。罗马教皇格里高利十三世在1582年组织了一批天文学家,根据哥白尼日心说计算出来的数据,对儒略历作了修改。将1582年10月5日到14日之间的10天宣布撤销,继10月4日之后为10月15日。
后来人们将这一新的历法称为“格里高利历”,也就是今天世界上所通用的历法,简称格里历或公历。

问题解决

string WeekDay(int d, int m, int y) {
vector<string> weeks = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
if(m < 3) m += 12, --y;
int D = y + y/4 - y/100 + y/400 + 2*m + 3*(m+1)/5 + d + 1;
return weeks[D%7];
}