我需要再问一个有关从标准输入中阅读的问题。 我正在从标准输入中读取大量的行,但是绝对不知道这是每行的大小。因此,我不想只为一行包含三个char的文件而不是一个使用每行50 Mio的文件的缓冲区提供类似50Mio的缓冲区。 因此,目前我有以下代码:
int cur_max = 2047;
char *str = malloc(sizeof(char) * cur_max);
int length = 0;
while(fgets(str, sizeof(str), stdin) != NULL) {
//do something with str
//for example printing
printf("%s",str);
}
free(str);
因此,我在每行中使用fgets,并且每行的初始大小为2047个字符。 我的计划是在一行达到极限时增加缓冲区(str)的大小。所以我的想法是用长度计算大小,如果当前长度大于cur_max,那么我会将cur_max加倍。 这个想法来自这里Read line from file without knowing the line length 我目前不确定如何使用fgets进行此操作,因为我认为fgets不会按字符进行此char操作,因此我不知道何时增加大小。
答案 0 :(得分:2)
sizeof(str)
是指针的大小,例如2、4或8个字节。将fgets()
指向的内存大小传递到str
。 @Andrew Henle @Steve Summit
char *str = malloc(sizeof(char) * cur_max);
...
// while(fgets(str, sizeof(str), stdin) != NULL
while(fgets(str, cur_max, stdin) != NULL
文本文件和fgets()
并不是读取超长行的便携式解决方案。
实现应支持文本文件,该文件的行至少包含254个字符,包括终止换行符。宏
BUFSIZ
的值至少应为256 C11§7.21.29
因此,一旦行长超过BUFSIZ - 2
,C标准库函数是否可以处理文本文件的代码就由自己决定。
所以要么以二进制形式读取数据,要么使用其他确保所需功能的库,要么依赖希望。
注意:BUFSIZ
中定义的<stdio.h>
答案 1 :(得分:1)
POSIX.1 getline()
(man 3 getline
)在几乎所有操作系统的C库中都可用(我所知道的唯一例外是Windows)。读取任意长度的线的循环是
char *line_ptr = NULL;
size_t line_max = 0;
ssize_t line_len;
while (1) {
line_len = getline(&line_ptr, &line_max, stdin);
if (line_len == -1)
break;
/* You now have 'line_len' chars at 'line_ptr',
but it may contain embedded nul chars ('\0').
Also, line_ptr[line_len] == '\0'.
*/
}
/* Discard dynamically allocated buffer; allow reuse later. */
free(line_ptr);
line_ptr = NULL;
line_max = 0;
还有一个相关函数getdelim()
,它带有一个额外的参数(在流之前指定),用作记录结束标记。从Unixy / POSIXy环境中读取文件名时特别有用。标准输入,因为您可以使用nul本身('\0'
)作为分隔符(例如,参见find -print0
或xargs -0
),从而可以正确处理所有可能的文件名。
如果您使用Windows,或者您的文本文件具有不同的换行约定(不仅是'\n'
,还包括'\n'
,'\r'
,"\r\n"
或{ {1}}),您可以使用我的另一个答案中的getline_universal()
函数实现。它与标准"\n\r"
和getline()
的不同之处在于,换行符不包含在它返回的行中。它也留在流中,并被对fgets()
的 next 调用所消耗/忽略。如果您使用getline_universal()
来读取文件或流中的每一行,它将按预期工作。