aboutsummaryrefslogtreecommitdiff
path: root/5.17.c
diff options
context:
space:
mode:
Diffstat (limited to '5.17.c')
-rw-r--r--5.17.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/5.17.c b/5.17.c
new file mode 100644
index 0000000..3469a4e
--- /dev/null
+++ b/5.17.c
@@ -0,0 +1,259 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define MAXLINES 5000
+
+char *lineptr[MAXLINES];
+
+int realines(char *lineptr[], int max);
+void writelines(char *lineptr[], int nlins);
+void my_qsort(char *lineptr[], int left, int right, int (*cmp)(const char *, const char *));
+int numcmp(const char to[], const char from[]);
+int strcmp_ignore_case(const char str1[], const char str2[]);
+int reverse(const char str1[], const char str2[]);
+int mystcmp(const char to[], const char from[]);
+int (*compare)(const char str1[], const char str2[]);
+int (*strcmp_base)(const char to[], const char from[]);
+int isdirectory(char input);
+int field_skip(const char str[]);
+
+int directory_order_bool, field_bool;
+
+
+int
+main(int argc, char *argv[])
+{
+ char flag;
+ int numeric = 0, reverse_bool = 0, ignore_case_bool = 0;
+ int nlins;
+
+ while (--argc > 0 && **++argv == '-')
+ while ((flag = *++*argv))
+ switch (flag) {
+ case 'n' :
+ numeric = 1;
+ break;
+ case 'r' :
+ reverse_bool = 1;
+ break;
+ case 'f' :
+ ignore_case_bool = 1;
+ break;
+ case 'd' :
+ directory_order_bool = 1;
+ break;
+ case 'l' :
+ while (isdigit(*++*argv))
+ field_bool = field_bool * 10 + **argv - '0';
+
+ (*argv)--;
+ break;
+ default :
+ printf("Err: illigial option %c\n", flag);
+ }
+
+ if (argc)
+ printf("Usage: sort -nrf\n");
+ else if ((nlins = realines(lineptr, MAXLINES)) > 0) {
+
+ strcmp_base = ignore_case_bool ? strcmp_ignore_case : mystcmp;
+ compare = numeric ? numcmp : strcmp_base;
+
+ my_qsort(lineptr, 0, nlins - 1, reverse_bool ? reverse : compare);
+ writelines(lineptr, nlins);
+ }
+
+ return 0;
+}
+
+void swap(char *lineptr[], int to, int from);
+
+void
+my_qsort(char *lineptr[], int left, int right, int (*cmp)(const char *, const char *))
+{
+ int last, i;
+
+ if (left >= right)
+ return;
+
+ swap(lineptr, left, (left+right)/2);
+ last = left;
+
+ for (i = left+1; i <= right; i++) {
+ if ((*cmp)(lineptr[i], lineptr[left]) < 0)
+ swap(lineptr, ++last, i);
+
+ }
+ swap(lineptr, left, last);
+
+ my_qsort(lineptr, left, last-1, cmp);
+ my_qsort(lineptr, last+1, right, cmp);
+}
+
+int
+numcmp(const char to[], const char from[])
+{
+ if (field_bool) {
+ to += field_skip(to);
+ from += field_skip(from);
+ }
+
+ double n1 = atof(to);
+ double n2 = atof(from);
+
+ if (n1 < n2)
+ return -1;
+ else if (n1 > n2)
+ return 1;
+ else
+ return 0;
+}
+
+void
+swap(char *lineptr[], int to, int from)
+{
+ char *temp;
+
+ temp = lineptr[to];
+ lineptr[to] = lineptr[from];
+ lineptr[from] = temp;
+}
+
+void
+writelines(char *lineptr[], int nlins)
+{
+ while (nlins--)
+ printf("%s", *lineptr++);
+}
+
+#define MAXLEN 1000
+int sneed_getine(char str[], int max);
+
+int
+realines(char *lineptr[], int max)
+{
+ int len, nlins;
+ char buff[MAXLEN], *temp;
+
+ for (nlins = 0; (len = sneed_getine(buff, MAXLEN)) > 0; nlins++) {
+ if (nlins < max && (temp = malloc(len+1)) != NULL) {
+ strcpy(temp, buff);
+ lineptr[nlins] = temp;
+ }
+
+ else
+ return -1;
+ }
+
+ return nlins;
+}
+
+int
+sneed_getine(char str[], int max)
+{
+ char input;
+ char *str_og = str;
+
+ while ( --max && (input = getchar()) != EOF && input != '\n')
+ *str++ = input;
+
+ if (max && input == '\n')
+ *str++ = input;
+
+ *str = '\0';
+
+ return str - str_og;
+}
+
+int
+reverse(const char str1[], const char str2[])
+{
+ return (*compare)(str2, str1);
+}
+
+int
+strcmp_ignore_case(const char to[], const char from[])
+{
+ if (field_bool) {
+ to += field_skip(to);
+ from += field_skip(from);
+ }
+
+ if (directory_order_bool) {
+ for (; *to && *from; to++, from++)
+ if ((isdirectory(tolower(*from)) && tolower(*from) != tolower(*to)) || (field_bool && (isblank(*from) || isblank(*to))))
+ break;
+ }
+
+ else
+ for (; *to && *from && tolower(*to) == tolower(*from); to++, from++)
+ if (field_bool && (isblank(*from) || isblank(*to)))
+ break;
+
+ return tolower(*to) - tolower(*from);
+}
+
+int
+isdirectory(char input)
+{
+ if (isalpha(input) || isdigit(input) || isblank(input))
+ return 1;
+ else
+ return 0;
+}
+
+int
+mystcmp(const char to[], const char from[])
+{
+ if (field_bool) {
+ to += field_skip(to);
+ from += field_skip(from);
+ }
+
+ if (directory_order_bool) {
+ for (; *to && *from; to++, from++)
+ if ((isdirectory(*from) && *from != *to) || (field_bool && (isblank(*from) || isblank(*to))))
+ break;
+ }
+
+ else
+ for (; *to && *from && *to == *from; to++, from++)
+ if (field_bool && (isblank(*from) || isblank(*to)))
+ break;
+
+ return *to - *from;
+}
+
+int
+field_skip(const char str[])
+{
+ int count, inside;
+ const char *str_og;
+
+ str_og = str;
+
+ while (isblank(*str))
+ str++;
+
+ while (isblank(*str))
+ str++;
+
+ for (count = 1, inside = 1; count < field_bool && *str; str++) {
+ if (inside == 1 && isblank(*str))
+ inside = 0;
+
+ if (inside == 0 && !isblank(*str)) {
+ inside = 1;
+ count++;
+ }
+ }
+
+ if (count != field_bool) {
+ printf("Err: field not available\n");
+ return 0;
+ }
+
+ return str - str_og;
+}