-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy path5-16.c
224 lines (199 loc) · 5.46 KB
/
5-16.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*
* Exercise 5-16. Add the -d (''directory order'') option, which makes
* comparisons only on letters, numbers and blanks. Make sure it works in
* conjunction with -f.
*
* By Faisal Saadatmand
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINES 5000 /* max #lines to be sorted */
#define MAXLEN 1000 /* max length of any input line */
#define ALLOCSIZE 10000 /* storage for memory[] */
#define NUMERIC 01 /* numeric sort */
#define REVERSE 02 /* reverse sort */
#define FOLD 04 /* case-insensitive sort */
#define DIRORDER 010 /* directory-order sort */
typedef int (*funcP)(void *, void*); /* type alias to simplify syntax
see section 6.7 */
/* functions */
int getLine(char *, int);
int readlines(char *[], int);
void witelines(char *[], int, int);
char *alloc(int);
void qSort(void *[], int, int, funcP);
int strCmp(char *, char *);
int numcmp(char *, char *);
int foldCmp(char *, char *);
int dirCmp(char *, char *);
funcP comparator(int);
/* globals */
static char allocbuf[ALLOCSIZE]; /* storage for alloc */
static char *allocp = allocbuf; /* next free position */
static char option; /* bit flag (1 byte in size) */
/* getLine: get line into s, return length of s -- pointer version */
int getLine(char *s, int lim)
{
int c, len;
len = 0;
while (--lim > 0 && (c = getchar()) != EOF && c != '\n') {
*s++ = c;
++len;
}
if (c == '\n') {
*s++ = c;
++len;
}
*s = '\0';
return len;
}
/* readlines: read input lines */
int readlines(char *lineptr[], int maxlines)
{
int len, nlines;
char *p, line[MAXLEN];
nlines = 0;
while ((len = getLine(line, MAXLEN)) > 0) {
if (nlines >= maxlines || (p = alloc(len)) == NULL)
return -1;
line[len - 1] = '\0'; /* delete newline character */
strcpy(p, line);
lineptr[nlines++] = p;
}
return nlines;
}
/* writelines: write output lines */
void writelines(char *lineptr[], int nlines, int reverse)
{
if (reverse)
while (--nlines > 0) /* print lines in reverser order */
printf("%s\n", lineptr[nlines]);
else
while (nlines-- > 0)
printf("%s\n", *lineptr++);
}
/* alloc: return pointer to n characters */
char *alloc(int n)
{
if (allocbuf + ALLOCSIZE - allocp < n)
return 0; /* not enough room */
allocp += n;
return allocp - n; /* old p */
}
/* swap: swap the values of v[i] and v[j]. */
void swap(void *v[], int i, int j)
{
void *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
/* qsort: sort v[left]...V[right] into increasing order */
void qSort(void *v[], int left, int right, funcP comp)
{
int i, last;
void swap(void *v[], int, int);
if (left >= right) /* do nothing if array contains */
return; /* fewer than two elements */
swap(v, left, (left + right) / 2);
last = left;
for (i = left + 1; i <= right; i++)
if ((*comp)(v[i], v[left]) < 0)
swap(v, ++last, i);
swap(v, left, last);
qSort(v, left, last - 1, comp);
qSort(v, last + 1, right, comp);
}
/* strCmp: return < 0 if s < t, 0 if s == t, > 0 if s > t */
int strCmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == '\0')
return 0;
return *s - *t;
}
/* numcmp: compare s1 and s2 numerically */
int numcmp(char *s1, char *s2)
{
double v1, v2;
v1 = atof(s1);
v2 = atof(s2);
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
}
/* foldCmp: perform case-insensitive comparison between s and t */
int foldCmp(char *s, char *t)
{
char str1[MAXLEN], str2[MAXLEN];
int i;
funcP fp;
for (i = 0; *s; ++s)
str1[i++] = tolower(*s);
str1[i] = '\0';
for (i = 0; *t; ++t)
str2[i++] = tolower(*t);
str2[i] = '\0';
fp = comparator(option & DIRORDER); /* strCmp or dirCmp, exclude other options */
return fp(str1, str2);
}
/* dirCmp: perform directory-order comparison--compare only letters, numbers
* and blanks. */
int dirCmp(char *s, char *t)
{
int i;
char str1[MAXLEN], str2[MAXLEN];
for (i = 0; *s != '\0'; ++s)
if (isalnum(*s) || isblank(*s))
str1[i++] = *s;
str1[i] = '\0';
for (i = 0; *t != '\0'; ++t)
if (isalnum(*t) || isblank(*t))
str2[i++] = *t;
str2[i] = '\0';
return strCmp(str1, str2);
}
/* comparator: return a function pointer to the compare function corresponding
* to the input option(s). If no option was provided, i.e. the bit flag
* 'option' was 0, return a function pointer to strCmp. */
funcP comparator(int option)
{
/*
* Because functions could use the comparator function to determine which
* operation to perform, the order of the checks is important. Moreover,
* when calling the comparator, the calling function must exclude itself
* and any preceding options in the checks order from the option bit flag.
*/
return (funcP) (option & NUMERIC ? numcmp : option & FOLD ? foldCmp :
option & DIRORDER ? dirCmp : strCmp);
}
/* sort input lines */
int main(int argc, char *argv[])
{
char *lineptr[MAXLINES]; /* pointers to text lines */
int nlines; /* number of input lines read */
/* Note: no input error checking */
option = 0;
while (--argc > 0) {
++argv;
if (!strCmp(argv[0], "-n"))
option |= NUMERIC;
if (!strCmp(argv[0], "-r"))
option |= REVERSE;
if (!strCmp(argv[0], "-f"))
option |= FOLD;
if (!strCmp(argv[0], "-d"))
option |= DIRORDER;
}
if ((nlines = readlines(lineptr, MAXLINES)) < 0) {
printf("input too big to sort\n");
return 1;
}
qSort((void**) lineptr, 0, nlines - 1, comparator(option));
writelines(lineptr, nlines, option & REVERSE);
return 0;
}