K&R C Programs Exercise 5-6

Exercise 5-6. Rewrite appropriate programs from earlier chapters and exercises with pointers instead of array indexing. Good possibilities include getline (Chapters 1 and 4), atoi, itoa, and their variants (Chapters 2, 3, 4), reverse (Chapter 3), strindex and getop (Chapter 4).

This exercise is about translation: every array subscript a[i] can be written as *(a+i), and walking an array with an index can be replaced by advancing a pointer. The pointer versions are often more compact and are idiomatic C. Below are pointer rewrites of five key functions.

Solution

/* K&R Exercise 5-6 — pointer rewrites of earlier functions
 * Compile: gcc -ansi -Wall ex5-6.c -o ex5-6 */
#include <stdio.h>
#include <ctype.h>
#include <string.h>

/* getline — pointer version (Ch 1) */
int my_getline(char *s, int lim)
{
    char *p = s;
    int c;
    while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
        *p++ = c;
    if (c == '\n')
        *p++ = c;
    *p = '\0';
    return p - s;
}

/* atoi — pointer version (Ch 2) */
int my_atoi(const char *s)
{
    int n = 0, sign;
    while (isspace(*s)) s++;
    sign = (*s == '-') ? -1 : 1;
    if (*s == '+' || *s == '-') s++;
    while (isdigit(*s))
        n = 10 * n + (*s++ - '0');
    return sign * n;
}

/* itoa — pointer version (Ch 3) */
static void rev(char *s, char *e)
{
    char tmp;
    for (e--; s < e; s++, e--)
        { tmp = *s; *s = *e; *e = tmp; }
}
void my_itoa(int n, char *s)
{
    char *p = s;
    int neg = (n < 0);
    if (neg) n = -n;
    do { *p++ = (n % 10) + '0'; } while ((n /= 10) > 0);
    if (neg) *p++ = '-';
    *p = '\0';
    rev(s, p);
}

/* reverse — pointer version (Ch 3) */
void my_reverse(char *s)
{
    char *e = s;
    char tmp;
    while (*e) e++;
    for (e--; s < e; s++, e--)
        { tmp = *s; *s = *e; *e = tmp; }
}

/* strindex — pointer version, returns rightmost match (Ch 4) */
int my_strindex(const char *s, const char *t)
{
    const char *p, *q, *r;
    int last = -1;
    for (p = s; *p; p++) {
        for (q = p, r = t; *r && *q == *r; q++, r++)
            ;
        if (*r == '\0')
            last = (int)(p - s);
    }
    return last;
}

int main(void)
{
    char buf[50];

    my_itoa(12345,  buf); printf("itoa: %s\n", buf);  /* 12345 */
    my_itoa(-999,   buf); printf("itoa: %s\n", buf);  /* -999  */

    printf("atoi: %d\n", my_atoi("  -42abc"));        /* -42   */

    char s[] = "hello";
    my_reverse(s);          printf("reverse: %s\n", s); /* olleh */

    printf("strindex: %d\n", my_strindex("abcabc","bc")); /* 4 */
    return 0;
}

Array vs Pointer at a Glance

Pattern Array version Pointer version
Walk forward while (s[i]) i++; while (*s) s++;
Copy loop while ((s[i]=t[i])!='\0') i++; while ((*s++=*t++));
Length i - start p - s

What This Exercise Teaches

  • Array indexing is pointer arithmetica[i] is defined as *(a+i); both compile to the same machine code
  • Pointer subtraction gives lengthp - s is the number of elements between two pointers into the same array; this is an int (or ptrdiff_t)
  • Advancing the pointer vs advancing the index — the pointer version is often more concise but requires care: unlike an index variable, the pointer itself is modified and cannot be rewound without saving the original

Set Up Your C Environment

← Exercise 5-5  | 
Chapter 5 Solutions  | 
Exercise 5-7 →

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>