我已经写了一个程序,应该找出两天之间的日期,但它有一些打嗝。当我阅读它的时候,这个逻辑在我的脑海中是非常有意义的,所以我假设我有一些语法错误,我一直在浏览或者别的什么。
首先,在不同年份输入两个日期时,输出总是会减少大约一个月(多数情况下为31个,但在一个case...go数字中为32个)。第二,相隔一个月的两个日期将返回第二个月的天数(即1/1/1至2/1/1 /1产生28天)。当然,这个程序还会做一些奇怪的事情,但我希望这是足够的信息来帮助你们知道我做错了什么。为了我的生命,我自己想不出这件事。我对C比较陌生,所以请温柔点
谢谢
// Calculates the number of calendar days between any two dates in history (beginning with 1/1/1).
#include <stdio.h>
#include <stdlib.h>
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 < 1 || *month1 > 12)
{
printf("Invalid entry for month.\n");
fail += 1;
}
if(*day1 < 1 || *day1 > 31)
{
printf("Invalid entry for day.\n");
fail += 1;
}
if(*year1 < 1)
{
printf("Invalid entry for year.\n");
fail += 1;
}
if(daysPerMonth[month1] == 30 && *day1 > 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 < 1 || *month2 > 12)
{
printf("Invalid entry for month.\n");
fail += 1;
}
if(*day2 < 1 || *day2 > 31)
{
printf("Invalid entry for day.\n");
fail += 1;
}
if(*year2 < 1)
{
printf("Invalid entry for year.\n");
fail += 1;
}
if(daysPerMonth[month2] == 30 && *day2 > 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;
}
}发布于 2012-04-25 04:12:06
首先,这个leap函数感觉过于复杂;您不需要在一个函数调用中同时执行两个日期,我确信可以更简洁地编写它,这样它就更明显地正确了。这里有一个不简洁的版本,但我相信它很容易检查逻辑:
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);
/* J F M A M J J A S O N D */
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];
}在这里,我假设一月是0;您需要强制其余的代码匹配。(我从The Elements of Programming Style (page 54)那里学到了这个双数组技巧。)使用像这样的例程最好的部分是,它从差分计算中删除了leap条件。
第四,索引数组超出了它们的界限:
for(i = month1 + 1; i <= 12; i++)
{
if(leap1 == 1)
total += daysPerMonthLeap[i];这只是0-索引数组和1-索引月份问题的另一个实例--但在修复月份时,请确保也修复了这个问题。
我担心我还没有发现所有的问题--在输入和删除所有验证代码之后,您可能会发现更容易对第一次和第二次日期进行排序--然后使用名称before和after或其他名称来给出在计算的复杂核心中更容易考虑的名称。
发布于 2012-04-25 04:09:53
将所有月份索引减少1。
我想说的是一月将与daysPerMonth[0]或daysPerMonthLeap[0]相对应,而不是daysPerMonth[1]或daysPerMonthLeap[1]。出现这种情况的原因是数组索引从0开始。
因此,无论您在哪里使用month1、month2 and daysPerMonth[]或daysPerMonthLeap[],请使用month1-1和month2-1。
我希望这是足够清楚的。否则,请随意评论。
发布于 2012-04-25 04:19:26
这不是一个完整的答案。我只想提一种更好的计算闰年的方法(这取自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);https://stackoverflow.com/questions/10309107
复制相似问题