我正在使用以下内容来打印文件的行:
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
分配存储空间,因此您需要在完成buffer
后free()
- 除了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 文本文件是一个问题,很好地打印思想空字符有助于识别问题。