Skip to content

Commit 17cef27

Browse files
committed
rewrite code
Use a comparator function that returns a pointer to the appropriate function according to the command line options. The different options are stored in a 1 byte bit flag. This abstracts quiet a bit of code and thus simplifies the main routine other functions.
1 parent 7f593ea commit 17cef27

File tree

4 files changed

+455
-434
lines changed

4 files changed

+455
-434
lines changed

chapter05/5-14.c

Lines changed: 70 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
11
/*
22
* Exercise 5-14. Modify the sort program to handle a -r flag, which indicates
33
* sorting in reverse (decreasing) order. Be sure that -r works with -n.
4+
*
45
* By Faisal Saadatmand
56
*/
67

78
#include <stdio.h>
8-
#include <string.h>
99
#include <stdlib.h>
10+
#include <string.h>
1011

1112
#define MAXLINES 5000 /* max #lines to be sorted */
1213
#define MAXLEN 1000 /* max length of any input line */
13-
#define ALLOCSIZE 100000 /* storage for alloc */
14+
#define ALLOCSIZE 100000 /* storage for alloc */
15+
#define NUMERIC 01 /* numeric sort */
16+
#define REVERSE 02 /* reverse sort */
17+
18+
typedef int (*funcP)(void *, void*); /* type alias to simplify syntax
19+
see section 6.7 */
1420

1521
/* functions */
16-
int getLine(char *, int);
17-
int readlines(char *[], int);
22+
int getLine(char *, int);
23+
int readlines(char *[], int);
1824
void witelines(char *[], int);
1925
char *alloc(int);
20-
void qSort(void *[], int, int,
21-
int (*)(void *, void *));
22-
int numcmp(char *, char *);
23-
int strCmp(char *, char *);
24-
int reverse(char *, char *);
26+
void qSort(void *[], int, int, funcP);
27+
int numcmp(char *, char *);
28+
funcP comperator(int);
2529

2630
/* globals */
27-
char *lineptr[MAXLINES]; /* pointers to text lines */
2831
static char allocbuf[ALLOCSIZE]; /* storage for alloc */
2932
static char *allocp = allocbuf; /* next free position */
30-
int numeric = 0; /* 1 if numeric sort */
31-
int decreasing = 0; /* 1 if reverse order sort */
33+
static char option; /* bit flag (1 byte in size) */
3234

3335
/* getLine: get line into s, return length of s -- pointer version */
3436
int getLine(char *s, int lim)
@@ -40,7 +42,7 @@ int getLine(char *s, int lim)
4042
*s++ = c;
4143
++len;
4244
}
43-
if ( c == '\n') {
45+
if (c == '\n') {
4446
*s++ = c;
4547
++len;
4648
}
@@ -55,45 +57,55 @@ int readlines(char *lineptr[], int maxlines)
5557
char *p, line[MAXLEN];
5658

5759
nlines = 0;
58-
while ((len = getLine(line, MAXLEN)) > 0)
60+
while ((len = getLine(line, MAXLEN)) > 0) {
5961
if (nlines >= maxlines || (p = alloc(len)) == NULL)
6062
return -1;
61-
else {
62-
line[len - 1] = '\0'; /* delete newline character */
63-
strcpy(p, line);
64-
lineptr[nlines++] = p;
65-
}
63+
line[len - 1] = '\0'; /* delete newline character */
64+
strcpy(p, line);
65+
lineptr[nlines++] = p;
66+
}
6667
return nlines;
6768
}
6869

6970
/* writelines: write output lines */
70-
void writelines(char *lineptr[], int nlines)
71+
void writelines(char *lineptr[], int nlines, int reverse)
7172
{
72-
while (nlines-- > 0)
73-
printf("%s\n", *lineptr++);
73+
if (reverse)
74+
while (--nlines > 0) /* print lines in reverser order */
75+
printf("%s\n", lineptr[nlines]);
76+
else
77+
while (nlines-- > 0)
78+
printf("%s\n", *lineptr++);
7479
}
7580

