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

Popular posts from this blog

Contents

Blogger Page Margins in Contempo