编辑:包括现在所有的代码,显然问题可能在countDays()
之外。
我正在写一个函数,它接受两个日期作为输入,并返回一个带有两个变量的结构:m_TotalDays
个(两个日期之间的总天数)和m_WorkDays
(总天数减去周末和特定的国家法定假日)。但是,当两个给定日期的年份不同时,m_WorkDays
的计算是错误的,而对于年份相同的人,它给出的答案比正确答案少一天。
该函数还使用了另外两个函数isWorkDay()
和totalDays()
,但是,我确信问题不是来自这些函数。我相信错误一定是在countDays()
中的for
循环中,但我似乎没有找到问题可能在哪里。
#include <stdio.h>
#include <stdbool.h>
int m_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
typedef struct
{
int m_TotalDays;
int m_WorkDays;
} TResult;
bool isDayValid(int y, int m, int d);
bool isLeapYear(int y);
int totalDays(int y, int m, int d);
bool isWorkDay(int y, int m, int d);
TResult countDays (int y1, int m1, int d1, int y2, int m2, int d2);
int main()
{
int y1 = 2023;
int m1 = 1;
int d1 = 1;
int y2 = 2023;
int m2 = 12;
int d2 = 31;
countDays(y1, m1, d1, y2, m2, d2);
}
bool isLeapYear(int y) {
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
return true;
else
return false;
}
bool isDayValid(int y, int m, int d)
{
int months_31[7] = { 1, 3, 5, 7, 8, 10, 12 };
int months_30[4] = { 4, 6, 9, 11 };
if (y < 2000) //year is invalid
return false;
if (m < 1 || m > 12) //month is invalid
return false;
for (int i = 0; i < 7; i++) //day is invalid
if (m == months_30[i])
if (d > 31)
return false;
for (int i = 0; i < 4; i++)
if (m == months_30[i])
if (d > 30)
return false;
if (!(isLeapYear(y)) && m == 2 && d > 28) //if february > 28 on a normal year
return false;
else if ((isLeapYear(y)) && m == 2 && d > 29) //if february > 29 on a leap year
return false;
else
return true;
}
int totalDays(int y, int m, int d)
{
if (isDayValid(y, m, d))
{
int leap_count = 0;
int years_index = y - 2000;
for (int i = 2000; i < y; i++) {
if (isLeapYear(i))
leap_count++;
}
int add_years = leap_count + 365 * (years_index);
int add_months = 0;
if (isLeapYear(y))
m_days[1] = 29;
for (int i = 0; i < m - 1; i++)
add_months += m_days[i];
int add_days = d - 1;
int total_days = add_years + add_months + add_days;
//printf("Days since: %d\n", total_days);
return total_days;
}
}
bool isWorkDay(int y, int m, int d)
{
int day_in_week = totalDays(y, m, d) % 7;
//printf("Day in week: %d\n", day_in_week);
if ((day_in_week == 0) || (day_in_week == 1))
{
return false;
}
if ((m == 1 && d == 1) ||
(m == 5 && (d == 1 || d == 8)) ||
(m == 7 && (d == 5 || d == 6)) ||
(m == 9 && d == 28) ||
(m == 10 && d == 28) ||
(m == 11 && d == 17) ||
(m == 12 && (d == 24 || d == 25 || d == 26)))
{
//printf("not work day\n");
return false;
}
//printf("work day\n");
return true;
}
TResult countDays(int y1, int m1, int d1, int y2, int m2, int d2)
{
TResult res = { 0, 0 };
if (y2 > y1 || (y2 == y1 && (m2 > m1 || (m2 == m1 && d2 >= d1))))
{
int total_days1 = totalDays(y1, m1, d1);
int total_days2 = totalDays(y2, m2, d2);
res.m_TotalDays = (total_days2 - total_days1) + 1;
int nonWorkDays = 0;
for (int i = 1; i <= res.m_TotalDays; i++) {
if (!(isWorkDay(y1, m1, d1))) {
nonWorkDays++;
}
if (d1 < d2)
d1++;
if (d1 < m_days[m1 - 1]) {
d1++;
} else {
d1 = 1;
if (m1 < 12) {
m1++;
} else {
m1 = 1;
y1++;
}
}
}
res.m_WorkDays = res.m_TotalDays - nonWorkDays;
printf("m_TotalDays: %d\n", res.m_TotalDays);
printf("m_WorkDays: %d\n", res.m_WorkDays);
return res;
}
TResult invalidRes = { -1, -1 };
return invalidRes;
}
字符串
2条答案
按热度按时间des4xlb01#
至少这些问题:
totalDays()
更改m_days[]
表使用
if (isLeapYear(y)) m_days[1] = 29;
时,m_days[]
表被更改。如果totalDays()
只被调用一次,这是可以的,但如果是多次调用,当后续调用不是闰年时,更改表会产生问题。OP先前开放问题中的替代代码already posted。
缺少返回
在
totalDays()
中,当isDayValid(y, m, d)
为false时,函数不返回任何值。这意味着代码没有在启用所有警告的情况下编译。保存时间. Enable them all。密码错误
通过启用所有警告,快速发现以下代码错误。
字符串
eanckbw92#
你对闰年的处理是不正确的:你修改全局数组
m_days
作为函数totalDays()
的副作用,如果该函数在闰年至少被调用一次,则使二月有29天,这可能会为后续调用产生错误的结果,并在countDays
中导致问题,因为你使用m_days
数组枚举跨越该期间的所有天数,如果第一年和最后一年都不是闰年,则可能忽略2月29日的事件,否则计算额外的事件。还有其他更简单的错误,例如
d1
递增一次if (d1 < d2)
,另一次if (d1 < m_days[m1 - 1])
.另外,
m_TotalDays
和m_WorkDays
同时包括第一天和最后一天。这是预期的行为吗?闰年问题的一个更简单的解决方案是使用函数
int monthDays(int y, int m)
,而不是不可能总是正确的全局数组。以下是修改后的版本:
字符串
示例输出:
型