Page 118
Write the program tail, which prints the last n lines of its input. By default, n is
10, say, but it can be changed by an optional argument, so that tail -n
prints the
last n lines. The program should behave rationally no matter how unreasonable the
input or the value of n. Write the program so it makes the best use of available
storage; lines should be stored as in the sorting program of Section 5.6, not in a
two-dimensional array of fixed size.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define DEFAULT_PRINT_COUNT 10
#define STORE_SIZE 1000000
#define MAX_LINES 1000
#define MAX_LINE 1000
int get_line(char s[], int lim);
int main(int argc, char *argv[])
{
unsigned print_count = DEFAULT_PRINT_COUNT;
unsigned line_count;
char storage[STORE_SIZE];
char *lines[MAX_LINES];
int i;
while (--argc > 0) {
if (argv[argc][0] == '-') {
for (i = 1; isdigit(argv[argc][i]); i++)
;
if (argv[argc][i] == '\0') {
print_count = atoi(&argv[argc][1]);
} else {
printf("Invalid argument '%s'! Must be an integer.\n",
argv[argc]);
}
}
}
unsigned len;
unsigned used = 0;
for (; (len = get_line(storage + used, MAX_LINE)) > 0; line_count++) {
lines[line_count] = storage + used;
used += len + 1;
}
for (i = print_count > line_count ? 0 : line_count - print_count;
i < line_count; i++) {
printf("%s", lines[i]);
}
}
int get_line(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && (c = getchar()) != EOF && c != '\n') {
s[i++] = c;
}
if (c == '\n') {
s[i++] = c;
}
s[i] = '\0';
return i;
}