我试图用 fscanf() 提供一个数组,同时循环一个包含整数列表的文件,n 个整数长。看来我需要使用 malloc 和/或可能的 realloc。我听说 malloc 命令需要大量的执行时间,最好过度分配。有人介意帮助我了解实现这一目标的基石吗?
免责声明:我是 C 的新手。
不,您所听到的具有误导性(至少对我而言)。malloc
只是一个功能,通常是一个快速的功能。
malloc
认为你可以malloc
在这场比赛中轻松击败是不现实的。如果这不能回答您的问题(这很笼统),我很抱歉,但您必须意识到没有可以轻松实现的 ( spoon ) 优化。
读取文件会比分配内存慢得多!
您可能想要阅读整个文件并找出您想要的整体数量,然后一次性使用 malloc()。
malloc(sizeof(int)*n)
过早的优化是万恶之源(google it)。
也就是说,为手头的任务分配您认为合理/典型的任何数量,并在您必须重新分配时将其加倍。这种策略很难被击败。
请注意,malloc()
每个分配都会增加一些开销以维护其内部数据结构(在常见实现中至少为 4 个字节),因此如果整数是 4 个字节长,malloc()
则为每个整数执行 a 将具有 >= 50% 的开销(可能是 75%) . 这相当于Integer
在 Java 中使用 's 数组,而不是int
's 数组。
正如@Charles Dowd 所说,最好一次性分配所有内存,以避免开销。
对于您的具体情况, malloc 不会给您带来问题。fscanf 的运行时间将比 malloc 和 free 的开销慢很多很多倍。但是,它可以添加到应用程序的高性能区域。在这些领域,还有其他方法,例如内存池和固定大小的分配器,可以对抗 malloc() 的开销。但是,当您刚开始时,您几乎不需要担心性能开销。
您不想调用malloc
或realloc
读取每个整数,这是肯定的。你能估计一下你需要多少空间吗?你控制文件格式吗?如果是这样,您可以让文件的第一行是一个整数,表示要从文件中读取多少个整数。然后,您可以一次性分配所需的所有空间。如果您不控制格式并且无法执行此操作,请遵循此线程中提到的其他建议:分配一个合理大小的缓冲区,并在每次空间不足时将其加倍。
它是一个文本文件(不是二进制文件)而不是固定格式,对吧?否则很容易根据文件大小计算数组的大小(buffer_size = file_size / record_size
, buffersize 以字为单位(int 的大小),其他大小以字节为单位)。
这就是我会做的(但在应用统计方面我有点发疯)。
1)一个数字(又名记录)将在文件中占用的最大字符数(又名字节)是多少,不要忘记包括行尾字符(CR,NF)和其他空白字形(空格,标签等)?如果您已经可以估计记录的平均大小,那么使用它而不是最大大小会更好。
initial_buffer_size = file_size / max_record_size + 1 (/ is integer division)
2)分配该缓冲区,将整数读入该缓冲区,直到它已满。如果读取了整个文件,那么您就完成了,否则调整大小或重新分配缓冲区以满足您新的估计需求。
resize_size =
prev_buffer_size
+ bytes_not_read / ( bytes_already_read / number_of_records_already_read )
+ 1
3)读入该缓冲区(从先前读取结束的位置)直到它已满,或者已读取所有文件。
4) 如果未完成,请从步骤 2) 开始使用新的prev_buffer_size
.
如果从字节大小的角度来看,数字(记录)完全随机分布,这将最有效。如果没有,并且如果你知道它们有什么样的分布,你可以据此调整算法。