exc/k&r/05-pointers-and-arrays/05-08.c

69 lines
2.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#define HELP_STR "usage: name year [month] day"
int month_day(int year, int day, int *pmonth);
int day_of_year(int year, int month, int day);
/* converts arguments year yearday to year month day or
* year month day to year yearday */
int main(int argc, char *argv[])
{
int y, m, d, yd;
if (argc == 3) { /* year day -> month day */
y = atoi(argv[1]), yd = atoi(argv[2]);
if ((d = month_day(y, yd, &m))) {
printf("%d %d %d\n", y, m, d);
return 0;
}
printf("error: invalid yearday %d\n", yd);
} else if (argc == 4) { /* year month day -> year day */
y = atoi(argv[1]), m = atoi(argv[2]), d = atoi(argv[3]);
if ((yd = day_of_year(y, m, d))) {
printf("%d %d\n", y, yd);
return 0;
}
printf("error: invalid month %d or day %d\n", m, d);
}
puts(HELP_STR);
return 1;
}
static char daytab[][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}
};
#define IS_LEAP(Y) (Y%4 == 0 && Y%100 != 0 || Y%400 == 0)
#define IS_MONTH(M) (0 < M && M <= 12)
#define IS_D_OF_M(LEAP, M, D) (0 < D && D <= daytab[LEAP][M])
#define IS_YD_OF_Y(LEAP, YD) (0 < YD && YD <= 365+LEAP)
/* day_of_year: set day of year from month & day
* return day of year or 0 on error */
int day_of_year(int year, int month, int day)
{
int m, leap = IS_LEAP(year);
if (!IS_MONTH(month) || !IS_D_OF_M(leap, month, day))
/* validity check */
return 0;
for (m = 1; m < month; m++)
day += daytab[leap][m];
return day;
}
/* month_day: set month, day from day of year
* return day of month or 0 on error, set pmonth to month */
int month_day(int year, int yearday, int *pmonth)
{
int m, leap = IS_LEAP(year);
if (!IS_YD_OF_Y(leap, yearday)) /* validity check */
return 0;
for (m = 1; yearday > daytab[leap][m]; m++)
yearday -= daytab[leap][m];
*pmonth = m;
return yearday;
}