From a481bec3ba9a5e07090bcba8359edf2c4002cb8a Mon Sep 17 00:00:00 2001 From: Tibor Bizjak Date: Tue, 18 Jul 2023 23:48:37 +0200 Subject: [PATCH] rewrote readlines --- k&r/05-pointers-and-arrays/05-07-sort.c | 104 ++++++++++-------------- 1 file changed, 44 insertions(+), 60 deletions(-) diff --git a/k&r/05-pointers-and-arrays/05-07-sort.c b/k&r/05-pointers-and-arrays/05-07-sort.c index d52771e..6a8015e 100644 --- a/k&r/05-pointers-and-arrays/05-07-sort.c +++ b/k&r/05-pointers-and-arrays/05-07-sort.c @@ -1,41 +1,36 @@ #include -#include -#include -#include +#include /* array bounds */ -#define MAXLINES 10 -#define BUFF_SIZE 1000 - -/* error return values */ -#define GETLINE_OVERFLOW -2 -#define READLINES_OVERFLOW -1 +#define MAXLINES 100 +#define BUFF_SIZE (80 * 100) 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); +/* sorts lines from stdin and prints them */ int main() { char *lines[MAXLINES]; - char ln_buff[BUFF_SIZE]; + char buffer[BUFF_SIZE]; - int line_count = readlines(lines, MAXLINES, ln_buff, BUFF_SIZE); - + int line_count = readlines(lines, MAXLINES, buffer, 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!"); + } else if (line_count == -1) { + puts("error: lines overflow"); return 1; - } else if (line_count == GETLINE_OVERFLOW) { - puts("error: line too long!"); + } else if (line_count == -2) { + puts("error: buffer overflow"); return 2; } return 0; } /* ---------- reading/printing functions */ +#include /* writelines: prints n lines */ void writelines(char *lines[], int n) { @@ -43,49 +38,44 @@ void writelines(char *lines[], int 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) +/* readlines: reads lines from input, writing them to ln_buff + * and line pointers to lines. returns number of lines read, + * -1 on lines overflow + * -2 on buffer overflow */ +int readlines(char *lines[], int maxlines, char *buffer, size_t buff_size) { - assert(maxlines); - int len; - char ** const lines_start = lines; + char ** const fst_line = lines; + char *ln_start = buffer; + int c, not_empty = 0; - while ((len = getln(ln_buff, lb_size)) >= 0 && --maxlines) { - *lines++ = ln_buff; - ln_buff += len + 1; - lb_size -= len + 1; + for (; (c = getchar()) != EOF && buff_size; --buff_size) { + not_empty |= !isspace(c); + if (c == '\n') { + if (!not_empty) { /* skip empty lines */ + buff_size += buffer - ln_start; + buffer = ln_start; + continue; + } + *buffer++ = '\0'; + *lines++ = ln_start; + if (!--maxlines) + break; + not_empty = 0; + ln_start = buffer; + } else + *buffer++ = c; } - - if (!maxlines) - return READLINES_OVERFLOW; - if (len == GETLINE_OVERFLOW) - return GETLINE_OVERFLOW; - if (*ln_buff) - *lines++ = ln_buff; - return lines - lines_start; + /* ignore trailing whitespace and emepty lines */ + while (c != EOF && isspace(c)) + c = getchar(); + if (!maxlines && c != EOF) /* lines overflow */ + return -1; + if (!buff_size && c != EOF) /* buffer overflow */ + return -2; + return lines - fst_line; } -/* 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 */ +/* ---------- string quicksort */ /* swap: swap v[i] and v[j] */ void swap(char *v[], int i, int j) { @@ -113,9 +103,3 @@ void qsort_string(char *v[], int left, int right) 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 -