k&r section 5.6 excercise solution
parent
ee59768555
commit
9df28e0ec9
|
@ -0,0 +1,121 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* 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
|
||||
|
Loading…
Reference in New Issue