两个日期之间的C程序天 [英] C program days between two dates

查看:107
本文介绍了两个日期之间的C程序天的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了程序应的发现两个日期之间的天,但它有一些打嗝。逻辑非常有意义在我的头上,当我读通过它,所以我假设我有我一直在扫视或某事的一些语法错误。

首先,在不同年进入两个日期时,则输出总是关闭的约一个月(31在大多数情况下,但在一种情况下,32 ...去图)。第二,两个日期整整一个月间隔将返回在第二个月的天数(即1/1/1至2/1/1收率28)。还有不免有些其他奇怪的事情,这个程序做,但我希望这是足够的信息来帮助你们找出我在做什么错。对于我的生活中,我想不通这一个我自己。我是比较新的C,所以请温柔=)

感谢

  //计算(与1/1/1开头)日历天历史上的任何两个日期之间的数字。#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;无效的飞跃(INT YEAR1,诠释YEAR2,为int * leap1,为int * leap2);
无效日期为(int * MONTH1,为int * DAY1,为int * YEAR1,为int * MONTH2,为int * DAY2,为int * YEAR2,为int * leap1,为int * leap2);INT主要(无效)
{
        INT MONTH1,第1天,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};        飞跃(YEAR1,YEAR2,&安培; leap1,&安培; leap2);
        日期(安培; MONTH1,和放大器;第1天,和放大器; YEAR1,&安培; MONTH2,&安培;第2天,和放大器; YEAR2,&安培; leap1,&安培; leap2);        如果(YEAR1 == YEAR2)
        {
                INT I,总;                如果(MONTH1 == MONTH2)//总天数,如果MONTH1 == MONTH2
                {
                        总=第2天 - 第1天;
                        的printf(有两个日期之间%d天,总数);
                }
                其他
                {
                    如果(leap1 == 1)
                        总= daysPerMonthLeap [MONTH1] - 第1天;
                    其他
                        总= daysPerMonth [MONTH1] - 第1天;                    对于(i = MONTH1 + 1; I< MONTH2;我++)//日期(不包括最后一个月)之间的剩余天数
                    {
                        如果(leap1 == 1)
                            总+ = daysPerMonthLeap [I]
                        其他
                            总+ = daysPerMonth [I]
                    }                    总+ =第2天;天日期(包括上个月)之间//最后一笔                    的printf(有两个日期之间%d天,总数);
                }
        }
        否则//如果YEAR1!= YEAR2 ...
        {
                INT I,总计century1 =((YEAR1 / 100)+ 1)* 100,falseleap = 0;                如果(leap1 == 1)
                    总= daysPerMonthLeap [MONTH1] - 第1天;
                其他
                    总= daysPerMonth [MONTH1] - 第1天;                对于(i = MONTH1 + 1; I< = 12;我++)//日剩余元年
                {
                    如果(leap1 == 1)
                        总+ = daysPerMonthLeap [I]
                    其他
                        总+ = daysPerMonth [I]
                }                对于(i = 1; I< MONTH2;我++)//留在最后一年的天数(不包括上月)
                {
                    如果(leap2 == 1)
                        总+ = daysPerMonthLeap [I]
                    其他
                        总+ = daysPerMonth [I]
                }                INT leapcount1 = YEAR1 / 4; //闰年之前并包括第一年
                INT leapcount2 = YEAR2 / 4; //闰年之前和不包括最后一年
                如果(YEAR2%4 == 0)
                        leapcount2 - = 1;                INT leaptotal = leapcount2 - leapcount1; //日期之间的闰年                对于(i = century1; I< YEAR2; I + = 100)//假闰年(整除100而不是400)
                {
                        如果((ⅰ%400)!= 0)
                                falseleap + = 1;
                }                总+ = 365 *(YEAR2 - YEAR1 - 1)+第2天+ leaptotal - falseleap; //最后计算
                的printf(有两个日期之间%d天,总数);
        }
        返回0;
}无效的飞跃(INT YEAR1,诠释YEAR2,为int * leap1,为int * leap2)//确定是否第一和最后几年是闰年
{
        如果(YEAR1%4 == 0)
        {
                如果(YEAR1%100 == 0)
                {
                        如果(YEAR1%400 == 0)
                                * leap1 = 1;
                        其他
                                * leap1 = 0;
                }
                其他
                        * leap1 = 1;
        }
        其他
                * leap1 = 0;        如果(YEAR2%4 == 0)
        {
                如果(YEAR2%100 == 0)
                {
                        如果(YEAR2%400 == 0)
                                * leap2 = 1;
                        其他
                                * leap2 = 0;
                                }
                其他
                        * leap2 = 1;
        }
        其他
                * leap2 = 0;
}无效日期为(int * MONTH1,为int * DAY1,为int * YEAR1,为int * MONTH2,为int * DAY2,为int * YEAR2,为int * leap1,为int * leap2)
{
        为(;;)//无限循环(退出时出示有效输入)
        {
                INT失败= 0;
                的printf(\\ n输入第一个日期:);
                scanf函数(%D /%D /%D,MONTH1,第1天,YEAR1);
                如果(*&MONTH1。1 || * MONTH1> 12)
                {
                        的printf(为无效的月进入\\ n);
                        失败+ = 1;
                }
                如果(* DAY1< 1 || * DAY1> 31)
                {
                        的printf(白天进入无效\\ n);
                        失败+ = 1;
                }
                如果(*&YEAR1。1)
                {
                        的printf(。对于今年进入无效\\ n);
                        失败+ = 1;
                }
                如果(daysPerMonth [MONTH1] == 30&放大器;&放大器; * DAY1→30)
                {
                        的printf(月无效,日组合\\ n);
                        失败+ = 1;
                }
                如果(* MONTH1 == 2)
                {
                        如果(* leap1 == 1安培;&放大器; * DAY1> 29)
                        {
                            的printf(月无效,日组合\\ n);
                            失败+ = 1;
                        }
                        否则,如果(* DAY1> 28)
                        {
                            的printf(月无效,日组合\\ n);
                            失败+ = 1;
                        }
                }
                如果(失败大于0)
                        继续;
                其他
                        打破;
        }        对于(;;)
        {
                INT失败= 0;
                的printf(\\ n输入第二个日期:);
                scanf函数(%D /%D /%D,MONTH2,DAY2,YEAR2);
                如果(* YEAR1 == * YEAR2)
                {
                        如果(*&MONTH1 GT; * MONTH2)
                        {
                                的printf(无效条目\\ n);
                                失败+ = 1;
                        }
                        如果(* MONTH1 == *&MONTH2功放;&放大器; * DAY1> *第2天)
                        {
                                的printf(无效条目\\ n);
                                失败+ = 1;
                        }
                }
                如果(* MONTH2< 1 || * MONTH2> 12)
                {
                        的printf(为无效的月进入\\ n);
                        失败+ = 1;
                }
                如果(* DAY2< 1 || * DAY2> 31)
                {
                        的printf(白天进入无效\\ n);
                        失败+ = 1;
                }
                如果(* YEAR2< 1)
                {
                        的printf(。对于今年进入无效\\ n);
                        失败+ = 1;
                }
                如果(daysPerMonth [MONTH2] == 30&放大器;&放大器; * DAY2→30)
                {
                        的printf(月无效,日组合\\ n);
                        失败+ = 1;
                }
                如果(* MONTH2 == 2)
                {
                        如果(* leap2 == 1安培;&放大器; * DAY2> 29)
                        {
                            的printf(月无效,日组合\\ n);
                            失败+ = 1;
                        }
                        否则,如果(* DAY2> 28)
                        {
                            的printf(月无效,日组合\\ n);
                            失败+ = 1;
                        }
                }
                如果(失败大于0)
                        继续;
                其他
                        打破;
        }
}


