0

In my program, I am asking the user to input a date (in just integers such as 12 31 2019 367) and the number of days they add to it. In one of my functions, this is precisely what I am doing.

The user inputs 12 31 2019 367, and the program is meant to print 1 1 2021, but instead prints 1 1 2020 (a year behind)...

What I did (sorry for a lot of code, I tried to keep it simple and clean):

int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                      
void add_days_to_date(int *mm, int *dd, int *yy, int days_left_to_add)
{
  int days_left_in_month;
  while(days_left_in_month > 0)
  {
    days_left_in_month = days_in_month[*mm] - *dd;
 //   days_left_in_month = days_in_month[*mm] - *dd;
    if (days_in_month[2] && is_leap_year(*yy) == true)
    {
      days_left_in_month++;
    }
   } // end while
   printf("after while\n");
    if(days_left_to_add > days_left_in_month)
    {
      days_left_to_add -= days_left_in_month;
      *dd = 1;
      if(*mm == 12)
      {
        *mm = 1;
        (*yy)++;
      }
      else
      {
        (*mm)++;
      }
    }
    else
    {
      *dd += days_left_to_add;
      days_left_to_add = 0;
    }
}
int main()
{
  int mm, dd, yy, days_left_to_add;
  printf("Please enter a date between the years 1800 and 10000 in the format mm dd yy and provide the number of days to add to this date:\n");
  scanf("%d %d %d %d", &mm, &dd, &yy, &days_left_to_add);
 // printf("\nREAD\n");
  //These are pointers, so they have to be at certain location i.e. int* mm = &mm
  add_days_to_date(&mm, &dd, &yy, days_left_to_add);
  printf("%d %d %d\n", mm, dd, yy);
}

What I got after inputs:

Inputs: 12 31 2019 367

Output: 1 1 2020 (meant to be 1 1 2021)

6
  • 1
    There may be other problems, but you declare an uninitialised variable called days_left_in_month then immediately compare it to zero. This will invoke undefined behaviour. Turn on more warnings on your compiler and it will tell you that. Commented Dec 27, 2022 at 3:01
  • @pmacfarlane, I had actually initialized it inside the loop, but even after initializing it outside of the loop, it still came as the same output. I'm sorry but I do not understand what is meant to happen. However, thank you for your time. Commented Dec 27, 2022 at 3:11
  • 1
    You have if (days_in_month[2] && is_leap_year(*yy) == true) — surely you should be testing whether the month (*mm) is 2 (February). Since days_in_month[2] is 28, it always evaluates to true. Commented Dec 27, 2022 at 3:12
  • @JonathanLeffler, what are you suggesting that I do then? Edit: Thank you for your help Commented Dec 27, 2022 at 3:13
  • if (*mm == 2 && is_leap_year(*yy)) would be reasonable — you can add the == true but that isn't the idiomatic way of testing boolean values. However, I don't think that's the only problem — though it is one problem that affects the calculation because you add one day to each month in a leap year with the existing code. Commented Dec 27, 2022 at 3:15

1 Answer 1

0

Your loop in the function needs to be while (days_left_to_add > 0), and should cover the whole of the function (and then needs some minor adjustments). As it is, you add just one month, which given that your input is 2019-12-31 lands you on 2020-01-01.

Your code should validate the input date.

This code works, at least for a number of test cases similar to your example.

/* SO 74925-5084 */
#include <stdio.h>
#include <stdbool.h>

static const int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

static bool is_leap_year(int year)
{
    if (year % 4 != 0)
        return false;
    if (year % 100 != 0)
        return true;
    if (year % 400 != 0)
        return false;
    return true;
}

static void add_days_to_date(int *mm, int *dd, int *yy, int days)
{
    while (days > 0)
    {
        int days_left_in_month = days_in_month[*mm] - *dd + 1;
        if (*mm == 2 && is_leap_year(*yy))
            days_left_in_month++;
        //printf("DAYS = %2d, DLIM = %2d, leap(%4d) = %s\n",
        //       days, days_left_in_month, *yy, is_leap_year(*yy) ? "true" : "false");
        if (days >= days_left_in_month)
        {
            days -= days_left_in_month;
            *dd = 1;
            if (*mm == 12)
            {
                *mm = 1;
                (*yy)++;
            }
            else
            {
                (*mm)++;
            }
        }
        else
        {
            *dd += days;
            days = 0;
        }
        // This is informative while debugging
        printf("%.4d-%.2d-%.2d + %d\n", *yy, *mm, *dd, days);
    }
}

int main(void)
{
    int mm, dd, yy, days_left_to_add;
    printf("Please enter a date between the years 1800 and 10000 in the format mm dd yyyy\n"
           "and provide the positive number of days to add to this date:\n");
    if (scanf("%d %d %d %d", &mm, &dd, &yy, &days_left_to_add) != 4)
    {
        fprintf(stderr, "Failed to read 4 numbers\n");
        return 1;
    }
    printf("Input: %.4d-%.2d-%.2d + %d\n", yy, mm, dd, days_left_to_add);

    /* Data validation */
    if (days_left_to_add <= 0)
    {
        fprintf(stderr, "The number of days to add must be a positive number (unlike %d)\n",
                days_left_to_add);
        return 1;
    }
    if (yy < 1800 || yy > 10000)
    {
        fprintf(stderr, "Year %d is outside the range 1800..10000\n", yy);
        return 1;
    }
    if (mm < 1 || mm > 12)
    {
        fprintf(stderr, "Month %d is outside the range 1..12\n", mm);
        return 1;
    }
    int dim = days_in_month[mm];
    if (mm == 2 && is_leap_year(yy))
        dim++;
    if (dd < 1 || dd > dim)
    {
        fprintf(stderr, "Day %d is outside the range 1..%d\n", dd, dim);
        return 1;
    }

    add_days_to_date(&mm, &dd, &yy, days_left_to_add);
    printf("%d %d %d\n", mm, dd, yy);
    return 0;
}

Sample runs (program ad41 created from ad41.c):

$ ad41
Please enter a date between the years 1800 and 10000 in the format mm dd yyyy
and provide the positive number of days to add to this date:
12 31 2019 367
Input: 2019-12-31 + 367
2020-01-01 + 366
2020-02-01 + 335
2020-03-01 + 306
2020-04-01 + 275
2020-05-01 + 245
2020-06-01 + 214
2020-07-01 + 184
2020-08-01 + 153
2020-09-01 + 122
2020-10-01 + 92
2020-11-01 + 61
2020-12-01 + 31
2021-01-01 + 0
1 1 2021
$ ad41
Please enter a date between the years 1800 and 10000 in the format mm dd yyyy
and provide the positive number of days to add to this date:
12 31 2018 60
Input: 2018-12-31 + 60
2019-01-01 + 59
2019-02-01 + 28
2019-03-01 + 0
3 1 2019
$ ad41
Please enter a date between the years 1800 and 10000 in the format mm dd yyyy
and provide the positive number of days to add to this date:
12 31 2019 60
Input: 2019-12-31 + 60
2020-01-01 + 59
2020-02-01 + 28
2020-02-29 + 0
2 29 2020
$
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.