两个日期之间的C程序天数

我写了一个程序, 应该找到两个日期之间的日子,但它有一些打嗝。 当我阅读它时,逻辑在我的头脑中非常有意义,所以我假设我有一些语法错误,我一直在看一看。

首先,当输入不同年份的两个日期时,输出总是偏离大约一个月(大多数情况下为31,但在一种情况下为32 ……去图)。 第二,相隔一个月的两个日期将返回第二个月的天数(即1/1/1到2/1/1的收益率28)。 这个程序不可避免地会有一些其他奇怪的东西,但是我希望这些信息可以帮助你们弄清楚我做错了什么。 对于我的生活,我无法独自思考这一点。 我对C比较新,所以请温柔=)

谢谢

// Calculates the number of calendar days between any two dates in history (beginning with 1/1/1). #include  #include  void leap(int year1, int year2, int *leap1, int *leap2); void date(int *month1, int *day1, int *year1, int *month2, int *day2, int *year2, int *leap1, int *leap2); int main(void) { int month1, day1, year1, month2, day2, year2, leap1, leap2; int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int daysPerMonthLeap[] = {31,29,31,30,31,30,31,31,30,31,30,31}; leap(year1, year2, &leap1, &leap2); date(&month1, &day1, &year1, &month2, &day2, &year2, &leap1, &leap2); if(year1 == year2) { int i, total; if(month1 == month2) // Total days if month1 == month2 { total = day2 - day1; printf("There are %d days between the two dates.", total); } else { if(leap1 == 1) total = daysPerMonthLeap[month1] - day1; else total = daysPerMonth[month1] - day1; for(i = month1 + 1; i < month2; i++) // Days remaining between dates (excluding last month) { if(leap1 == 1) total += daysPerMonthLeap[i]; else total += daysPerMonth[i]; } total += day2; // Final sum of days between dates (including last month) printf("There are %d days between the two dates.", total); } } else // If year1 != year2 ... { int i, total, century1 = ((year1 / 100) + 1) * 100, falseleap = 0; if(leap1 == 1) total = daysPerMonthLeap[month1] - day1; else total = daysPerMonth[month1] - day1; for(i = month1 + 1; i <= 12; i++) // Day remaining in first year { if(leap1 == 1) total += daysPerMonthLeap[i]; else total += daysPerMonth[i]; } for(i = 1; i < month2; i++) // Days remaining in final year (excluding last month) { if(leap2 == 1) total += daysPerMonthLeap[i]; else total += daysPerMonth[i]; } int leapcount1 = year1 / 4; // Leap years prior to and including first year int leapcount2 = year2 / 4; // Leap years prior to and NOT including final year if(year2 % 4 == 0) leapcount2 -= 1; int leaptotal = leapcount2 - leapcount1; // Leap years between dates for(i = century1; i < year2; i += 100) // "False" leap years (divisible by 100 but not 400) { if((i % 400) != 0) falseleap += 1; } total += 365 * (year2 - year1 - 1) + day2 + leaptotal - falseleap; // Final calculation printf("There are %d days between the two dates.", total); } return 0; } void leap(int year1, int year2, int *leap1, int *leap2) // Determines if first and final years are leap years { if(year1 % 4 == 0) { if(year1 % 100 == 0) { if(year1 % 400 == 0) *leap1 = 1; else *leap1 = 0; } else *leap1 = 1; } else *leap1 = 0; if(year2 % 4 == 0) { if(year2 % 100 == 0) { if(year2 % 400 == 0) *leap2 = 1; else *leap2 = 0; } else *leap2 = 1; } else *leap2 = 0; } void date(int *month1, int *day1, int *year1, int *month2, int *day2, int *year2, int *leap1, int *leap2) { for(;;) // Infinite loop (exited upon valid input) { int fail = 0; printf("\nEnter first date: "); scanf("%d/%d/%d", month1, day1, year1); if(*month1  12) { printf("Invalid entry for month.\n"); fail += 1; } if(*day1  31) { printf("Invalid entry for day.\n"); fail += 1; } if(*year1  30) { printf("Invalid month and day combination.\n"); fail += 1; } if(*month1 == 2) { if(*leap1 == 1 && *day1 > 29) { printf("Invalid month and day combination.\n"); fail += 1; } else if(*day1 > 28) { printf("Invalid month and day combination.\n"); fail += 1; } } if(fail > 0) continue; else break; } for(;;) { int fail = 0; printf("\nEnter second date: "); scanf("%d/%d/%d", month2, day2, year2); if(*year1 == *year2) { if(*month1 > *month2) { printf("Invalid entry.\n"); fail += 1; } if(*month1 == *month2 && *day1 > *day2) { printf("Invalid entry.\n"); fail += 1; } } if(*month2  12) { printf("Invalid entry for month.\n"); fail += 1; } if(*day2  31) { printf("Invalid entry for day.\n"); fail += 1; } if(*year2  30) { printf("Invalid month and day combination.\n"); fail += 1; } if(*month2 == 2) { if(*leap2 == 1 && *day2 > 29) { printf("Invalid month and day combination.\n"); fail += 1; } else if(*day2 > 28) { printf("Invalid month and day combination.\n"); fail += 1; } } if(fail > 0) continue; else break; } } 

