使用 getline 与 fgets 进行基本文件打印

Using getline vs fgets for basic file printing

我正在使用以下命令打印文件的行:

int main() {

    FILE *fptr = fopen("test20k.csv", "r");
    char buffer[MAXLINE];

    while (fgets(buffer, sizeof(buffer), fptr) != NULL)
        printf("%s", buffer);
    putchar('\n');

    return 0;

}

如何使用 getline 完成同样的事情?这是一个更概念化的类似问题:.

您只需检查 getline(3) - Linux manual page 以确定要传递的适当参数类型和要处理的 return 类型以及 getline 如何指示 success/failure。

然后只需将代码中的 fgets() 替换为 getline() 即可。所有 line-oriented 输入函数读取并包含尾随 '\n',因此那里没有变化。但是,请注意 getline() 为您的 buffer 分配存储空间,因此您需要 free() 完成后 buffer -- 要求您包含 [=21] =] 除了 stdio.h.

此外,您注意到 getline 不是标准 C 库的一部分。相反,getline 是一个 POSIX 函数,因此并非每个 C 实现都需要提供它,因此您可能会遇到可移植性问题。

基本上就是这样。但是,在您的代码中,您不应使用 硬编码文件名 。这就是 main() 接受参数的原因之一。因此,只需将要读取的文件名作为第一个参数传递给您的程序(如果没有提供参数,您也可以默认从 stdin 读取)

将它们放在一起,作为最低限度的实现,您可以这样做:

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

int main (int argc, char **argv) {

    size_t n = 0;           /* initial alloc size, 0 - getline decides */
    char *buffer = NULL;    /* pointer to block of mem holding input */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fptr = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fptr) {    /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    /* you pass the address of your buffer and a pointer to n */
    while (getline (&buffer, &n, fptr) != -1)
        printf("%s", buffer);
    putchar('\n');

    if (fptr != stdin)   /* close file if not stdin */
        fclose (fptr);

    free (buffer);      /* getline allocates, don't forget to free */

    return 0;
}

检查一下,如果您还有其他问题,请告诉我。

示例输入文件

$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

例子Use/Output

$ ./bin/getline_file dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

fgets()/getline()常用于阅读文本.

不常见的是,输入流包含 空字符 '[=13=]'.

fgets() 像任何字符一样读取 空字符 。它不会停止读取输入的

以下仅打印到 字符串 中遇到的第一个 空字符 - 它与读取 [=37= 没有区别]空字符和fgets()添加的附加空字符

while (fgets(buffer, sizeof(buffer), fptr)) {
  printf("%s", buffer);  // Maybe stops too early?
}

getline(),虽然不是标准的 C,但有一个优势,因为它 returns 读取的字符数。然后打印可以打印到返回的计数,而不是仅打印到第一个 空字符 .

size_t n = 0;
char *buffer = NULL;

ssize_t sz;
while ((sz = getline (&buffer, &n, fptr)) != -1) {
  fwrite(buffer, 1, sz, stdout);
}

free(buffer);

注:size_t n = 0; char *buffer = NULL;为初始设置。 getline (&buffer, &n, ...) 接收这两个变量的地址,允许它根据需要更新这两个变量(由于重新分配)。最大缓冲区大小为 SIZE_MAX 或内存池的限制。我们不需要知道它在 getline() 中是如何工作的,因为这是一个不同的实现细节。


虽然 空字符 在简单的文本文件中并不常见,但我发现编写最适合 be prepared for for null characters. They readily come up is reading a text file that is UTF16 encoded. Of course expecting an ASCII or UTF8 文本文件的代码并获得 UTF16 是一个问题,很好地打印想法 空字符 有助于识别问题。