76-
/* alloc: allocate memory */
77-
char *alloc(int n) /* return pointer to n characters */
81+
/* alloc: return pointer to n characters */
82+
char *alloc(int n)
83+
{
84+
if (allocbuf + ALLOCSIZE - allocp < n)
85+
return 0; /* not enough room */
86+
allocp += n;
87+
return allocp - n; /* old p */
88+
}
89+
90+
/* swap: swap the values of v[i] and v[j]. */
91+
void swap(void *v[], int i, int j)
7892
{
79-
if (allocbuf + ALLOCSIZE - allocp >=n) { /* it fits */
80-
allocp += n;
81-
return allocp - n; /* old p */
82-
} else /* not enough room */
83-
return 0;
93+
void *temp;
94+
95+
temp = v[i];
96+
v[i] = v[j];
97+
v[j] = temp;
8498
}
8599

86100
/* qsort: sort v[left]...V[right] into increasing order */
87-
void qSort(void *v[], int left, int right,
88-
int (*comp)(void *, void *))
101+
void qSort(void *v[], int left, int right, funcP comp)
89102
{
90103
int i, last;
91104

92105
void swap(void *v[], int, int);
93106

94107
if (left >= right) /* do nothing if array contains */
95108
return; /* fewer than two elements */
96-
97109
swap(v, left, (left + right) / 2);
98110
last = left;
99111
for (i = left + 1; i <= right; i++)
@@ -111,13 +123,11 @@ int numcmp(char *s1, char *s2)
111123

112124
v1 = atof(s1);
113125
v2 = atof(s2);
114-
115126
if (v1 < v2)
116127
return -1;
117-
else if (v1 > v2)
118-
return 1;
119-
else
120-
return 0;
128+
if (v1 > v2)
129+
return 1;
130+
return 0;
121131
}
122132

123133
/* strCmp: return < 0 if s < t, 0 if s == t, > 0 if s > t */
@@ -129,49 +139,40 @@ int strCmp(char *s, char *t)
129139
return *s - *t;
130140
}
131141

132-
void swap(void *v[], int i, int j)
142+
/* comparator: return a function pointer to the compare function corresponding
143+
* to the input option(s). If no option was provided, i.e. the bit flag
144+
* 'option' was 0, return a function pointer to strCmp. */
145+
funcP comparator(int option)
133146
{
134-
void *temp;
135-
136-
temp = v[i];
137-
v[i] = v[j];
138-
v[j] = temp;
139-
}
140-
141-
/* reverse: reverse the return value of a function */
142-
int reverse(char *s, char *t)
143-
{
144-
int (*compfun) (char *, char *); /* pointer to compare function */
145-
146-
compfun = (numeric) ? numcmp : strCmp;
147-
148-
if ((*compfun)(s, t) < 0)
149-
return 1;
150-
else if ((*compfun)(s, t) > 0)
151-
return -1;
152-
return 0;
147+
/*
148+
* Because functions could use the comparator function to determine which
149+
* operation to perform, the order of the checks is important. Moreover,
150+
* when calling the comparator, the calling function must exclude itself
151+
* and any preceding options in the checks order from the option bit flag.
152+
*/
153+
return (funcP) (option & NUMERIC ? numcmp : strCmp);
153154
}
154155

155156
/* sort input lines */
156157
int main(int argc, char *argv[])
157158
{
158-
int nlines; /* number of input lines read */
159+
char *lineptr[MAXLINES]; /* pointers to text lines */
160+
int nlines; /* number of input lines read */
159161

162+
/* Note: no input error checking */
163+
option = 0;
160164
while (--argc > 0) {
161165
++argv;
162-
if (strCmp(argv[0], "-n") == 0)
163-
numeric = 1;
164-
if (strCmp(argv[0], "-r") == 0)
165-
decreasing = 1;
166+
if (!strCmp(argv[0], "-n"))
167+
option |= NUMERIC;
168+
if (!strCmp(argv[0], "-r"))
169+
option |= REVERSE;
166170
}
167-
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
168-
qSort((void**) lineptr, 0, nlines - 1,
169-
(int (*)(void *, void *))(decreasing ? reverse :
170-
numeric ? numcmp : strCmp));
171-
writelines(lineptr, nlines);
172-
return 0;
173-
} else {
171+
if ((nlines = readlines(lineptr, MAXLINES)) < 0) {
174172
printf("input too big to sort\n");
175173
return 1;
176174
}
175+
qSort((void**) lineptr, 0, nlines - 1, comparator(option));
176+
writelines(lineptr, nlines, option & REVERSE);
177+
return 0;
177178
}

0 commit comments

Comments
 (0)