2
votes

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;
}
2
next.m == apr || jun || sep || nov is not how you compare a value against multiple valuesTed Klein Bergman
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
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 + 1fabian
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
Where is the test for December 31? The next day is January 1.PaulMcKenzie

2 Answers

1
votes

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://stackguides.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
0
votes

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