如果您不知道要读取的字符数量,如何使用fgets?

10
我需要读取一个文件并将其发送到一个字符串中,以便我可以解析它。然而,程序不会知道文件的确切长度,如果我想使用fgets(),该怎么办?还是有更好的替代方案吗?
char *fgets(char *str, size_t num, FILE *stream);

1
你的标题暗示你想使用fgets,但文本暗示你正在寻找替代方案。是什么让你首先选择了fgets? - default
4个回答

11

别忘了,fgets() 是一次读取一行,但前提是有足够的空间。

人们很少写超过...80、256或自定义的字符数的长行。POSIX建议每行的长度为4096个字符。因此,我通常使用:

char buffer[4096];

while (fgets(buffer, sizeof(buffer), fp)) 
{
    ...process line...
}

如果您担心某人可能在单行中提供超过4K的数据(如HTML或JSON等机器生成的文件),那么您需要决定下一步该做什么。您可以执行以下任何操作(还有可能我没有提到的其他选项):

  1. 逐位处理过长的行,而不假定之间有换行符。
  2. 为更长的行(比如8K)分配内存,将最初的4K复制到已分配的缓冲区中,并将更多数据读入缓冲区的后半部分,迭代直到找到行末。
  3. 使用Linux上可用的POSIX 2008函数getline(),它会为您进行内存分配。

3
你可以使用fgets进行迭代,但更简单的替代方法是(stdio.h的)getline。它在POSIX中,但不是标准C。
由于你正在使用C ++,所以可以使用std :: string函数,如iostream的getline吗?

3

0

分配一个缓冲区(即str指向的缓冲区),并将缓冲区的大小传递给num。实际占用的空间只有fgets读取的文本长度。

类似于:

char str[1000];
fgets(str, 1000, &file);

如果下一行在换行符之前只有10个字符,则str将包含这些10个字符、换行符和空终止符。 编辑:以防有任何混淆,我并不是打算让上面的内容听起来好像缓冲区中的多余空格没有被使用。我只是想说明,只要您可以给字符串设定一个最大长度,就无需预先知道字符串的长度。

除非您重新分配缓冲区,否则任何额外的空间仍在使用中。这样怎么样? - Matthew Flaschen
我指的是缓冲区中的空间,而不是内存中的空间。此外,OP的问题并不是关于如何节省内存的。 - danben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接