Page 121
Modify the sort program to handle a -r
flag, which indicates sorting in reverse
(decreasing) order. Be sure that -r
works with -n.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINES 5000
#define MAXCHARS 500000
char *lineptr[MAXLINES];
int readlines(char *lineptr[], int maxlines, char storage[], int maxchars);
void writelines(char *lineptr[], int nlines);
void q_sort(void *lineptr[], int left, int right,
int (*comp)(const char *, const char *), bool reverse);
int numcmp(const char *, const char *);
int main(int argc, char *argv[])
{
int nlines;
int numeric = 0;
bool reverse = false;
char storage[MAXCHARS];
while (--argc > 0) {
if (strcmp(argv[argc], "-n") == 0) {
numeric = 1;
} else if (strcmp(argv[argc], "-r") == 0) {
reverse = true;
}
}
if ((nlines = readlines(lineptr, MAXLINES, storage, MAXCHARS)) >= 0) {
q_sort((void **)lineptr, 0, nlines - 1,
(int (*)(const char *, const char *))(numeric ? numcmp :
strcmp),
reverse);
writelines(lineptr, nlines);
return 0;
} else {
printf("input too big to sort \n");
return 1;
}
}
void q_sort(void *v[], int left, int right,
int (*comp)(const char *, const char *), bool reverse)
{
int i, last, comp_result;
void swap(void *v[], int, int);
if (left >= right) {
return;
}
swap(v, left, (left + right) / 2);
last = left;
for (i = left + 1; i <= right; i++) {
comp_result = (*comp)(v[i], v[left]);
if (reverse && comp_result >= 0) {
swap(v, ++last, i);
} else if (!reverse && comp_result < 0) {
swap(v, ++last, i);
}
}
swap(v, left, last);
q_sort(v, left, last - 1, comp, opts);
q_sort(v, last + 1, right, comp, opts);
}
int numcmp(const char *s1, const char *s2)
{
double v1, v2;
v1 = atof(s1);
v2 = atof(s2);
if (v1 < v2) {
return -1;
} else if (v1 > v2) {
return 1;
} else {
return 0;
}
}
void swap(void *v[], int i, int j)
{
void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
#define MAXLEN 1000
int get_line(char s[], int lim);
int readlines(char *lineptr[], int maxlines, char storage[], int maxchars)
{
int len, nlines;
char line[MAXLEN];
int i;
i = 0;
nlines = 0;
while ((len = get_line(line, MAXLEN)) > 0) {
if (nlines >= maxlines || (i + len) >= maxchars) {
return -1;
} else {
line[len - 1] = '\0';
strcpy(storage + i, line);
lineptr[nlines++] = storage + i;
i += len;
}
}
return nlines;
}
void writelines(char *lineptr[], int nlines)
{
while (nlines-- > 0) {
printf("%s\n", *lineptr++);
}
}
int get_line(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && (c = getchar()) != EOF && c != '\n') {
s[i++] = c;
}
if (c == '\n') {
s[i++] = c;
}
s[i] = '\0';
return i;
}