解决方案

首先,飞跃函数感觉过于复杂;你不需要在一个函数调用做两个日期,而且我敢肯定,可以写得更简洁,这样它更显然是正确的。这里有一个版本,我已经得到了周围铺设未的简洁的,但我相信它很容易检查的逻辑:

  INT is_leap_year(INT年){
        如果(年%400 == 0){
                返回1;
        }否则如果(每年100%== 0){
                返回0;
        }否则如果(年%4 == 0){
                返回1;
        }其他{
                返回0;
        }
}

您可以把它像这样:

  INT YEAR1,YEAR2,leap1,leap2;
YEAR1 = get_input();
YEAR2 = get_input();
leap1 = is_leap_year(YEAR1);
leap2 = is_leap_year(YEAR2);

没有指针和显著少code重复。是的,我知道, is_leap_year()可减少到一个单一的如果(...)语句,但这是容易的,我读

第二,我觉得你得到0索引的数组和不匹配1索引的人月:

 如果(*&MONTH1。1 || * MONTH1> 12)

VS

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

第三,我认为,每月的天数可以计算略微更好:

  INT days_in_month(INT月,年整型){
        INT飞跃= is_leap_year(年);
        / *ĴF M A MĴJ A S 0 N D * /
        INT天[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}};
        如果(月℃,||月&GT 11 ||年&下; 1753)
                返回-1;        回天[飞跃] [月];
}

在这里,我假设月份为0;你需要强制code的其余部分相匹配。 (我学到编程风格的要件这双阵列绝招(<一个href=\"http://books.google.com/books?ei=jzeXT--_OYeYiAKJjuX6Dw&id=-_QmAAAAMAAJ&dq=%22the+elements+of+programming+style%22&q=leap+year#search_anchor\">page 54 )。)用这样的程序的最好的部分是,它消除了从差计算的飞跃的条件。

四,你数组索引的范围之外:

 为(i = MONTH1 + 1; I&LT; = 12;我++)
            {
                如果(leap1 == 1)
                    总+ = daysPerMonthLeap [I]

这是另一个以0索引的数组和1个索引问题的实例 - 但要确保你解决的这个的也一样,当你解决个月

我有一个担心,我还没有发现所有的问题 - 你可能会发现更容易的排序的第一和输入之后的第二个日期,并删除所有验证code - 然后用名称之前或东西给那些通过复杂的核更容易想到的名字计算。

I have written a program that should find the days between two dates, but it has some hiccups. The logic makes perfect sense in my head when I read through it, so I'm assuming I have some syntax errors that I keep glancing over or something.

Firstly, when entering two dates in different years, the output is always off by about one month (31 in most cases, but 32 in one case...go figure). Second, two dates exactly one month apart will return the number of days in the second month (i.e. 1/1/1 to 2/1/1 yields 28). There are inevitably some other weird things that this program does, but I am hoping that is enough information to help you guys figure out what I'm doing wrong. For the life of me I can't figure this one out on my own. I am relatively new to C, so please be gentle =)

Thanks

// 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;
        }
}

解决方案

First, that leap function feels overly complicated; you don't need to do both dates in one function call, and I'm sure that can be written more succinctly so that it is more obviously correct. Here's a version I've got laying around that isn't succinct but I'm confident it is easy to check the logic:

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;
        }
}

You could call it like this:

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

No pointers and significantly less code duplication. Yes, I know that is_leap_year() can be reduced to a single if(...) statement, but this is easy for me to read.

Second, I think you're got a mismatch between 0-indexed arrays and 1-indexed human months:

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

vs

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

Third, I think that days per month can be calculated slightly nicer:

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];
}

Here, I assume January is 0; you would need to force the rest of the code to match. (I learned this double-array trick from The Elements of Programming Style (page 54).) The best part of using a routine like this is that it removes the leap condition from the difference calculation.

Fourth, you're indexing arrays outside their bounds:

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

This is just another instance of the problem with 0-indexed arrays and 1-indexed months -- but be sure that you fix this, too, when you fix the months.

I have a fear that I haven't yet found all the issues -- you may find it easier to sort the first and the second date after input and remove all that validation code -- and then use names before and after or something to give names that are easier to think through in the complicated core of the calculation.

这篇关于两个日期之间的C程序天的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