为什么我的程序要在非闰年中多加一天?

Why is my program adding an extra day to a non leap year?

这是我的程序,我根据输入的日期找到一年中的某一天。我还必须考虑闰年。我拥有所有这些,但是当输入诸如 12/31/1993 之类的年份时,我得到的日期是 366,这是不正确的,因为它不是闰年,所以一年中的某一天应该是 365。我测试过这是否是我的 if 语句,只是让程序能够只测试闰年并在非闰年时关闭。当输入相同的日期时,程序关闭并告诉我问题不在我的 if 语句中,而在我的 case 和 switch 中。我不太确定发生了什么,也不确定为什么要在日期中添加额外的一天。

#include <stdio.h>

int main(void){

    int month,day,year,day_number=0;

    printf("Enter a date in the form (01/02/1996): ");
    scanf("%d/%d/%d", &month,&day,&year);


    if(((year%4 == 0) && (year%100 !=0)) || (year%400==0)){
        goto two;
    }
    else{
        month=month;
        goto one;
    }

    one:
        switch(month)
        {
            case 1:day_number=day;
                break;
            case 2:day_number=31+day; //January+Febuary
                break;
            case 3:day_number=59+day; //January+Febuary+March
                break;
            case 4:day_number=90+day; //January+Febuary+March+April
                break;
            case 5:day_number=120+day; //January+Febuary+March+April+May
                break;
            case 6:day_number=151+day; //January+Febuary+March+April+May+June
                break;
            case 7:day_number=181+day; //January+Febuary+March+April+May+June+July
                break;
            case 8:day_number=212+day; //January+Febuary+March+April+May+June+July+August
                break;
            case 9:day_number=243+day; //January+Febuary+March+April+May+June+July+August+September
                break;
            case 10:day_number=273+day; //January+Febuary+March+April+May+June+July+August+September+October
                break;
            case 11:day_number=304+day; //January+Febuary+March+April+May+June+July+August+September+October+November
                break;
            case 12:day_number=334+day; //January+Febuary+March+April+May+June+July+August+September+October+November+December
                break;
        }
    two:
        switch(month)
        {
            case 1:day_number=day;
                break;
            case 2:day_number=31+day; //January+Febuary
                break;
            case 3:day_number=60+day; //January+Febuary+March
                break;
            case 4:day_number=91+day; //January+Febuary+March+April
                break;
            case 5:day_number=121+day; //January+Febuary+March+April+May
                break;
            case 6:day_number=151+day; //January+Febuary+March+April+May+June
                break;
            case 7:day_number=182+day; //January+Febuary+March+April+May+June+July
                break;
            case 8:day_number=213+day; //January+Febuary+March+April+May+June+July+August
                break;
            case 9:day_number=243+day; //January+Febuary+March+April+May+June+July+August+September
                break;
            case 10:day_number=274+day; //January+Febuary+March+April+May+June+July+August+September+October
                break;
            case 11:day_number=304+day; //January+Febuary+March+April+May+June+July+August+September+October+November
                break;
            case 12:day_number=335+day; //January+Febuary+March+April+May+June+July+August+September+October+November+December
                break;
        }
    printf("day %d\n", day_number);

        return 0;
}

代码通过标签one:后,没有什么可以阻止它执行标签two:下的所有内容。因此,它也执行这些行。

更新

goto 语句是上个世纪的 :) 除非没有其他办法,否则请避免使用它们。

你可以通过使用合适的函数来减少大量的冗余代码。

#include <stdio.h>

int get_non_leap_year_day()
{
   switch(month)
   {
      case 1:
         return day;

      case 2:
         return 31+day; //January+Febuary

      case 3:
         return 59+day; //January+Febuary+March

      case 4:
         return 90+day; //January+Febuary+March+April

      case 5:
         return 120+day; //January+Febuary+March+April+May

      case 6:
         return 151+day; //January+Febuary+March+April+May+June

      case 7:
         return 181+day; //January+Febuary+March+April+May+June+July

      case 8:
         return 212+day; //January+Febuary+March+April+May+June+July+August

      case 9:
         return 243+day; //January+Febuary+March+April+May+June+July+August+September

      case 10:
         return 273+day; //January+Febuary+March+April+May+June+July+August+September+October

      case 11:
         return 304+day; //January+Febuary+March+April+May+June+July+August+September+October+November

      case 12:
         return 334+day; //January+Febuary+March+April+May+June+July+August+September+October+November+December
   }

   // Never should come here.
   // Add a return to keep the compiler happy.
   return 0;
}

int get_leap_year_day()
{
   int day_number = get_leap_year_day();
   if ( month > 2 )
   {
      day_number++;
   }
   return day_number;
}

int main(void)
{
   int month,day,year,day_number=0;

   printf("Enter a date in the form (01/02/1996): ");
   scanf("%d/%d/%d", &month,&day,&year);

   if(((year%4 == 0) && (year%100 !=0)) || (year%400==0))
   {
      day_number = get_leap_year_day(month, day);
   }
   else
   {
      day_number = get_non_leap_year_day(month, day);
   }

   printf("day %d\n", day_number);

   return 0;
}

您需要在标签 one: 后加上一个 return。因为在执行 one: 之后,还有两个也被执行了。

此外,

  1. 始终尽量避免使用 goto 语句
  2. month=month 行完全没有必要。
  3. 代码重复较多

更好的方法是:

#include <stdio.h>

int main(void)
{

  int month,day,year,day_number=0;

  printf("Enter a date in the form (01/02/1996): ");
  scanf("%d/%d/%d", &month,&day,&year);




  switch(month)
  {
     case 1:day_number=day;
           break;
    case 2:day_number=31+day; //January+Febuary
           break;
    case 3:day_number=59+day; //January+Febuary+March
           break;
    case 4:day_number=90+day; //January+Febuary+March+April
           break;
    case 5:day_number=120+day; //January+Febuary+March+April+May
           break;
    case 6:day_number=151+day; //January+Febuary+March+April+May+June
           break;
    case 7:day_number=181+day; //January+Febuary+March+April+May+June+July
           break;
    case 8:day_number=212+day; //January+Febuary+March+April+May+June+July+August
           break;
    case 9:day_number=243+day; //January+Febuary+March+April+May+June+July+August+September
           break;
    case 10:day_number=273+day; //January+Febuary+March+April+May+June+July+August+September+October
           break;
    case 11:day_number=304+day; //January+Febuary+March+April+May+June+July+August+September+October+November
           break;
    case 12:day_number=334+day; //January+Febuary+March+April+May+June+July+August+September+October+November+December
           break;
  }

  if(((year%4 == 0) && (year%100 !=0)) || (year%400==0))
  {
       if(month>2)
       ++day_number;
  }


  printf("day %d\n", day_number);
  return 0;
}

为什么不用数组来简化代码。即

static int days_in_non_leap_year[] = 
   {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; 

if (((year%4 == 0) && (year%100 !=0)) || (year%400==0)) {
   day_number = days_in_non_leap_year[month] + 1 + days;
} else {
   day_number = days_in_non_leap_year[month] + days;
}

当然你也应该检查输入。 -1 是因为月份从 1 开始 - 它只是一个填充符