2023-07-18 22:22:18 +02:00
|
|
|
#include <stdio.h>
|
2023-07-18 23:48:37 +02:00
|
|
|
#include <ctype.h>
|
2023-07-19 11:17:23 +02:00
|
|
|
#include <assert.h>
|
2023-07-18 22:22:18 +02:00
|
|
|
|
|
|
|
/* array bounds */
|
2023-07-19 11:17:23 +02:00
|
|
|
#define MAXLINES 100
|
|
|
|
#define BUFF_SIZE (80 * MAXLINES)
|
2023-07-18 22:22:18 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2023-07-18 23:48:37 +02:00
|
|
|
/* sorts lines from stdin and prints them */
|
2023-07-18 22:22:18 +02:00
|
|
|
int main()
|
|
|
|
{
|
|
|
|
char *lines[MAXLINES];
|
2023-07-18 23:48:37 +02:00
|
|
|
char buffer[BUFF_SIZE];
|
2023-07-18 22:22:18 +02:00
|
|
|
|
2023-07-18 23:48:37 +02:00
|
|
|
int line_count = readlines(lines, MAXLINES, buffer, BUFF_SIZE);
|
2023-07-19 11:17:23 +02:00
|
|
|
if (line_count < 0) {
|
|
|
|
line_count = -line_count - 1;
|
|
|
|
printf("warning: buffer overflow occured, read %d lines\n", line_count);
|
|
|
|
} else if (line_count > MAXLINES) {
|
|
|
|
line_count = MAXLINES;
|
|
|
|
printf("warning: too many lines, read %d lines\n", line_count);
|
2023-07-18 22:22:18 +02:00
|
|
|
}
|
2023-07-19 11:17:23 +02:00
|
|
|
qsort_string(lines, 0, line_count-1);
|
|
|
|
writelines(lines, line_count);
|
2023-07-18 22:22:18 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------- reading/printing functions */
|
2023-07-18 23:48:37 +02:00
|
|
|
#include <string.h>
|
2023-07-18 22:22:18 +02:00
|
|
|
/* writelines: prints n lines */
|
|
|
|
void writelines(char *lines[], int n)
|
|
|
|
{
|
|
|
|
while (n--)
|
|
|
|
printf("%s\n", *lines++);
|
|
|
|
}
|
|
|
|
|
2023-07-18 23:48:37 +02:00
|
|
|
/* readlines: reads lines from input, writing them to ln_buff
|
2023-07-19 11:17:23 +02:00
|
|
|
* and line pointers to lines.
|
|
|
|
* returns number of lines read,
|
|
|
|
* -lines_read-1 < 0 on buffer overflow
|
|
|
|
* maxlines+1 on lines overflow */
|
2023-07-18 23:48:37 +02:00
|
|
|
int readlines(char *lines[], int maxlines, char *buffer, size_t buff_size)
|
2023-07-18 22:22:18 +02:00
|
|
|
{
|
2023-07-19 11:17:23 +02:00
|
|
|
assert(maxlines > 0);
|
2023-07-18 23:48:37 +02:00
|
|
|
char ** const fst_line = lines;
|
|
|
|
int c, not_empty = 0;
|
|
|
|
|
2023-07-19 11:17:23 +02:00
|
|
|
for (*lines = buffer; (c = getchar()) != EOF && buff_size; --buff_size) {
|
2023-07-18 23:48:37 +02:00
|
|
|
not_empty |= !isspace(c);
|
|
|
|
if (c == '\n') {
|
|
|
|
if (!not_empty) { /* skip empty lines */
|
2023-07-19 11:17:23 +02:00
|
|
|
buff_size += buffer - *lines;
|
|
|
|
buffer = *lines;
|
2023-07-18 23:48:37 +02:00
|
|
|
continue;
|
|
|
|
}
|
2023-07-19 11:17:23 +02:00
|
|
|
not_empty = 0;
|
2023-07-18 23:48:37 +02:00
|
|
|
*buffer++ = '\0';
|
|
|
|
if (!--maxlines)
|
|
|
|
break;
|
2023-07-19 11:17:23 +02:00
|
|
|
*++lines = buffer;
|
2023-07-18 23:48:37 +02:00
|
|
|
} else
|
|
|
|
*buffer++ = c;
|
2023-07-18 22:22:18 +02:00
|
|
|
}
|
2023-07-19 11:17:23 +02:00
|
|
|
/* ignore trailing whitespace and empty lines */
|
2023-07-18 23:48:37 +02:00
|
|
|
while (c != EOF && isspace(c))
|
|
|
|
c = getchar();
|
2023-07-19 11:17:23 +02:00
|
|
|
if (c != EOF && !buff_size) /* buffer overflow, return -lines_read-1 */
|
|
|
|
return fst_line - lines - 1;
|
|
|
|
if (c != EOF && !maxlines) /* lines overflow, return maxlines+1 */
|
|
|
|
return lines - fst_line + 2;
|
|
|
|
return lines - fst_line + not_empty;
|
2023-07-18 22:22:18 +02:00
|
|
|
}
|
|
|
|
|
2023-07-18 23:48:37 +02:00
|
|
|
/* ---------- string quicksort */
|
2023-07-18 22:22:18 +02:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|