rewrote readlines
parent
9df28e0ec9
commit
a481bec3ba
|
@ -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
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue