0

I've seen many questions similar to mine but haven't found anything that helps. I want to determine the day of the week of 1st given month. example: week day of March 01, 2021 or August 01, 2021. Only the month is asked from the user and it is given that Jan 01, 2021 is a Friday. This is my code so far:

#include <stdio.h>

char* MonthName(int m){

    switch(m){
        case 1: 
            return "January";
        case 2: 
            return "February";
        case 3: 
            return "March";
        case 4: 
            return "April";
        case 5: 
            return "May";
        case 6: 
            return "June";
        case 7: 
            return "July";
        case 8: 
            return "August";
        case 9: 
            return "September";
        case 10: 
            return "October";
        case 11: 
            return "November";
        case 12: 
            return "December";
        default:
            return 0;
    }
}

int MonthDays(int m){
    switch(m){
        case 1: 
            return (31);
        case 2: 
            return (28);
        case 3: 
            return (31);
        case 4: 
            return (30);
        case 5: 
            return (31);
        case 6: 
            return (30);
        case 7: 
            return (31);
        case 8: 
            return (31);
        case 9: 
            return (30);
        case 10: 
            return (31);
        case 11: 
            return (30);
        case 12: 
            return (31);
    }
}

char* WeekDay(){
    int m, d, x;
  
    x += 365;
    x += MonthDays(m);

    d = x%7;
    
    switch(d){
    //because the Jan 1 is a friday
    case 0:
        return "Friday";
    case 1:
        return "Saturday";
    case 2:
        return "Sunday";
    case 3:
        return "Monday";
    case 4:
        return "Tuesday";
    case 5:
        return "Wednesday";
    case 6:
        return "Thursday";
    
    }
}


int main(){
    int m; 
    char d;

    printf("Choose a month number from 1-12: ");
    scanf("%d", &m);

    printf("The day of %s 01, 2021 is %s\n", MonthName(m), WeekDay(d));
}

I know my codes are a little long and messy, but I'm new to C programming and I don't want anything advanced since there aren't really any errors anymore. I'm hoping not to have to modify any of the codes/switches, just the formula because I really can't figure out how to get the day of the week (see function WeekDay(), specifically the one with variables x and d). It prints a week day but it's not the correct week day. I want to incorporate the MonthDays function, as well and most of the other answers on questions similar to mine doesn't use the number of days in a month.

Any help/advice would be appreciated. Thank you!

user199707
  • 15
  • 4
  • 3
    Check: https://stackoverflow.com/questions/6054016/c-program-to-find-day-of-week-given-date?rq=1 or https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Implementation-dependent_methods – Martin Apr 19 '21 at 17:04
  • On Linux, see also [time(7)](https://man7.org/linux/man-pages/man7/time.7.html), [clock_gettime(2)](https://man7.org/linux/man-pages/man2/clock_gettime.2.html), [time(2)](https://man7.org/linux/man-pages/man2/time.2.html), [strftime(3)](https://man7.org/linux/man-pages/man3/strftime.3.html). Be aware of [leap second](https://en.wikipedia.org/wiki/Leap_second)s. Look inside the source code of [musl-libc](https://musl.libc.org/) – Basile Starynkevitch Apr 19 '21 at 17:16
  • @user200109 - You forgot to add AFAICS to _there aren't really any errors anymore_. Wouldn't you call `int m, d, x; x += 365;` - adding to an undefined value - an error? – Armali Apr 19 '21 at 19:34
  • 1
    @Armali I meant no errors show in the terminal when I compile the program. You make a valid point, though. My bad. lol – user199707 Apr 19 '21 at 21:00

2 Answers2

2

In your function WeekDay, arguments are ignored and some calculation is done with the uninitialized local variable (with indeterminate value) x, invoking undefined behavior.

Instead of this:

char* WeekDay(){
    int m, d, x;

It seems the x should be an argument like this:

char* WeekDay(int x){
    int m, d;

Also the d, which is passed to WeekDay from main, is not initialized. You should initialize that with proper value before passing, or the argument should be changed to some other proper thing.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
1

Apart from the suggestions that the other answer has already provided, here's what is missing in your WeekDay() function.

You need to essentially sum up the days from the 1st of January and then % 7 to get at the answer.

So, first, changing your WeekDay()'s signature to

char* WeekDay(int m){

to actually accept the month number that is read in from the user.

Taking an example of 1st of February, that's 31 days since the start of January i.e. the number of days in the previous month. Extending this logic to the subsequent months, it boils down to simply adding up the number of days in all the previous months. So,

int d, x = 0;

for(int i = 2; i <= m; ++i) {
    x += MonthDays(i - 1);
}

d = x%7;

Note that x is initialized to 0. Coming to the for loop, it's as mentioned, summing over the days in the previous months. Note that the starting index of the loop is 2 to avoid adding any days for January (in case the value of passed in m was 1).

Coming to other functions, the MonthName() function doesn't return a value in case m doesn't match with any of the cases. Return some default value (return NULL or something). You could possibly simplify these cases by just having arrays as:

char* days[] = {"Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday"};

and similarly char* monthName[] = .... and int numDaysInMonth[] = .... and that would just leave you to sanitize the user input m at one single place and check if it's within the range 1-12 and then access the array accordingly. Remember to take care of the 0-indexed arrays, so int daysInJan = numDaysInMonth[0] and not numDaysInMonth[1].

EDIT: Here's the link to the complete working program. And I'm sharing the program here as per the things mentioned in the latter part of the answer. It might be a matter of convenience mostly at the end of the day but here it goes:

#include <stdio.h>

int validMonth(int m) {
    return m >= 1 && m <= 12;
}

char const* MonthName(int m){
    static char const* months[] = {
        NULL, /*For convenience,
         start with NULL for avoiding 0-indexing the months*/
        "January", "February", "March", "April", "May", "June", "July",
        "August", "Septemeber", "October", "Novemeber",  "December"
    };
    return months[m];
}

char const* WeekDay(int m){
    static char const* days[] = {
        /*Starting with the day for 1st January
         NOTE: Here 0 means same as Friday, so no need
         to add a dummy value at 0-index
        */
        "Friday", "Saturday", "Sunday", "Monday",
        "Tuesday", "Wednesday", "Thursday",
    };

    static const int numDaysinMonth[] = {
        /*For convenience start with -1 at the 0-index
        to avoid 0-indexing the months*/
        -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
    };
    
    int x = 0;
  
    for(int i = 2; i <= m; ++i) {
        x += numDaysinMonth[i - 1];
    }
    return days[x % 7];
}


int main(){
    int m; 
    do {
        printf("Choose a month number from 1-12: ");
        scanf("%d", &m);
        if(validMonth(m) != 1) {
            printf("%d doesn't map to any calendar month\n", m);
        } else {
            printf("The day of %s 01, 2021 is %s\n", MonthName(m), WeekDay(m));
        }
    } while (m != 12);
}
Zoso
  • 3,273
  • 1
  • 16
  • 27
  • hi! i tried this and it just returns the same week day (friday) for every month – user199707 Apr 19 '21 at 20:20
  • @user200109 This is the [link](https://godbolt.org/z/drfxTTbGE) to the working program. It has the same code as I suggested in my answer. – Zoso Apr 19 '21 at 20:39
  • I checked again and I apparently used the wrong parameter (d instead of m) when I called the WeekDay() function in the main function. thank you so much!! – user199707 Apr 19 '21 at 20:57
  • @user200109 Good. I've added the links inline in the answer and also the version as per what I mentioned in the latter part of the answer. Just an alternative approach to long `switch-case` branches but almost equivalent. – Zoso Apr 19 '21 at 21:23