练习5-13.写程序尾,它打印输入的最后n行。默认情况下,n设置为10,但可以通过可选参数进行更改,以便tail -n
打印最后n行。无论输入或n的值多么不合理,程序都应该理性地运行。编写程序,使其最大限度地利用可用存储空间;行应该像5.6节中的排序程序那样存储,而不是存储在固定大小的二维数组中。
这是我现在写的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int isint(char s[]);
int toint(char s[]);
int readlines(char *lineptr[], int no);
void writelines(char *lineptr[], int no);
#define MAXLINE 100
int main(int argc, char *argv[])
{
int n = 10, nlines;
char *lineptr[MAXLINE];
while (--argc > 0) {
if ((*++argv)[0] == '-' && isint(*argv) && toint(*argv) <= MAXLINE) {
n = toint(*argv);
break;
}
else
printf("invalid argument %s\n", *argv);
}
printf("Printing %d line%s\n", n, n > 1 ? "s" : "");
if ((nlines = readlines(lineptr, n)) >= 0) {
writelines(lineptr, nlines);
return 0;
}
else {
printf("input too big too handle\n");
return 1;
}
return 0;
}
int isint(char s[])
{
while (*s == '-' || *s == '0')
s++;
if (isdigit(*s)) {
while (*s != '\0')
if (!isdigit(*s++))
return 0;
return 1;
}
else
return 0;
}
int toint(char s[])
{
while (*s == '-' || *s == '0')
s++;
return atoi(s);
}
#define MAXLEN 1000
int readlines(char *lineptr[], int no)
{
char *alloc(int n, int no);
int get_line(char *, int);
void push(char *lineptr[], char *p, int len);
int nlines, len, i;
char *p, line[MAXLEN];
for (i = 0; i < no; i++)
lineptr[i] = NULL;
nlines = 0;
while ((len = get_line(line, MAXLEN)) > 0)
if ((p = alloc(len, no)) == NULL) {
return -1;
} else {
line[len-1] = '\0';
strcpy(p, line);
push(lineptr, p, no);
nlines++;
}
return no < nlines ? no : nlines;
}
void writelines(char *lineptr[], int no)
{
int i;
for (i = 0; i < no; i++)
if (lineptr[i] != NULL)
printf("%s\n", lineptr[i]);
}
int get_line(char *line, int lim)
{
int i, c;
i = 0;
while (--lim > 0 && (c = getchar()) != EOF && c != '\n')
line[i++] = c;
if (c == '\n')
line[i++] = c;
line[i] = '\0';
return i;
}
void push(char *lineptr[], char *p, int no)
{
void shift(int i)
{
if (i > 1)
shift(i-1);
lineptr[i-1] = lineptr[i];
}
shift(no-1);
lineptr[no-1] = p;
}
static char allocbuf[MAXLINE][MAXLEN];
static int allocn = 0;
char *alloc(int n, int no)
{
if (n < MAXLEN) {
allocn++;
return allocbuf[allocn%no];
} else
return NULL;
}
它可以处理无限多的行作为输入,但它使用了一个二维数组,这本书要求我像这样存储行:
#define ALLOCSIZE 10000
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;
char *alloc(int n)
{
if (n <= ALLOCSIZE - (allocp - allocbuf)) {
allocp += n;
return allocp - n;
} else
return NULL;
}
void afree(char *p)
{
if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
allocp = p;
}
这样我就不能用新的行替换我存储的过时的行。我可以将allocbuf
拆分成多个1000个字符长的部分作为解决方案,但这本质上是一个手动的二维数组和重新发明轮子,而不是书中要求我做的。我只能想到少数几个设计,这些设计真的很难实现。
1条答案
按热度按时间d8tt03nd1#
看起来有点乱,但我想出来了: