K&R C Programs Exercise 5-9

Exercise 5-9. Rewrite the routines day_of_year and month_day with pointers instead of indexing.

Replace every daytab[leap][i] with pointer arithmetic. The key step: instead of indexing into the 2D array, take a pointer to the correct row (const char *p = daytab[ly]) and use p[i] or *(p + i) to access elements. The loop variable can be replaced by advancing the pointer directly.

Solution

/* K&R Exercise 5-9 — day_of_year / month_day with pointers
 * Compile: gcc -ansi -Wall ex5-9.c -o ex5-9 */
#include <stdio.h>

static char daytab[2][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}
};

static int leap(int year) { return year%4==0 && (year%100!=0 || year%400==0); }

int day_of_year(int year, int month, int day)
{
    const char *p = daytab[leap(year)];  /* pointer to the correct row */
    const char *pm;
    for (pm = p + 1; pm < p + month; pm++)
        day += *pm;
    return day;
}

int month_day(int year, int yearday, int *pmonth, int *pday)
{
    const char *p = daytab[leap(year)];
    const char *pm;
    for (pm = p + 1; yearday > *pm; pm++)
        yearday -= *pm;
    *pmonth = (int)(pm - p);
    *pday   = yearday;
    return 0;
}

int main(void)
{
    int m, d;

    printf("2024-03-01: day %d\n", day_of_year(2024,3,1)); /* 61 */
    printf("2023-12-31: day %d\n", day_of_year(2023,12,31)); /* 365 */

    month_day(2024, 61, &m, &d);
    printf("day 61 of 2024: %02d/%02d\n", m, d); /* 03/01 */

    month_day(2023, 365, &m, &d);
    printf("day 365 of 2023: %02d/%02d\n", m, d); /* 12/31 */
    return 0;
}

Array vs Pointer Comparison

/* Indexing (original) */
for (i = 1; i < month; i++)
    day += daytab[leap(year)][i];

/* Pointer (exercise 5-9) */
const char *p = daytab[leap(year)];
for (pm = p + 1; pm < p + month; pm++)
    day += *pm;

In month_day, the pointer version has a bonus: pm - p gives the month number directly without maintaining a separate counter.

Compile and Run

gcc -ansi -Wall ex5-9.c -o ex5-9
./ex5-9

Sample Output

2024-03-01: day 61
2023-12-31: day 365
day 61 of 2024: 03/01
day 365 of 2023: 12/31

What This Exercise Teaches

  • Row pointer from 2D arraydaytab[ly] is a pointer to the first element of row ly; assigning it to const char *p is idiomatic
  • Pointer difference as indexpm - p recovers the integer index without a counter variable; this is the pointer-arithmetic payoff
  • Bounds via pointer comparisonpm < p + month is equivalent to i < month; both compile to the same loop

Set Up Your C Environment

← Exercise 5-8  | 
Chapter 5 Solutions  | 
Exercise 5-10 →

Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>