提问人:hansoko 提问时间:9/11/2023 最后编辑:hansoko 更新时间:9/11/2023 访问量:62
为什么我的程序不能正确处理大文件(650M)?K&R 发挥 5-13 尾巴
Why doesn't my program work with large files(650M) correctly? K&R exersice 5-13 tail
问:
练习 5-13。编写程序尾部,打印最后 n 行 的输入。默认情况下,n 设置为 10,让我们说,但它可以是 通过可选参数更改,以便“tail -n”打印最后 n 线。无论如何,程序都应该理性地运行 n的输入或值不合理。编写程序,使其 充分利用可用存储空间;行应按 第 5.6 节的排序程序,不在二维数组中 固定大小。
我写的代码(我把它放在帖子的末尾)适用于小文件,但是当它是一个大文件时,它会给出奇怪的输出。该文件约为 650 兆字节,每行超过 1000 个字符,除了最后 11 行:1、2、3 到 11。当我使用 -11 运行它时,此输出一切正常:
Printing 11 lines
1
2
3
4
5
6
7
8
9
10
11
但是当我用 -1 运行它时,我得到以下输出:
Printing 1 line
input too big too handle
与运行大约需要 5 或 6 秒的 -11 不同,这个运行速度非常快,这意味着错误在程序中发生得太早。输出与 -1 中的输出相同,具有 -2、-3 和 -4。 在 -5 时,我得到这个:
Printing 5 lines
1
8
9
10
11
使用 -6 这个:
Printing 6 lines
1
7
8
9
10
11
它在 -7 及更高版本下正常工作:
Printing 7 lines
5
6
7
8
9
10
11
如果我删除最后一行 11,并使用 -5 或 -6 运行它,我会得到以下输出:
Printing 5 lines
7
8
9
10
和
Printing 6 lines
6
7
8
9
10
这是我写的代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int isint(char s[]);
int toint(char s[]); /* convert s to an integer */
int readlines(char *lineptr[], int no); /* read the last 'no' lines and save them in lineptr */
void writelines(char *lineptr[], int no);
#define MAXLINE 100 /* the maximum acceptable number of lines to be printed */
int main(int argc, char *argv[])
{
int n = 10;
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 (readlines(lineptr, n) >= 0) {
writelines(lineptr, n);
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 /* maximum acceptable length of a line to be saved */
int readlines(char *lineptr[], int no)
{
char *alloc(int n, int no);
int get_line(char *, int); /* returns the length of a line excluding '\0' */
void push(char *lineptr[], char *p, int len); /* pushes a pointer in lineptr */
int len, i;
char *p, line[MAXLEN];
for (i = 0; i < no; i++)
lineptr[i] = NULL; /* in case the number of to-be-printed lines is less thatn 'no' */
while ((len = get_line(line, MAXLEN)) > 0)
if ((p = alloc(len, no)) == NULL) {
return -1;
} else {
line[len-1] = '\0'; /* remove the nl character, -*/
/*-the last line of input is expected to end in a nl */
strcpy(p, line);
push(lineptr, p, no);
}
return 1;
}
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)
{
int i;
for (i = 0; i < no-1; i++)
lineptr[i] = lineptr[i+1];
lineptr[no-1] = p;
}
#define ALLOCSIZE MAXLINE * MAXLEN
static char allocbuf[ALLOCSIZE];
static int allocn = 0; /* the number of allocations */
static char *allocp = allocbuf;
static char *leftalloc = allocbuf; /* left edge of the replaceable section of array */
static char *rightalloc = allocbuf - 1; /* right edge of the replaceable section of array */
char *alloc(int n, int no)
{
int i;
char *j;
if (allocn%no == no - 1) {
leftalloc = allocbuf;
rightalloc = allocbuf - 1; /* no line is replaceable yet */
}
if (allocn >= no) {
while (allocn-no >= no) /* reduce allocn to congruent modulo 'no' value to prevent overflow */
allocn -= no;
for (i = 0; i < allocn%no; i++)
while (*rightalloc++ != '\0');
;
}
if (n <= rightalloc - leftalloc + 1) {
leftalloc += n;
allocn++;
return leftalloc - n;
} else if (n <= allocbuf + ALLOCSIZE - allocp) {
allocp += n;
allocn++;
return allocp - n;
} else
return NULL;
}
我检查了一下,问题很可能来自alloc函数
答: 暂无答案
下一个:从反射中获取的转换列表
评论
readlines