-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy path5-15.c
199 lines (176 loc) · 4.81 KB
/
5-15.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
/*
* Exercise 5-15. Add the option -f to fold upper and lower case together, so
* that case distinctions are not made during sorting; for example, a and A
* compare equal.
*
* 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 100000 /* storage for alloc */
#define NUMERIC 01 /* numeric sort */
#define REVERSE 02 /* reverse sort */
#define FOLD 04 /* case-insensitive 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 *);
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);
}
/* 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;
}
/* 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;
}
/* foldCmp: perform case-insensitive comparison between s and t */
int foldCmp(char *s, char *t)
{
char str1[MAXLEN], str2[MAXLEN];
int i;
for (i = 0; *s; ++s)
str1[i++] = tolower(*s);
str1[i] = '\0';
for (i = 0; *t; ++t)
str2[i++] = tolower(*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 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 : 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") == 0)
option |= NUMERIC;
if (strCmp(argv[0], "-r") == 0)
option |= REVERSE;
if (strCmp(argv[0], "-f") == 0)
option |= FOLD;
}
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;
}