Alexandru Cimpanu Alexandru Cimpanu - 2 months ago 7
C Question

Determine the number of days in a month

I am receiving the year, month and day as inputs and I am trying to validate the inputs in an efficient way. The year range is [0-99] (0,4,8.. are considered leap years), month range [1-12] and day range [1-31].

The straight forward way of validating the day would be the following:

if( (Day<1u) || (Day>31u) ){
/*error*/
}
else if ( (Month==4u) || (Month==6u) || (Month==9u) || (Month==11u) && (Day>30u) ){
/*error*/
}
else if ( (Month==2u) && (Year % 4u == 0u) && (Day > 29u) ){
/*error*/
}
else if ( (Month==2u) && (Year % 4u != 0u) && (Day > 28u) ){
/*error*/
}
else
{
/*valid*/
}


But it has a high complexity.

A lookup table seems like a better choice. And now the question:

Is there a more efficient way of creating the table for this case other than the following?

const int testTable[4][12] = {
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

if( testTable[ Year % 4 ][ Month - 1 ] >= Day){
/*valid*/
}
else{
/*error*/
}


Is there another rule that I'm not seeing?

Answer

You need one dimension for leap years and another one for non leap years:

int isleap(int year)
{
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

int mthdays(int month, int year)
{
    static const int days[2][13] = {
        {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    };
    int leap = isleap(year);

    return days[leap][month];
}

The year range is [0-99] (0,4,8.. are considered leap years)

Then your isleap() function must be:

int isleap(int year)
{
    return (year % 4 == 0);
}

month range [1-12]

Using:

{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

instead of

{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

you can avoid [ Month - 1 ]