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
作为宏实现时, getc
和fgets
之间的差异通常很小,所以你最好专注于其他问题。
如果你可以设置一个最大行长度,即使是一个fgets
长度,那么一个fgets
也可以。 如果没有,多个fgets
调用仍然比多个fgetc
调用快,因为后者的开销会更大。
但是,更好的答案是,除非必须,否则不值得担心性能差异。 如果fgetc
足够快,那有什么关系呢?
我会分配一个大缓冲区,然后使用fgets,检查,重新分配和重复,如果你还没有读到行的末尾。
每次读取(通过fgetc或fgets),您正在进行系统调用,这需要花费时间,您希望最小化发生的次数,因此调用fgets的次数更少,并且在内存中迭代更快。
如果您正在读取文件,则文件中的mmap()
是另一种选择。