1
1
/*
2
2
* Exercise 5-14. Modify the sort program to handle a -r flag, which indicates
3
3
* sorting in reverse (decreasing) order. Be sure that -r works with -n.
4
+ *
4
5
* By Faisal Saadatmand
5
6
*/
6
7
7
8
#include <stdio.h>
8
- #include <string.h>
9
9
#include <stdlib.h>
10
+ #include <string.h>
10
11
11
12
#define MAXLINES 5000 /* max #lines to be sorted */
12
13
#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 */
14
20
15
21
/* functions */
16
- int getLine (char * , int );
17
- int readlines (char * [], int );
22
+ int getLine (char * , int );
23
+ int readlines (char * [], int );
18
24
void witelines (char * [], int );
19
25
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 );
25
29
26
30
/* globals */
27
- char * lineptr [MAXLINES ]; /* pointers to text lines */
28
31
static char allocbuf [ALLOCSIZE ]; /* storage for alloc */
29
32
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) */
32
34
33
35
/* getLine: get line into s, return length of s -- pointer version */
34
36
int getLine (char * s , int lim )
@@ -40,7 +42,7 @@ int getLine(char *s, int lim)
40
42
* s ++ = c ;
41
43
++ len ;
42
44
}
43
- if ( c == '\n' ) {
45
+ if (c == '\n' ) {
44
46
* s ++ = c ;
45
47
++ len ;
46
48
}
@@ -55,45 +57,55 @@ int readlines(char *lineptr[], int maxlines)
55
57
char * p , line [MAXLEN ];
56
58
57
59
nlines = 0 ;
58
- while ((len = getLine (line , MAXLEN )) > 0 )
60
+ while ((len = getLine (line , MAXLEN )) > 0 ) {
59
61
if (nlines >= maxlines || (p = alloc (len )) == NULL )
60
62
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
+ }
66
67
return nlines ;
67
68
}
68
69
69
70
/* writelines: write output lines */
70
- void writelines (char * lineptr [], int nlines )
71
+ void writelines (char * lineptr [], int nlines , int reverse )
71
72
{
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 ++ );
74
79
}
75
80
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 )
78
92
{
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 ;
84
98
}
85
99
86
100
/* 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 )
89
102
{
90
103
int i , last ;
91
104
92
105
void swap (void * v [], int , int );
93
106
94
107
if (left >= right ) /* do nothing if array contains */
95
108
return ; /* fewer than two elements */
96
-
97
109
swap (v , left , (left + right ) / 2 );
98
110
last = left ;
99
111
for (i = left + 1 ; i <= right ; i ++ )
@@ -111,13 +123,11 @@ int numcmp(char *s1, char *s2)
111
123
112
124
v1 = atof (s1 );
113
125
v2 = atof (s2 );
114
-
115
126
if (v1 < v2 )
116
127
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 ;
121
131
}
122
132
123
133
/* strCmp: return < 0 if s < t, 0 if s == t, > 0 if s > t */
@@ -129,49 +139,40 @@ int strCmp(char *s, char *t)
129
139
return * s - * t ;
130
140
}
131
141
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 )
133
146
{
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 );
153
154
}
154
155
155
156
/* sort input lines */
156
157
int main (int argc , char * argv [])
157
158
{
158
- int nlines ; /* number of input lines read */
159
+ char * lineptr [MAXLINES ]; /* pointers to text lines */
160
+ int nlines ; /* number of input lines read */
159
161
162
+ /* Note: no input error checking */
163
+ option = 0 ;
160
164
while (-- argc > 0 ) {
161
165
++ 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 ;
166
170
}
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 ) {
174
172
printf ("input too big to sort\n" );
175
173
return 1 ;
176
174
}
175
+ qSort ((void * * ) lineptr , 0 , nlines - 1 , comparator (option ));
176
+ writelines (lineptr , nlines , option & REVERSE );
177
+ return 0 ;
177
178
}
0 commit comments