From 9df28e0ec998c51d25cbe8d6c29d193659030d8f Mon Sep 17 00:00:00 2001 From: Tibor Bizjak Date: Tue, 18 Jul 2023 22:22:18 +0200 Subject: [PATCH] k&r section 5.6 excercise solution --- k&r/05-pointers-and-arrays/05-07-sort.c | 121 ++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 k&r/05-pointers-and-arrays/05-07-sort.c diff --git a/k&r/05-pointers-and-arrays/05-07-sort.c b/k&r/05-pointers-and-arrays/05-07-sort.c new file mode 100644 index 0000000..d52771e --- /dev/null +++ b/k&r/05-pointers-and-arrays/05-07-sort.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +/* array bounds */ +#define MAXLINES 10 +#define BUFF_SIZE 1000 + +/* error return values */ +#define GETLINE_OVERFLOW -2 +#define READLINES_OVERFLOW -1 + +int readlines(char *lines[], int maxlines, char *ln_buff, size_t lb_size); +void writelines(char *lines[], int n); +void qsort_string(char *v[], int left, int right); + +int main() +{ + char *lines[MAXLINES]; + char ln_buff[BUFF_SIZE]; + + int line_count = readlines(lines, MAXLINES, ln_buff, BUFF_SIZE); + + if (line_count >= 0) { + qsort_string(lines, 0, line_count-1); + writelines(lines, line_count); + } else if (line_count == READLINES_OVERFLOW) { + puts("error: too many lines!"); + return 1; + } else if (line_count == GETLINE_OVERFLOW) { + puts("error: line too long!"); + return 2; + } + return 0; +} + +/* ---------- reading/printing functions */ +/* writelines: prints n lines */ +void writelines(char *lines[], int n) +{ + while (n--) + printf("%s\n", *lines++); +} + +int getln(char *ln_buff, size_t size); + +/* readlines: reads lines from input, writing them to ln_buff and line + * start pointers to lines. returns number of lines read or + * GETLINE_OVERFLOW or READLINES_OVERFLOW */ +int readlines(char *lines[], int maxlines, char *ln_buff, size_t lb_size) +{ + assert(maxlines); + int len; + char ** const lines_start = lines; + + while ((len = getln(ln_buff, lb_size)) >= 0 && --maxlines) { + *lines++ = ln_buff; + ln_buff += len + 1; + lb_size -= len + 1; + } + + if (!maxlines) + return READLINES_OVERFLOW; + if (len == GETLINE_OVERFLOW) + return GETLINE_OVERFLOW; + if (*ln_buff) + *lines++ = ln_buff; + return lines - lines_start; +} + +/* getln: gets line from stdin and writes it to ln_buff + * returns line length (without '\n') or EOF or GETLINE_OVERFLOW */ +int getln(char *ln_buff, size_t size) +{ + assert(size); + char * const ln_start = ln_buff; + size = (size > INT_MAX) ? INT_MAX : size; + int c; + while ((c = getchar()) != EOF && c != '\n' && --size) + *ln_buff++ = c; + if (!size) + return GETLINE_OVERFLOW; + *ln_buff = '\0'; + return (c == EOF) ? EOF : ln_buff - ln_start; +} + +/* ---------- sorting functions */ +/* swap: swap v[i] and v[j] */ +void swap(char *v[], int i, int j) +{ + char *temp = v[i]; + v[i] = v[j], v[j] = temp; +} + + +/* qsort_string: sort v[left]...v[right] into increasing order */ +void qsort_string(char *v[], int left, int right) +{ + int i, last; + + if (left >= right) /* do nothing if array contains */ + return; /* fewer than two elements */ + swap(v, left, (left + right)/2); /* move partition elem */ + last = left; /* to v[0] */ + + for (i = left+1; i <= right; i++) /* partition */ + if (strcmp(v[i], v[left]) < 0) + swap(v, ++last, i); + swap(v, left, last); /* restore partition elem */ + + qsort_string(v, left, last-1); + qsort_string(v, last+1, right); +} + +/* ---------- static asserts */ +#define assert_diff(a, b) static_assert(a != b, #a " equals " #b) +assert_diff(GETLINE_OVERFLOW, EOF); +assert_diff(GETLINE_OVERFLOW, READLINES_OVERFLOW); +#undef assert_diff +