C语言 K&R练习5-13如何让我的程序处理无限行的输入

im9ewurl  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(105)

练习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个字符长的部分作为解决方案,但这本质上是一个手动的二维数组和重新发明轮子,而不是书中要求我做的。我只能想到少数几个设计,这些设计真的很难实现。

d8tt03nd

d8tt03nd1#

看起来有点乱,但我想出来了:

#define ALLOCSIZE MAXLINE * MAXLEN

static char allocbuf[ALLOCSIZE];
static int allocn = 0; /* the number of allocations */
static char *allocp = allocbuf;
static char *backallocp = allocbuf; /* the start of replaceable section of array */
static char *backallocpend = allocbuf - 1; /* the end of replaceable section of array */

char *alloc(int n, int no)
{
    int i;
    char *j;

    if (allocn%no == no - 1) {
        backallocp = allocbuf;
        backallocpend = allocbuf - 1;
    }
    if (allocn >= no) {
        while (allocn-no >= no)
            allocn -= no;
        for (i = 0; i < allocn%no; i++)
            while (*backallocpend++ != '\0');
                ;
    }

    if (n <= backallocpend - backallocp + 1) {
        backallocp += n;
        allocn++;
        return backallocp - n;
    } else if (n <= allocbuf + ALLOCSIZE - allocp) {
        allocp += n;
        allocn++;
        return allocp - n;
    } else
        return NULL;
}

相关问题