C程序打印文件中的第一行和最后n行,我做错了什么?

C Program to print first and last n lines in a file, what am I doing wrong?

总的来说,我是编程新手。请注意,这是作业。 我正在使用 a-z 小写的 txt 文件。 我用命令./a.out test.txt到运行程序,然后输入一个数字。

我的代码:

#include <stdio.h>

static void cat(FILE *fp, int num) {
    int count = 0;
    char buffer[4096];

    while (fgets(buffer, sizeof(buffer), fp) != 0) {
        if (count == num)
            break;
        else
            count++;
        fputs(buffer, stdout);
    }
}

int main(int argc, char *argv[]) {
    int num, count = 0;
    long length;
    char buffer[4096];

    FILE *fp;
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        printf("Can't open this file\n");
        return 0;
    }

    scanf("%d", &num);
    cat(fp, num);
    printf("...\n");

    fseek(fp, 0, SEEK_END);
    length = ftell(fp);
    fseek(fp, (length - 2), SEEK_SET);
    printf("1\n");
    while (fgets(buffer, sizeof(buffer), fp) != 0) {
        fputs(buffer, stdout);
    }
    if (ftell(fp) == '\n') {
        count++;
        length = ftell(fp);
        fseek(fp, (length - 4), SEEK_SET);
        printf("2\n");
        while (fgets(buffer, sizeof(buffer), fp) != 0) {
            fputs(buffer, stdout);
        }
    } else {  //<------ missing opening brace
        length = ftell(fp);
        fseek(fp, (length - 2), SEEK_SET);
        printf("3\n");
        while (fgets(buffer,s izeof(buffer), fp) != 0) {
            fputs(buffer, stdout);
        }
        if (count == num) {
            printf("4\n");
            while (fgets(buffer, sizeof(buffer), fp) != 0) {
                fputs(buffer, stdout);
        }
    }

    fclose(fp);
    return 0;
}

请帮忙!

1) 您应该检查文件大小是否小于缓冲区大小。

2) 如果您打算一次读取文件中的 n 行数据块,请一次读取一行。可能使用 fscanf。这样你就可以跟踪你有多少行 read/printed。这也有助于了解您的文件是否有足够的行数。

我重新格式化了您的代码以提高可读性。我指出的地方缺少 {。正如发布的那样,代码无法编译。

您的程序应该能够打印前 n 行,但您的方法不适用于最后 n 行。

分配 n 个缓冲区数组:

char (*array)[4096] = calloc(4096, num);

对于读取的每一行,移动缓冲区并复制最后位置的行:

memmove(array[0], array[1], sizeof(array[0] * (num - 1));
strcpy(array[num - 1], buffer);

还有更有效的方法,但您应该能够实现这个简单的方法。

到达文件末尾时,打印数组中的非空行。

编辑:

这是一个完整的版本,它使用了一个 num+1 缓冲区数组。它读取整个文件,在读取时打印前 num 行,并始终将最后 num 行保留在数组中,循环读取下一行的位置 num+1缓冲区。

在文件末尾,如果文件超过 num 行,则必须打印额外的行,如果在文件中间跳过行,则可能用 -------- 分隔.打印最后 num 行或更少行:计算 pos 以找到正确的缓冲区模数 num+1 并且打印行直到最后。

代码如下:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int num, pos, count;
    FILE *fp;
    char (*array)[4096];  /* pointer to an array of buffers */

    if (argc < 2) {
        printf("Usage headtail filename [number]\n");
        return 1;
    }
    fp = fopen(argv[1], "r");
    if (fp == NULL) {
        printf("Cannot open file %s\n", argv[1]);
        return 1;
    }
    if (argc > 2) {
        /* get the number from the command line if 2 args were given */
        if (sscanf(argv[2], "%d", &num) != 1) {
            num = -1;
        }
    } else {
        /* otherwise read from standard input */
        if (scanf("%d", &num) != 1) {
            num = -1;
        }
    }
    if (num < 0) {
        printf("Invalid number\n");  /* negative or non numeric */
        return 1;
    }

    /* allocate space for num+1 buffers */
    array = malloc(4096 * (num + 1));

    for (count = pos = 0; fgets(array[pos], 4096, fp) != NULL; count++) {
        /* printing the first num lines */
        if (count < num)
            fputs(array[pos], stdout);
        /* cycle buffers for num lines + 1 extra buffer */
        if (++pos >= num + 1)
            pos = 0;
    }
    if (count > num) {
        /* more lines to print */
        pos = count - num;
        if (pos > num) {
            /* print place holder for missing lines */
            printf("...\n");
        } else {
            /* print from the last line printed */
            pos = num;
        }
        for (; pos < count; pos++) {
            fputs(array[pos % (num + 1)], stdout);
        }
    }
    fclose(fp);
    return 0;
}