Exercise 5-9 (Calendar with pointers)
Chapter_5 Exercise_5-8 | echo Exercise_5-10 |
Exercise 5-9 K&R, p. 114
Exercise 5-9. Rewrite the routines day_of_year() and month_day() with pointers instead of indexing.
CONTENTS: daysp.c dayscp.c
daysp.c download
#include <stdio.h> // for printf(), scanf()
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}
}; // don't forget semicolon
static char *monthtab[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; // don't forget semicolon
// get day of year from year (leap or not), month, day of month
int day_of_year(int year, int month, int day);
// set month and day of month from year (leap or not) and day of that year
int month_day(int year, int yearday, int *pmonth, int *pday); // return error code
int main()
{
int year, month, day, yearday, error;
printf("Year: ");
scanf("%d", &year);
printf("Yearday (1 ... 365 / 366): "); // for leap years
scanf("%d", &yearday);
error = month_day(year, yearday, &month, &day);
if (error) {return 1;} // signal error
printf("year %d, yearday %d: month %d (%s), day %d\n",
year, yearday, month, monthtab[month], day);
printf("Year: ");
scanf("%d", &year);
printf("Month (1 ... 12): ");
scanf("%d", &month);
printf("Day (1 ... 28 / 29 / 30 / 31): ");
scanf("%d", &day);
yearday = day_of_year(year, month, day);
if (yearday == 0) // error
{return 1;} // signal error
printf("year %d, yearday %d: month %d (%s), day %d\n",
year, yearday, month, monthtab[month], day);
return 0;
}
int leap_year (int year); // leap year?
// get day of year from year (leap or not), month, day of month
int day_of_year(int year, int month, int day)
{
if (month <= 0 || day <= 0)
{
printf("Month and Day of month > 0\n");
return 0; // signal error
}
if (month > 12)
{
printf("1 <= month <= 12\n");
return 0; // signal error
}
if (day > 31)
{
printf("1 <= day of month <= 28 / 29 / 30 / 31\n");
return 0; // signal error
}
int i, leap = leap_year(year);
char *d = daytab[leap];
if (day > *(d+month))
{
if (month == 2 && day == 29)
{
printf("1 <= day of month <= %d for month %d (%s), year %d\n",
*(d+month), month, *(monthtab+month), year);
}
else if (month == 2 && day > 29)
{
printf("1 <= day of month <= 28 / 29 for month %d (%s)\n",
month, *(monthtab+month));
}
else
{
printf("1 <= day of month <= %d for month %d (%s)\n",
*(d+month), month, *(monthtab+month));
}
return 0; // signal error
}
d++; // point to first month, Jan
while (--month) // while (month-- > 1)
{
day += *d++;
}
return day;
}
// set month and day of month from year (leap or not) and day of that year
int month_day(int year, int yearday, int *pmonth, int *pday) // return error code
{
if (yearday <= 0)
{
printf("Day of the year > 0\n");
return 1; // signal error
}
if (yearday > 366)
{
printf("Day of the year <= 365 or 366 for leap years\n");
return 1; // signal error
}
int leap = leap_year(year);
if (!leap && yearday == 366)
{
printf("Day of the year == 366 only for leap years\n");
return 1; // signal error
}
char *d = daytab[leap];
d++; // point to first month, Jan
while (yearday > *d)
{
yearday -= *d++;
}
*pmonth = d-daytab[leap];
*pday = yearday;
return 0; // no error
}
int leap_year (int year) // leap year?
{
return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
}
/*
gcc daysp.c -o daysp
./daysp
Year: 2013
Yearday (1 ... 365 / 366): 0
Day of the year > 0
./daysp
Year: 2013
Yearday (1 ... 365 / 366): 367
Day of the year <= 365 or 366 for leap years
./daysp
Year: 2013
Yearday (1 ... 365 / 366): 366
Day of the year == 366 only for leap years
./daysp
Year: 2013
Yearday (1 ... 365 / 366): 365
year 2013, year-day 365: month 12 (Dec), day 31
Year: 2013
Month (1 ... 12): 0
Day (1 ... 28 / 29 / 30 / 31): 1
Month and Day of month > 0
./daysp
Year: 2012
Yearday (1 ... 365 / 366): 366
year 2012, yearday 366: month 12 (Dec), day 31
Year: 2012
Month (1 ... 12): 12
Day (1 ... 28 / 29 / 30 / 31): 31
year 2012, yearday 366: month 12 (Dec), day 31
./daysp
Year: 2014
Yearday (1 ... 365 / 366): 365
year 2014, year-day 365: month 12 (Dec), day 31
Year: 2015
Month (1 ... 12): 31
Day (1 ... 28 / 29 / 30 / 31): 1
1 <= month <= 12
./daysp
Year: 2015
Yearday (1 ... 365 / 366): 1
year 2015, year-day 1: month 1 (Jan), day 1
Year: 2012
Month (1 ... 12): 12
Day (1 ... 28 / 29 / 30 / 31): 0
Month and Day of month > 0
./daysp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, year-day 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 10
Day (1 ... 28 / 29 / 30 / 31): 32
1 <= day of month <= 28 / 29 / 30 / 31
./daysp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, yearday 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 10
Day (1 ... 28 / 29 / 30 / 31): 31
year 2012, yearday 305: month 10 (Oct), day 31
./daysp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, yearday 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 9
Day (1 ... 28 / 29 / 30 / 31): 31
1 <= day of month <= 30 for month 9 (Sep)
./daysp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, yearday 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 9
Day (1 ... 28 / 29 / 30 / 31): 30
year 2012, yearday 274: month 9 (Sep), day 30
./daysp
Year: 2011
Yearday (1 ... 365 / 366): 60
year 2011, yearday 60: month 3 (Mar), day 1
Year: 2011
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 30
1 <= day of month <= 28 / 29 for month 2 (Feb)
./daysp
Year: 2011
Yearday (1 ... 365 / 366): 60
year 2011, yearday 60: month 3 (Mar), day 1
Year: 2011
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 29
1 <= day of month <= 28 for month 2 (Feb), year 2011
./daysp
Year: 2011
Yearday (1 ... 365 / 366): 60
year 2011, yearday 60: month 3 (Mar), day 1
Year: 2011
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 28
year 2011, yearday 59: month 2 (Feb), day 28
./daysp
Year: 1988
Yearday (1 ... 365 / 366): 60
year 1988, yearday 60: month 2 (Feb), day 29
Year: 1988
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 29
year 1988, yearday 60: month 2 (Feb), day 29
*/
dayscp.c download
#include <stdio.h> // for printf(), scanf()
// complicated pointers
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}
}; // don't forget semicolon
static char *monthtab[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; // don't forget semicolon
// get day of year from year (leap or not), month, day of month
int day_of_year(int year, int month, int day);
// set month and day of month from year (leap or not) and day of that year
int month_day(int year, int yearday, int *pmonth, int *pday); // return error code
int main()
{
int year, month, day, yearday, error;
printf("Year: ");
scanf("%d", &year);
printf("Yearday (1 ... 365 / 366): "); // for leap years
scanf("%d", &yearday);
error = month_day(year, yearday, &month, &day);
if (error) {return 1;} // signal error
printf("year %d, yearday %d: month %d (%s), day %d\n",
year, yearday, month, monthtab[month], day);
printf("Year: ");
scanf("%d", &year);
printf("Month (1 ... 12): ");
scanf("%d", &month);
printf("Day (1 ... 28 / 29 / 30 / 31): ");
scanf("%d", &day);
yearday = day_of_year(year, month, day);
if (yearday == 0) // error
{return 1;} // signal error
printf("year %d, yearday %d: month %d (%s), day %d\n",
year, yearday, month, monthtab[month], day);
return 0;
}
int leap_year (int year); // leap year?
// get day of year from year (leap or not), month, day of month
int day_of_year(int year, int month, int day)
{
if (month <= 0 || day <= 0)
{
printf("Month and Day of month > 0\n");
return 0; // signal error
}
if (month > 12)
{
printf("1 <= month <= 12\n");
return 0; // signal error
}
if (day > 31)
{
printf("1 <= day of month <= 28 / 29 / 30 / 31\n");
return 0; // signal error
}
int i, leap = leap_year(year);
// complicated pointers:
char *dt[] = {*daytab, *(daytab+1)}; // daytab[0], daytab[1]
char **d = dt;
if(leap) {d++;} // point to daytab[leap]
if (day > *((*d)+month))
{
if (month == 2 && day == 29)
{
printf("1 <= day of month <= %d for month %d (%s), year %d\n",
*((*d)+month), month, *(monthtab+month), year);
}
else if (month == 2 && day > 29)
{
printf("1 <= day of month <= 28 / 29 for month %d (%s)\n",
month, *(monthtab+month));
}
else
{
printf("1 <= day of month <= %d for month %d (%s)\n",
*((*d)+month), month, *(monthtab+month));
}
return 0; // signal error
}
(*d)++; // point to first month, Jan
while (--month) // while (month-- > 1)
{
day += *(*d)++;
}
return day;
}
// set month and day of month from year (leap or not) and day of that year
int month_day(int year, int yearday, int *pmonth, int *pday) // return error code
{
if (yearday <= 0)
{
printf("Day of the year > 0\n");
return 1; // signal error
}
if (yearday > 366)
{
printf("Day of the year <= 365 or 366 for leap years\n");
return 1; // signal error
}
int leap = leap_year(year);
if (!leap && yearday == 366)
{
printf("Day of the year == 366 only for leap years\n");
return 1; // signal error
}
// complicated pointers:
char *dt[] = {*daytab, *(daytab+1)}; // daytab[0], daytab[1]
char **d = dt;
if(leap) {d++;} // point to daytab[leap]
(*d)++; // point to first month, Jan
while (yearday > **d)
{
yearday -= *(*d)++;
}
*pmonth = (*d)-daytab[leap];
*pday = yearday;
return 0; // no error
}
int leap_year (int year) // leap year?
{
return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
}
/*
gcc dayscp.c -o dayscp
./dayscp
Year: 2013
Yearday (1 ... 365 / 366): 0
Day of the year > 0
./dayscp
Year: 2013
Yearday (1 ... 365 / 366): 367
Day of the year <= 365 or 366 for leap years
./dayscp
Year: 2013
Yearday (1 ... 365 / 366): 366
Day of the year == 366 only for leap years
./dayscp
Year: 2013
Yearday (1 ... 365 / 366): 365
year 2013, year-day 365: month 12 (Dec), day 31
Year: 2013
Month (1 ... 12): 0
Day (1 ... 28 / 29 / 30 / 31): 1
Month and Day of month > 0
./dayscp
Year: 2012
Yearday (1 ... 365 / 366): 366
year 2012, yearday 366: month 12 (Dec), day 31
Year: 2012
Month (1 ... 12): 12
Day (1 ... 28 / 29 / 30 / 31): 31
year 2012, yearday 366: month 12 (Dec), day 31
./dayscp
Year: 2014
Yearday (1 ... 365 / 366): 365
year 2014, year-day 365: month 12 (Dec), day 31
Year: 2015
Month (1 ... 12): 31
Day (1 ... 28 / 29 / 30 / 31): 1
1 <= month <= 12
./dayscp
Year: 2015
Yearday (1 ... 365 / 366): 1
year 2015, year-day 1: month 1 (Jan), day 1
Year: 2012
Month (1 ... 12): 12
Day (1 ... 28 / 29 / 30 / 31): 0
Month and Day of month > 0
./dayscp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, year-day 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 10
Day (1 ... 28 / 29 / 30 / 31): 32
1 <= day of month <= 28 / 29 / 30 / 31
./dayscp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, yearday 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 10
Day (1 ... 28 / 29 / 30 / 31): 31
year 2012, yearday 305: month 10 (Oct), day 31
./dayscp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, yearday 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 9
Day (1 ... 28 / 29 / 30 / 31): 31
1 <= day of month <= 30 for month 9 (Sep)
./dayscp
Year: 2012
Yearday (1 ... 365 / 366): 60
year 2012, yearday 60: month 2 (Feb), day 29
Year: 2012
Month (1 ... 12): 9
Day (1 ... 28 / 29 / 30 / 31): 30
year 2012, yearday 274: month 9 (Sep), day 30
./dayscp
Year: 2011
Yearday (1 ... 365 / 366): 60
year 2011, yearday 60: month 3 (Mar), day 1
Year: 2011
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 30
1 <= day of month <= 28 / 29 for month 2 (Feb)
./dayscp
Year: 2011
Yearday (1 ... 365 / 366): 60
year 2011, yearday 60: month 3 (Mar), day 1
Year: 2011
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 29
1 <= day of month <= 28 for month 2 (Feb), year 2011
./dayscp
Year: 2011
Yearday (1 ... 365 / 366): 60
year 2011, yearday 60: month 3 (Mar), day 1
Year: 2011
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 28
year 2011, yearday 59: month 2 (Feb), day 28
./dayscp
Year: 1988
Yearday (1 ... 365 / 366): 60
year 1988, yearday 60: month 2 (Feb), day 29
Year: 1988
Month (1 ... 12): 2
Day (1 ... 28 / 29 / 30 / 31): 29
year 1988, yearday 60: month 2 (Feb), day 29
*/
Note: The complicated pointers dt and d must be kept local. If they are global variables, they will retain their changes from one function call to the next.
Chapter_5 Exercise_5-8 | BACK_TO_TOP | echo Exercise_5-10 |
Comments
Post a Comment