我正在编写一个简单的日历类。我正在尝试重载 operator++
以使用它将日历移动到下个月。但是,我查找下个月开始日期的算法不太正确。
calendar calendar::operator ++(int)
{
int hold;
calendar cal = *this;
month++;
if (month > December)
{
month = January;
year++;
if (year == 0)
year++;
}
previousStartDay = startDay;
startDay = nextStartDay;
nextStartDay = findNextStartDay();
return cal;
}
int calendar::findNextStartDay() const
{
int monthLength,
day = startDay;
monthLength = findMonthLength(false);
monthLength -= 28;
day += monthLength;
if (day > Saturday)
day -= Saturday;
return day;
}
January定义为0,December为11,Sunday为0,Saturday为6。startDay,previousStartDay,nextStartDay,month,year都是私有(private)类变量
当我针对 2013 年对此进行测试时,日期在 3 月之前都是正确的。此时它将下一个开始日指定为星期二而不是星期一。
我也试过这个:
int calendar::findNextStartDay() const
{
int monthLength,
day = startDay;
monthLength = findMonthLength(false);
monthLength -= 28;
day -= monthLength;
if (day < Sunday)
day += Saturday;
return day;
}
然而,它也给出了相同的结果。
编辑:
我计算的是闰年。这是我来自 findMonthLength()
的代码,用于确定它是否存在。
if ((!(year % 4) && (year % 100)) || !(year % 400))
monthLength = 29;
else
monthLength = 28;
最佳答案
问题分析
假设现在是三月,而您的开始日期是正确的(星期五,5)。
您的 findNextStartDay
算法会发现 monthlength
等于 3 (31-28),那么日期将为 2 (8 - 6),即星期二 (2)星期一 (1)...
让我们通过运行算法(findNextStartDay
的第一个版本)看看为什么这是错误的:
一月:31-28 = 3,day = 2(星期二)+ 3 = 5(星期五),这是二月的正确开始日期。
2 月:28 - 28 = 0,day = 5(星期五)+ 0 = 5(星期五),这是三月的正确开始日期。
3 月:31-28 = 3,day = 5(星期五)+ 3 - 6(星期六)= 2(星期二),这是错误的 4 月开始日期。
错误解释
问题是,当您减去星期六导致溢出(多于星期六)时,您会少算一天(即:您减去的天数比您想要的少一天)。
想想你以 day == 7
结束的情况。你会想要星期天(比星期六多一个 - 循环增加),然后你必须删除 7,而不是 6,否则你将得到星期一!
错误在于循环增量:在正确的算法中,1 超过 6(即 7)必须回到 0,2 超过 6(即 8)必须回到 1,依此类推。
在您的算法中,超出 6(即 7)的 1 返回到 1,而忽略了可怜的 0(星期日),并且每次您以这种情况结束时,都会使一周中的某一天消失。
如果您减去 Saturday + 1
,您将得到下个月的正确日期,以防“工作日溢出”。
错误修复
简而言之,改变这一行:
day -= Saturday;
到
day -= (Saturday + 1);
但是请考虑检查您的代码以获得更清晰的算法版本!
一个小技巧是使用模运算符进行循环加法:
day = ((day + monthlength) % (Saturday + 1))
关于c++ - 计算下个月开始日期的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16346721/