C语言 使用 getline vs fgets 进行基本文件打印



我正在使用以下内容来打印文件的行:

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(( vs. fgets((:控制内存分配。

您只需查看 getline(3( - Linux 手册页,即可确定要传递的适当参数类型和要处理的返回类型以及getline如何指示成功/失败。

然后,所需要的只是将代码中的fgets()替换为getline()。所有面向行的输入函数都读取并包含尾随'n',因此没有变化。但是,请注意,getline()为您的buffer分配存储空间,因此您需要在完成bufferfree()- 除了stdio.h之外,还需要包含stdlib.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.

示例使用/输出

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

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

不常见的是,输入流包含空字符''

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

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

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

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

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()内是如何工作的,因为这是一个不同的实现细节。

虽然空字符

不常见是简单的文本文件,但我发现编写代码最好为空字符做好准备。他们很容易想到的是读取UTF16编码的文本文件。当然,期望一个 ASCII 或 UTF8 文本文件并获得一个 UTF16 文本文件是一个问题,很好地打印思想空字符有助于识别问题。

最新更新