13

我需要阅读一行文本(以换行符结尾)而不对长度做出假设。所以我现在面临着可能性:

  • fgets每次使用并检查最后一个字符是否为换行符并不断追加到缓冲区
  • 使用缓冲区读取每个字符fgetc,偶尔realloc使用缓冲区

直觉告诉我这个fgetc变体可能会更慢,但是我不知道fgets如果不检查每个角色怎么能做到(而且我的直觉并不总是那么好)。线条很大,所以性能很重要。

我想知道每种方法的优缺点。先感谢您。

4

5 回答 5

3

我建议fgets()与动态内存分配结合使用 - 或者您可以研究getline()POSIX 2008 标准中的接口,并且在更新的 Linux 机器上可用。这为您完成了内存分配工作。您需要密切关注缓冲区长度及其地址——因此您甚至可以自己创建一个结构来处理信息。

虽然fgetc()也有效,但它稍微有点复杂 - 但只是稍微如此。在封面之下,它使用与fgets(). 内部可能能够利用更快的操作 - 类似于strchr()- 当您直接调用时不可用fgetc()

于 2011-03-03T21:05:53.150 回答
2

您的环境是否提供该getline(3)功能?如果是这样,我会说去吧。

我看到的最大优势是它自己分配缓冲区(如果你愿意的话),如果realloc()缓冲区太小,你会传入缓冲区。(所以这意味着你需要传入从 获得的东西malloc())。

这摆脱了 fgets/fgetc 的一些痛苦,您可以希望编写实现它的 C 库的人会注意提高它的效率。

奖励:Linux 上的手册页有一个很好的示例,说明如何以有效的方式使用它。

于 2011-03-03T21:05:37.183 回答
2

如果性能对您很重要,您通常希望调用getc而不是fgetc. 该标准试图使其更容易实现getc为宏以避免函数调用开销。

除此之外,要处理的主要问题可能是您分配缓冲区的策略。大多数人使用固定增量(例如,当/如果我们用完空间时,再分配 128 个字节)。我建议改为使用 constant factor,因此如果空间不足,请分配一个缓冲区,例如,之前大小的 1 1/2 倍。

尤其是当作为宏实现时,和getc之间的差异通常很小,所以你最好把注意力集中在其他问题上。getcfgets

于 2011-03-03T21:11:28.837 回答
0

如果您可以设置最大行长度,即使是较大的行长度,也fgets可以做到这一点。如果不是,多次fgets调用仍然会比多次fgetc调用更快,因为后者的开销会更大。

不过,一个更好的答案是,除非您必须这样做,否则不必担心性能差异。如果fgetc足够快,那有什么关系?

于 2011-03-03T21:02:56.557 回答
0

如果您还没有读到行尾,我会分配一个大缓冲区,然后使用 fgets、检查、重新分配和重复。

每次阅读(通过 fgetc 或 fgets)时,您都在进行需要时间的系统调用,您希望尽量减少发生的次数,因此调用 fgets 的次数更少并且在内存中迭代更快。

如果您正在从文件中读取,则在文件中mmap()ing 是另一种选择。

于 2011-03-03T21:10:39.883 回答