C fgets与fgetc的阅读线

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

  • 使用fgets并每次检查最后一个字符是否为换行符并连续追加到缓冲区
  • 使用fgetc读取每个字符,偶尔重新分配缓冲区

Intuition告诉我fgetc变体可能会变慢,但是再一次我没有看到fgets如何在不检查每个角色的情况下做到这一点(我的直觉并不总是那么好)。 线条非常大,因此性能很重要。

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

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

虽然fgetc()也有效,但它有点琐碎 – 但只是略有不同。 在封面下,它使用与fgets()相同的机制。 内部可能能够利用更快的操作 – 类似于strchr() – 当您直接调用fgetc()时不可用。

您的环境是否提供getline(3)function? 如果是这样,我会说那样做。

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

这摆脱了fgets / fgetc的一些痛苦,你可以希望编写实现它的C库的人负责使其高效。

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

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

过去,处理的主要问题可能是你分配缓冲区的策略。 大多数人使用固定增量(例如,当/如果我们用完空间,则分配另外128个字节)。 我建议改为使用常数因子 ,所以如果你的空间不足,请分配一个缓冲区,比如前一个大小的1 1/2倍。

特别是当getc作为宏实现时, getcfgets之间的差异通常很小,所以你最好专注于其他问题。

如果你可以设置一个最大行长度,即使是一个fgets长度,那么一个fgets也可以。 如果没有,多个fgets调用仍然比多个fgetc调用快,因为后者的开销会更大。

但是,更好的答案是,除非必须,否则不值得担心性能差异。 如果fgetc足够快,那有什么关系呢?

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

每次读取(通过fgetc或fgets),您正在进行系统调用,这需要花费时间,您希望最小化发生的次数,因此调用fgets的次数更少,并且在内存中迭代更快。

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