2

So, this is my problem:

Write enumerated types that supports dates—such as December 12. Then add a function that produces a next day. So nextday(date) of December 12 is December 13. Also write a function printdate(date) that prints a date legibly. The function can assume that February has 28 days and it most know how many days are in each month. Use struct with two members; one is the month and the second is the day of the month — an int (or short). Then print out the date January 1 and print the next day Jan 2. Do this for the following dates: February 28, March 14, October 31, and December 31.

And that's my solution

#include <stdio.h>
#include <ctype.h>

typedef enum month { jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec } month;
typedef struct date { enum month m; int d; } date;

void print_month(struct date date) { //simple function for displaying month and day
    switch (date.m) {
      case jan:
        printf("January day %d\n", date.d);
        break;
      case feb:
        printf("February day %d\n", date.d);
        break;
      case mar:
        printf("March day %d\n", date.d);
        break;
      case apr:
        printf("April day %d\n", date.d);
        break;
      case may:
        printf("May day %d\n", date.d);
        break;
      case jun:
        printf("June day %d\n", date.d);
        break;
      case jul:
        printf("July day %d\n", date.d);
        break;
      case aug:
        printf("August day %d\n", date.d);
        break;
      case sep:
        printf("September day %d\n", date.d);
        break;
      case oct:
        printf("October day %d\n", date.d);
        break;
      case nov:
        printf("November day %d\n", date.d);
        break;
      case dec:
        printf("December day %d\n", date.d);
        break;
      default:
        printf("Out of range!");
        break;
    }
}

enum month next_day(struct date next) { //next month|day function which is the problem.
    if (next.m == jan || mar || may || jul || aug || oct || dec) {
        next.d + 1 % 31;
    }
    else if (next.m == apr || jun || sep || nov) {
        next.d + 1 % 30;
    }
    else if (next.m == feb) {
        next.d + 1 % 28;
        if (next.d > 28)
            next.m = mar;
    }

    return (month)next.m;
}

