rewrote readlines

master
Tibor Bizjak 2023-07-18 23:48:37 +02:00
parent 9df28e0ec9
commit a481bec3ba
1 changed files with 44 additions and 60 deletions

View File

@ -1,41 +1,36 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <ctype.h>
#include <limits.h>
#include <assert.h>
/* array bounds */ /* array bounds */
#define MAXLINES 10 #define MAXLINES 100
#define BUFF_SIZE 1000 #define BUFF_SIZE (80 * 100)
/* error return values */
#define GETLINE_OVERFLOW -2
#define READLINES_OVERFLOW -1
int readlines(char *lines[], int maxlines, char *ln_buff, size_t lb_size); int readlines(char *lines[], int maxlines, char *ln_buff, size_t lb_size);
void writelines(char *lines[], int n); void writelines(char *lines[], int n);
void qsort_string(char *v[], int left, int right); void qsort_string(char *v[], int left, int right);
/* sorts lines from stdin and prints them */
int main() int main()
{ {
char *lines[MAXLINES]; 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) { if (line_count >= 0) {
qsort_string(lines, 0, line_count-1); qsort_string(lines, 0, line_count-1);
writelines(lines, line_count); writelines(lines, line_count);
} else if (line_count == READLINES_OVERFLOW) { } else if (line_count == -1) {
puts("error: too many lines!"); puts("error: lines overflow");
return 1; return 1;
} else if (line_count == GETLINE_OVERFLOW) { } else if (line_count == -2) {
puts("error: line too long!"); puts("error: buffer overflow");
return 2; return 2;
} }
return 0; return 0;
} }
/* ---------- reading/printing functions */ /* ---------- reading/printing functions */
#include <string.h>
/* writelines: prints n lines */ /* writelines: prints n lines */
void writelines(char *lines[], int n) void writelines(char *lines[], int n)
{ {
@ -43,49 +38,44 @@ void writelines(char *lines[], int n)
printf("%s\n", *lines++); printf("%s\n", *lines++);
} }
int getln(char *ln_buff, size_t size); /* readlines: reads lines from input, writing them to ln_buff
* and line pointers to lines. returns number of lines read,
/* readlines: reads lines from input, writing them to ln_buff and line * -1 on lines overflow
* start pointers to lines. returns number of lines read or * -2 on buffer overflow */
* GETLINE_OVERFLOW or READLINES_OVERFLOW */ int readlines(char *lines[], int maxlines, char *buffer, size_t buff_size)
int readlines(char *lines[], int maxlines, char *ln_buff, size_t lb_size)
{ {
assert(maxlines); char ** const fst_line = lines;
int len; char *ln_start = buffer;
char ** const lines_start = lines; int c, not_empty = 0;
while ((len = getln(ln_buff, lb_size)) >= 0 && --maxlines) { for (; (c = getchar()) != EOF && buff_size; --buff_size) {
*lines++ = ln_buff; not_empty |= !isspace(c);
ln_buff += len + 1; if (c == '\n') {
lb_size -= len + 1; 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;
} }
/* ignore trailing whitespace and emepty lines */
if (!maxlines) while (c != EOF && isspace(c))
return READLINES_OVERFLOW; c = getchar();
if (len == GETLINE_OVERFLOW) if (!maxlines && c != EOF) /* lines overflow */
return GETLINE_OVERFLOW; return -1;
if (*ln_buff) if (!buff_size && c != EOF) /* buffer overflow */
*lines++ = ln_buff; return -2;
return lines - lines_start; return lines - fst_line;
} }
/* getln: gets line from stdin and writes it to ln_buff /* ---------- string quicksort */
* 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] */ /* swap: swap v[i] and v[j] */
void swap(char *v[], int i, int 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); 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