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 );
1824void witelines (char * [], int );
1925char * 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 */
2831static char allocbuf [ALLOCSIZE ]; /* storage for alloc */
2932static 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 */
3436int 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 */
156157int 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