首先,这种leapfunction感觉过于复杂; 你不需要在一个函数调用中同时执行这两个日期,并且我确信可以更简洁地编写它以使它更明显正确。 这是我已经铺设的一个版本并不简洁,但我相信很容易检查逻辑:

 int is_leap_year(int year) { if (year % 400 == 0) { return 1; } else if (year % 100 == 0) { return 0; } else if (year % 4 == 0) { return 1; } else { return 0; } } 

你可以这样称呼它:

 int year1, year2, leap1, leap2; year1 = get_input(); year2 = get_input(); leap1 = is_leap_year(year1); leap2 = is_leap_year(year2); 

没有指针,显着减少了代码重复。 是的,我知道is_leap_year()可以简化为单个if(...)语句,但这对我来说很容易阅读。

其次,我认为你在0索引数组和1索引人类月份之间存在不匹配:

  if(*month1 < 1 || *month1 > 12) 

VS

  int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; 

第三,我认为每月的日子可以计算得更好:

 int days_in_month(int month, int year) { int leap = is_leap_year(year); /* JFMAMJJASOND */ int days[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; if (month < 0 || month > 11 || year < 1753) return -1; return days[leap][month]; } 

在这里,我假设1月是0; 你需要强制其余的代码匹配。 (我从编程风格元素 ( 第54页 )中学到了这个双arrays技巧。)使用这样的例程的最好的部分是它从差异计算中删除了跳跃条件。

第四,你要在其边界之外索引数组:

  for(i = month1 + 1; i <= 12; i++) { if(leap1 == 1) total += daysPerMonthLeap[i]; 

这只是0索引数组和1索引月数问题的另一个实例 - 但是当你修复月份时,请确保你也解决了这个问题。

我担心我还没有发现所有问题 - 你可能会发现输入后第一个和第二个日期排序更容易并删除所有validation代码 - 然后使用beforeafter名称或者给出一些东西来给出在复杂的计算核心中更容易思考的名称。

这不是一个完整的答案。 我只想提一个更好的计算闰年的方法(这取自The C Programming Language – 第41页)

 if ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0) printf("%d is a leap year \n", year); else printf("%d is not a leap year \n", year); 

将所有月份索引减少1。

我的意思是1月将对应于daysPerMonth[0]daysPerMonthLeap[0]而不是daysPerMonth[1]daysPerMonthLeap[1] 。 这是数组索引从0开始的原因。

因此,无论您在daysPerMonth[]daysPerMonthLeap[]使用month1-1month2-1 ,请使用month1-1month2-1

我希望这很清楚。 否则,请随时发表评论。

更改

 int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int daysPerMonthLeap[] = {31,29,31,30,31,30,31,31,30,31,30,31}; 

 int daysPerMonth[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int daysPerMonthLeap[] = {0,31,29,31,30,31,30,31,31,30,31,30,31}; 

即在开始时填充数组,因为所有代码都依赖于数组值从元素1而不是元素0开始。

这将摆脱你抱怨的错误。

另一个问题是当你将day2添加到总数时会出现一个错误。 在这两种情况下,您都应该添加day2 - 1而不是day2 。 这也是由于日期索引从1开始而不是0。

在我做了这些更改(加上一对只是为了让代码编译)之后,它正常工作。

您的代码段中存在多个问题..但我必须说这是一个非常好的尝试。 您尝试实现的目标有许多捷径。

我写了以下程序,它找到两个给定日期之间的天数。 您可以将此作为参考。

 #include  #include  char *month[13] = {"None", "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; /* daysPerMonth[0] = non leap year daysPerMonth[1] = leap year */ int daysPerMonth[2][13] = {{-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; typedef struct _d { int day; /* 1 to 31 */ int month; /* 1 to 12 */ int year; /* any */ }dt; void print_dt(dt d) { printf("%d %s %d \n", d.day, month[d.month], d.year); return; } int leap(int year) { return ((year % 4 == 0 && year % 100 != 0) || year % 400 ==0) ? 1 : 0; } int minus(dt d1, dt d2) { int d1_l = leap(d1.year), d2_l = leap(d2.year); int y, m; int total_days = 0; for (y = d1.year; y >= d2.year ; y--) { if (y == d1.year) { for (m = d1.month ; m >= 1 ; m--) { if (m == d1.month) total_days += d1.day; else total_days += daysPerMonth[leap(y)][m]; // printf("%d - %5s - %d - %d \n", y, month[m], daysPerMonth[leap(y)][m], total_days); } } else if (y == d2.year) { for (m = 12 ; m >= d2.month ; m--) { if (m == d2.month) total_days += daysPerMonth[leap(y)][m] - d2.day; else total_days += daysPerMonth[leap(y)][m]; // printf("%d - %5s - %d - %d \n", y, month[m], daysPerMonth[leap(y)][m], total_days); } } else { for (m = 12 ; m >= 1 ; m--) { total_days += daysPerMonth[leap(y)][m]; // printf("%d - %5s - %d - %d \n", y, month[m], daysPerMonth[leap(y)][m], total_days); } } } return total_days; } int main(void) { /* 28 Oct 2018 */ dt d2 = {28, 10, 2018}; /* 30 June 2006 */ dt d1 = {30, 6, 2006}; int days; int d1_pt = 0, d2_pt = 0; if (d1.year > d2.year) d1_pt += 100; else d2_pt += 100; if (d1.month > d2.month) d1_pt += 10; else d2_pt += 10; if (d1.day > d2.day) d1_pt += 1; else d2_pt += 1; days = (d1_pt > d2_pt) ? minus(d1, d2) : minus(d2, d1); print_dt(d1); print_dt(d2); printf("number of days: %d \n", days); return 0; } 

输出如下:

 $ gcc dates.c $ ./a.out 30 June 2006 28 Oct 2018 number of days: 4503 $ 

注意:这不是一个完整的程序。 它缺乏输入validation。

希望能帮助到你!

 //Difference/Duration between two dates //No need to calculate leap year offset or anything // Author: Vinay Kaple # include  using namespace std; int main(int argc, char const *argv[]) { int days_add, days_sub, c_date, c_month, b_date, b_month, c_year, b_year; cout<<"Current Date(dd mm yyyy): "; cin>>c_date>>c_month>>c_year; cout<<"Birth Date(dd mm yyyy): "; cin>>b_date>>b_month>>b_year; int offset_month[12] = {0,31,59,90,120,151,181,212,243,273,304,334}; days_add = c_date + offset_month[c_month-1]; days_sub = b_date + offset_month[b_month-1]; int total_days = (c_year-b_year)*365.2422 + days_add - days_sub+1; cout<<"Total days: "<