我需要读取一行文本(以换行符结尾),而不对长度做出假设。所以我现在面对各种可能性:
fgets
并每次检查最后一个字符是否为换行符并连续附加到缓冲区fgetc
和偶尔realloc
缓冲区 Intuition告诉我fgetc
变体可能会变慢,但是我再也看不到fgets
如何在不检查每个角色的情况下做到这一点(我的直觉也并非总是那么好)。线条非常大,因此性能很重要。
我想知道每种方法的优缺点。提前谢谢。
答案 0 :(得分:2)
您的环境是否提供getline(3)
功能?如果是这样,我会说那样做。
我看到的最大优点是它本身分配了缓冲区(如果你想要的话),如果它太小,你将传入的缓冲区realloc()
。 (所以这意味着你需要传递从malloc()
获得的东西。
这消除了fgets / fgetc的一些痛苦,你可以希望那些编写实现它的C库的人都会把它变得高效。
Bonus:Linux上的手册页有一个很好的例子,说明如何以有效的方式使用它。
答案 1 :(得分:2)
我建议使用fgets()
加上动态内存分配 - 或者您可以调查POSIX 2008标准中getline()
的接口,并且可以在更新的Linux机器上使用。这为你做了内存分配。您需要密切关注缓冲区长度及其地址 - 因此您甚至可以创建一个处理信息的结构。
尽管fgetc()
也有效,但它有点吝啬 - 但只是略有不同。在封面下方,它使用与fgets()
相同的机制。内部可能能够利用更快的操作 - 类似于strchr()
- 当您直接致电fgetc()
时无法使用。
答案 2 :(得分:2)
如果效果对您很重要,通常需要拨打getc
而不是fgetc
。该标准试图使getc
更容易实现为宏,以避免函数调用开销。
过去,处理的主要问题可能是你分配缓冲区的策略。大多数人使用固定增量(例如,当我们用完空间时,分配另外128个字节)。我建议改为使用常量因子,所以如果空间不足,请分配一个缓冲区,比如前一个大小的1 1/2倍。
特别是当getc
作为宏实现时,getc
和fgets
之间的差异通常非常小,因此您最好专注于其他问题。
答案 3 :(得分:0)
如果你可以设置一个最大行长度,即使是一个大行长度,那么一个fgets
就可以了。如果没有,多个fgets
调用仍然会比多个fgetc
调用更快,因为后者的开销会更大。
但更好的答案是,除非必须,否则不值得担心性能差异。如果fgetc
足够快,那有什么关系?
答案 4 :(得分:0)
我会分配一个大缓冲区,然后使用fgets,检查,重新分配和重复,如果你还没有读到行的末尾。
每次你读(通过fgetc或fgets)你正在进行系统调用,这需要花费时间,你想要最小化发生的次数,所以调用fgets更少次并在内存中迭代更快。
如果您正在阅读文件,则mmap()
在文件中是另一种选择。