diff --git a/k&r/05-pointers-and-arrays/05-08.c b/k&r/05-pointers-and-arrays/05-08.c new file mode 100644 index 0000000..ad2bc62 --- /dev/null +++ b/k&r/05-pointers-and-arrays/05-08.c @@ -0,0 +1,68 @@ +#include +#include + +#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; +} +