Error generating calendar in C

2

I was fiddling with a program that generates a calendar for a month but it is not working correctly with bisexual years since in March 1004 the first day begins Wednesday and the last Friday.

March 1004

Sun  Mon  Tue  Wed  Thu  Fri  Sat
            1    2    3    4    5
  6    7    8    9   10   11   12
 13   14   15   16   17   18   19
 20   21   22   23   24   25   26
 27   28   29   30   31

already the month of February of 1004 is generating the calendar correctly

February 1004

Sun  Mon  Tue  Wed  Thu  Fri  Sat
            1    2    3    4    5
  6    7    8    9   10   11   12
 13   14   15   16   17   18   19
 20   21   22   23   24   25   26
 27   28   29 

But for the year 2004 it does not generate the calendar properly, because the first day of February 2004 is Sunday and the last one is also Sunday ..

February 2004

Sun  Mon  Tue  Wed  Thu  Fri  Sat
                                1
  2    3    4    5    6    7    8
  9   10   11   12   13   14   15
 16   17   18   19   20   21   22
 23   24   25   26   27   28   29

And in March of 1987 the first day falls on Sunday and the last on Tuesday. How do I resolve this error?

Sun  Mon  Tue  Wed  Thu  Fri  Sat
                                1
  2    3    4    5    6    7    8
  9   10   11   12   13   14   15
 16   17   18   19   20   21   22
 23   24   25   26   27   28   29
 30   31 

Follow the code:

#include <ctime>
#include <cstdio>

const char *months[]={
                      "\nJanuary","\nFebruary","\nMarch","\nApril","\nMay","\nJune","\nJuly","\nAugust","\nSeptember","\nOctober","\nNovember","\nDecember"
                     };

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

int first_day_year(int year)
{
    int first_day;
    int x;
    int y;
    int z;

    x = (year - 1.)/4.0;
    y = (year - 1.)/100.;
    z = (year - 1.)/400.;

    first_day = (year + x - y + z) %7;

    return first_day;
}

int leapyear(int year)
{
    if(__isleap(year))
      month_days[2] = 29;
      return 1;
    else 
      month_days[1] = 28;
      return 0;
}

int calendar(int month, int year, int first_day)
{
    int i;

    printf("%s %d\n\n", months[month], year);
    printf("Sun  Mon  Tue  Wed  Thu  Fri  Sat\n");

    for(i = 0; i < month; i++)
    {
        first_day = ((first_day + month_days[month])%7);
    }

    for(i = 1; i <= 1 + first_day * 5; i++)
    {
        printf(" ");
    }

    for(i = 1; i <= month_days[month]; i++)
    {
        printf("%2d", i);

        if((i + first_day)%7 > 0)
            printf("   ");
        else
            printf("\n ");
    }
}

int main(void)
{
    int year;
    int month;
    int first_day;

    do{
        printf("Enter a month (1 - 12): ");
        scanf("%d", &month);
    } while (month < 1 || month > 12);

    do{
        printf("Enter a year (1000 - 3000): ");
        scanf("%d", &year);
    } while (year < 1000 || year > 3000);

    first_day = first_day_year(year);

    leapyear(year);

    calendar(month, year, first_day);

    printf("\n");

    return 0; 
}
    
asked by anonymous 07.09.2017 / 23:54

1 answer

2

There are some bugs that need to be fixed:

  • The array of missing months

    The array month_days you are using:

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

    It does not play with what you are using in the functions relative to the positions and so it should become:

    int month_days[] = {0, 31, 28, 31, 30, 31, 30, 31 ,31 ,30, 31, 30, 31};
    

    In which the first position was added as 0 so that the month of position 1 gives the days of January.

  • The leapyear function has the incorrect months and a lack of { } for if and else since these have two instructions each

    You can correct it like this:

    int leapyear(int year)
    {
         if((year% 4 == 0 && year%100 != 0) || year%400 == 0){
              month_days[2] = 29; //agora [2] está certo devido ao primeiro ponto
              return 1;
         }
    
         //else é desnecessário basta fazer o retorno diretamente
         return 0;
    }
    
  • Construction of the first day for the incorrect month

    In the calendar function, the first_day setting is not being done correctly because you are not using the i variable in the loop, just as the beginning should be another considering the changes I have proposed above.

    It would look like this:

    int calendar(int month, int year, int first_day)
    {
        int i;
    
        printf("%s %d\n\n", months[month-1], year); //month-1 para imprimir o correto
        printf("Sun  Mon  Tue  Wed  Thu  Fri  Sat\n");
    
        for(i = 1; i < month; i++) //agora começa em 1
        {
            //+month_days[i] e não +month_days[month] que era o problema maior 
            first_day = ((first_day + month_days[i])%7); 
        }
        ...
    

    See this version working on Ideone

Edit :

To keep the array of days of months without the value 0 initial it is necessary to adjust the function calendar and leap_year :

int month_days[] = {31, 28, 31, 30, 31, 30, 31 ,31 ,30, 31, 30, 31}; //sem o 0
...

int leapyear(int year)
{
    if((year% 4 == 0 && year%100 != 0) || year%400 == 0){
      month_days[1] = 29; //agora com mês posição 1, que é o segundo
      return 1;
    }

    return 0;
}
...
int calendar(int month, int year, int first_day)
{
    int i;
    month--;//agora reduz o próprio month, pois em todos os locais que é
    //utilizado daqui para a frente tem de ter 1 a menos

    printf("%s %d\n\n", months[month], year); //sem -1 aqui, pois já foi reduzido acima
    printf("Sun  Mon  Tue  Wed  Thu  Fri  Sat\n");

    //volta ao i=0 que era o que tinha. month também tem agora -1 que veio de cima
    for(i = 0; i < month; i++) 
    {
        first_day = ((first_day + month_days[i])%7); 
    }

See the version without 0 working on Ideone

    
08.09.2017 / 02:35