首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C两个日期之间的程序日

C两个日期之间的程序日
EN

Stack Overflow用户
提问于 2012-04-25 03:48:48
回答 6查看 34.4K关注 0票数 7

我已经写了一个程序,应该找出两天之间的日期,但它有一些打嗝。当我阅读它的时候,这个逻辑在我的脑海中是非常有意义的,所以我假设我有一些语法错误,我一直在浏览或者别的什么。

首先,在不同年份输入两个日期时,输出总是会减少大约一个月(多数情况下为31个,但在一个case...go数字中为32个)。第二,相隔一个月的两个日期将返回第二个月的天数(即1/1/1至2/1/1 /1产生28天)。当然,这个程序还会做一些奇怪的事情,但我希望这是足够的信息来帮助你们知道我做错了什么。为了我的生命,我自己想不出这件事。我对C比较陌生,所以请温柔点

谢谢

代码语言:javascript
复制
// 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;
        }
}
EN

回答 6

Stack Overflow用户

发布于 2012-04-25 04:12:06

首先,这个leap函数感觉过于复杂;您不需要在一个函数调用中同时执行两个日期,我确信可以更简洁地编写它,这样它就更明显地正确了。这里有一个不简洁的版本,但我相信它很容易检查逻辑:

代码语言:javascript
复制
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;
        }
}

你可以这样说:

代码语言:javascript
复制
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索引人工月之间存在不匹配:

代码语言:javascript
复制
            if(*month1 < 1 || *month1 > 12)

vs

代码语言:javascript
复制
    int daysPerMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};

第三,我认为每月的日数可以计算得稍微好一点:

代码语言:javascript
复制
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条件。

第四,索引数组超出了它们的界限:

代码语言:javascript
复制
            for(i = month1 + 1; i <= 12; i++)
            {
                if(leap1 == 1)
                    total += daysPerMonthLeap[i];

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

我担心我还没有发现所有的问题--在输入和删除所有验证代码之后,您可能会发现更容易对第一次和第二次日期进行排序--然后使用名称beforeafter或其他名称来给出在计算的复杂核心中更容易考虑的名称。

票数 9
EN

Stack Overflow用户

发布于 2012-04-25 04:09:53

将所有月份索引减少1。

我想说的是一月将与daysPerMonth[0]daysPerMonthLeap[0]相对应,而不是daysPerMonth[1]daysPerMonthLeap[1]。出现这种情况的原因是数组索引从0开始。

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

我希望这是足够清楚的。否则,请随意评论。

票数 3
EN

Stack Overflow用户

发布于 2012-04-25 04:19:26

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

代码语言:javascript
复制
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);
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10309107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档