K&R C Programs Exercise 5-14

Exercise 5-14. Modify the sort program to handle a -r flag, which indicates sorting in reverse (decreasing) order. Be sure that -r works with -n.

The K&R sort from Section 5.11 calls qsort with a comparison function strcmp. Adding -r requires the comparison function to negate its result. The cleanest approach: add a global flag reverse and a wrapper numcmp/strcmp that multiplies the result by -1 when reverse is set. Flag parsing loops over argv looking for strings that start with -.

Solution

/* K&R Exercise 5-14 — sort with -r (reverse) and -n (numeric)
 * Compile: gcc -ansi -Wall ex5-14.c -o mysort
 * Usage:   ./mysort [-n] [-r] */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLINES  5000
#define MAXSTORE  100000

static char  store[MAXSTORE];
static char *lineptr[MAXLINES];
static int   numeric = 0;
static int   reverse = 0;

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 (int)(p - s);
}

int readlines(void)
{
    int len, n = 0;
    char *sp = store, line[1024];
    while ((len = my_getline(line, sizeof line)) > 0 && n < MAXLINES
           && sp + len < store + MAXSTORE) {
        line[len-1] = '\0';
        strcpy(sp, line);
        lineptr[n++] = sp;
        sp += len;
    }
    return n;
}

void writelines(char *lp[], int n) { while (n-- > 0) printf("%s\n", *lp++); }

int numcmp(const char *s1, const char *s2)
{
    double v1 = atof(s1), v2 = atof(s2);
    return (v1 < v2) ? -1 : (v1 > v2) ? 1 : 0;
}

int compare(const void *a, const void *b)
{
    const char *s1 = *(const char **)a, *s2 = *(const char **)b;
    int res = numeric ? numcmp(s1, s2) : strcmp(s1, s2);
    return reverse ? -res : res;
}

int main(int argc, char *argv[])
{
    int n, i;
    for (i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            char *p;
            for (p = argv[i]+1; *p; p++) {
                if (*p == 'n') numeric = 1;
                if (*p == 'r') reverse = 1;
            }
        }
    }
    if ((n = readlines()) > 0) {
        qsort(lineptr, n, sizeof(char *), compare);
        writelines(lineptr, n);
    }
    return 0;
}

Test It

printf "banana\napple\ncherry\n" | ./mysort        # alphabetical
printf "banana\napple\ncherry\n" | ./mysort -r     # reverse alphabetical
printf "10\n3\n20\n1\n"         | ./mysort -n      # numeric ascending
printf "10\n3\n20\n1\n"         | ./mysort -n -r   # numeric descending

What This Exercise Teaches

  • Flag parsing from argv — scanning for - prefixes and iterating over the flag characters within each argument
  • Negating a comparator for reversereturn reverse ? -res : res inverts the sort order without duplicating the comparison logic
  • Composable flags-n and -r work independently and together; the compare wrapper applies both transformations in sequence

Set Up Your C Environment

← Exercise 5-13  | 
Chapter 5 Solutions  | 
Exercise 5-15 →

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>