int main(void) {
    struct date date_1 = { feb, 28 };
    struct date date_2 = { mar, 14 };
    struct date date_3 = { oct, 31 };
    struct date date_4 = { dec, 31 };

    print_month(date_1);
    print_month(date_2);
    print_month(date_3);
    print_month(date_4);
    printf("\n");

    print_month(next_day(date_1)); //err C2440 
    print_month(next_day(date_2)); //err C2440
    print_month(next_day(date_3)); //err C2440
    print_month(next_day(date_4)); //err C2440
    printf("\n\n");

    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 10
    `next.m == apr || jun || sep || nov` is not how you compare a value against multiple values – Ted Klein Bergman Feb 07 '21 at 12:47
  • 3
    C and C++ are very different languages and it looks like you're only using C here. I'd suggest you remove the C++ tag because it could cause confusion. – mediocrevegetable1 Feb 07 '21 at 12:48
  • There's only one assignment in `next_day` and it receives a copy instead of a reference (or pointer, if you want to stay with C. Furthermore the `%` operator has the precedence of a division, i.e. `next.d + 1 % 30` is interpreted as `next.d + (1%30)` which is equivalent to `next.d + 1` – fabian Feb 07 '21 at 12:49
  • 1
    Also `next_day` returns a `month`, not a `date` so you aren't able to pass the result to a function expecting `date` as parameter. – fabian Feb 07 '21 at 12:56
  • Where is the test for December 31? The next day is January 1. – PaulMcKenzie Feb 07 '21 at 13:39

2 Answers2

1

I have some suggestions:

  • the date structure should contain the year to allow for leap year support.
  • You can simplify print_date() using an array of strings.
  • The function next_day() should return a date.

Here is a modified version:

#include <stdio.h>

typedef enum month { jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec } month;
typedef struct date { enum month m; int d; int y; } date;

static const char * const month_name[] = {
    "January",  "February", "March",
    "April",    "May",      "June",
    "July",     "August",   "September",
    "October",  "November", "December",
};

void print_month(struct date date) { //simple function for displaying month and day
    switch (date.m) {
      case jan:
      case feb:
      case mar:
      case apr:
      case may:
      case jun:
      case jul:
      case aug:
      case sep:
      case oct:
      case nov:
      case dec:
        printf("%s %d, %d\n", month_name[date.m], date.d, date.y);
        break;
      default:
        printf("Out of range!\n");
        break;
    }
}

date next_day(struct date next) { //next month|day function which is the problem.
    int last_day;
    switch (next.m) {
      case jan:
      case mar:
      case may:
      case jul:
      case aug:
      case oct:
      case dec:
        last_day = 31;
        break;
      case apr:
      case jun:
      case sep:
      case nov:
        last_day = 30;
        break;
      case feb:
        // check for Gregorian leap years
        // see https://stackoverflow.com/questions/3220163/how-to-find-leap-year-programmatically-in-c
        if (next.y % 4 == 0 && (next.y % 100 != 0 || next.y % 400 == 0))
            last_day = 29;
        else
            last_day = 28;
        break;
      default:
        return next;
    }
    if (next.d++ == last_day) {
        next.d = 1;
        if (next.m++ == dec) {
            next.m = jan;
            next.y++;
        }
    }
    return next;
}

int main() {
    struct date date_1 = { feb, 28, 2020 };
    struct date date_2 = { mar, 14, 2020 };
    struct date date_3 = { oct, 31, 2020 };
    struct date date_4 = { dec, 31, 2020 };
    struct date date_5 = { feb, 28, 2021 };

    print_month(date_1);
    print_month(date_2);
    print_month(date_3);
    print_month(date_4);
    print_month(date_5);
    printf("\n");

    print_month(next_day(date_1));
    print_month(next_day(date_2));
    print_month(next_day(date_3));
    print_month(next_day(date_4));
    print_month(next_day(date_5));
    printf("\n\n");

    return 0;
}

Output:

February 28, 2020
March 14, 2020
October 31, 2020
December 31, 2020
February 28, 2021

February 29, 2020
March 15, 2020
November 1, 2020
January 1, 2021
March 1, 2021
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    Thanks a lot for your help! I will try my best to someday give people, like me now, the answers to their questions! :) – From Bottom Feb 08 '21 at 05:36
  • Just to point out that the check for leap year is not complete: If divisible by 400 --> leap year, if divisible by 100 not a leap year if divisible by 4 leap year – Mario The Spoon Feb 08 '21 at 09:29
  • 1
    @MarioTheSpoon: of course! Hence my comment about the range of validity. I updated the code with a simplistic but readable test. This subject has been studied in depth [here](https://stackoverflow.com/questions/3220163/how-to-find-leap-year-programmatically-in-c) – chqrlie Feb 08 '21 at 09:40
0

First of all, I got to say that this is purely C. Tag it as so.

If you are interested in C++. First of all, let's overload the operator << for your struct.

std::ostream& operator<<(std::ostream &o, const date& d)
{
    std::string s = "Out of range"; 
    // your switch statement here to change the value of s.
    // or call a function to keep the operator code short.
    return o << s << date.d << std::endl;
}

Now we expect to display the date struct as follows:

date d{...}
std::cout << d; 

Solving your next_day function (idea). Let's return a date instead.

date next_day(date next) //next month|day function which is the problem.
{
    // make a map with months and their total days
    int total = totalDays[next.m]
    if (next.d + 1 > total) // Should go to next month
    {
       next.m = next.m + 1; // move on to next month 
       next.d = 1; 
    } else {
       next.d = next.d +1;
    }

    return next;
}

Edit: the next_day function will fail for Dec 31. Credits: @PaulMcKenzie

Oussama Ben Ghorbel
  • 2,132
  • 4
  • 17
  • 34
  • I don't think this will work if the date is December 31. – PaulMcKenzie Feb 07 '21 at 13:39
  • @PaulMcKenzie true. Tweaking this will render it very ugly I guess. – Oussama Ben Ghorbel Feb 07 '21 at 13:42
  • Yep, as You marked - the code is on C. For me the most problematic place is "next_day" function. I have the struct with two variables, one of them the "int d"(day) and I want to use it for changing "month". For that what I should do and how? I was thinking about pointers, but I little bit don't understand how to implement it and that's why I catch the "C2440" err. And sorry for my English, it is my third language which I'm still working on. – From Bottom Feb 07 '21 at 18:40