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

标签 c file fgets tail fseek

总的来说,我是编程新手。请注意,这是作业。 我正在使用 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;
}

请帮忙!

最佳答案

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

您的程序应该能够打印前 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;
}

关于C程序打印文件中的第一行和最后n行,我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35397725/

相关文章:

excel - 如何缩小一个巨大的Excel文件

javascript - 在 JavaScript 中将 base64 图像转换为文件对象

c++ - 在 C++ 中读取前缀

c - 不兼容的编译错误内置函数 ‘execl’

C分配不同大小的二维数组

objective-c - iOS:在c代码中获取文件路径

c - 字符串没有被比较?或者输入正确?

c - 猜单词 : I/O C logic error

c - 我的循环队列实现无法正常工作

我可以正确地比较 avx 中的零寄存器吗?