K&R习题5-13:如何实现符合内存要求的无限行输入tail程序
K&R习题5-13实现疑问
习题5-13:编写tail程序,打印输入的最后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字符长的段作为解决方案,但这本质上是手动实现二维数组,属于重复造轮子,不符合书籍要求。我只能想到几种设计方案,但实现难度都很大。
内容的提问来源于stack exchange,提问作者hansoko
相关产品推荐
相关产品推荐

