Exercise 5-14. Modify the sort program to handle a
-rflag, which indicates sorting in reverse (decreasing) order. Be sure that-rworks 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 reverse —
return reverse ? -res : resinverts the sort order without duplicating the comparison logic - Composable flags —
-nand-rwork independently and together; thecomparewrapper 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