Writting day_of_month and month_day with pointers instead of array indexing

Rewrite the routines day_of_year and month_day with pointers instead of indexing.

The exercise is quite simple, this is the solution:

int day_of_year(unsigned int year, int month, int day) {
int leap, i;

leap = ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));

if((month >= 1 && month <= 12) && ((day >= 1) && (day <= *(*(daytab + leap) + month)))) {
for(i = 1; i < month; i++) {
day += *(*(daytab + leap) + i);
}

return day;
}

return -1;

}

int month_day(unsigned int year, int yearday, int *pmonth, int *pday) {
int leap, i;

leap = ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
if((leap == 1 && (yearday >= 1 && yearday <= 366)) || (leap == 0 && (yearday >= 1 && yearday <= 365))) {

for(i = 1; yearday > *(*(daytab + leap) + i); i++) {
yearday -= *(*(daytab + leap) + i);
}
*pday = yearday;
*pmonth = i;

return 1;
}
return -1;
}

The expression (daytab + leap) is a pointer to the leap-th row and (*(daytab + leap) + i) is a pointer to the i-th element of the leap-th row.

It would have been nice to see your daytab definition as well. I'll just assume that you're satisfied with the way it's defined, and that the functions work as intended.

I find this condition in month_day() a bit monstrous:

if((leap == 1 && (yearday >= 1 && yearday <= 366)) || (leap == 0 && (yearday >= 1 && yearday <= 365)))

I would shorten it to the following. Also, I've inverted the check, so that the function returns early if the parameters fail validation. Returning early is a better habit, as it reduces indentation, and reduces mental load when reading the code by getting the simpler branch out of the way.

int leap = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
if (yearday < 1 || yearday > 365 + leap) {
return -1;
}
for (…) {
…
}
• But in this case I have to declare the variable i after the if. Is it recommended to declare variables in other places than the beginning of a routine? Feb 15 '14 at 0:31