【问题标题】:Reading and storing lines from file into array without limit无限制地从文件中读取行并将其存储到数组中
【发布时间】:2017-04-21 14:35:51
【问题描述】:

我需要从文件中读取行,但我不知道一行有多长。到目前为止,我唯一能想到的就是使用 fgetc 和 realloc

FILE* cFile = fopen(filename, "r");
....
//some while cycle for going from line to line
....
//now for reading the line itself
char* line = malloc(sizeof(char)); //one empty spot for the '\n'
unsigned int = 0;
char c = getc(cFile);
while (c != '\n') {
    line[i] = c;
    line = realloc(line, (i+2)*(sizeof(char));
    i++;
    c = getc(cfile);
}
line[i] = c;

我对 EOL 的所有检查进行了全面检查,或者我是否真的获得了分配的内存,这只是一个示例。

我的问题是,有没有更有效的方法来获得一条未知长度的线?

【问题讨论】:

  • 这个line[0] = c; 应该是line[i] = c;。
  • 最后的line[i] = c;应该是line[i] = '\0';
  • “获取未知长度的行”允许黑客压倒计算机的内存资源。防御性编程将确保输入行不超过某个 sane 大小。所以使用一个大缓冲区,如果这还不够,声明一个错误。
  • 许多系统使用tentative allocation,因此分配buf = malloc(1024*1204); 并不是内存效率低下。实际内存在使用时分配,不一定在调用*alloc()时分配。
  • @ZergOvermind: '\0' 不是换行符。

标签: c


【解决方案1】:

一次增加多个字符的缓冲区大小可能会更有效,例如从大小 80 开始,当缓冲区已满时将大小加倍,如果有必要在最后缩小它。

但这会使您的代码更复杂,因此更容易出错,因此请记住如何手动优化代码的两条规则:

  1. 不要这样做。
  2. 仅供专家使用:暂时不要这样做。

也就是说,不要这样做,因为它可能不值得付出努力。您可能会花费额外的一个小时来“改进”您的代码,除非您知道实际上需要加速,否则您可能不会注意到其中的差异。再加上更复杂的代码出错的风险,并且可能花费数百小时来寻找难以捉摸的错误,最终结果证明是这个小读取功能导致的内存损坏。

而且,如果您真的知道自己在做什么,并且需要额外的速度,请不要开始优化这段代码,直到您知道(即,测量)它实际上是执行时间就到这里了。

【讨论】:

  • 我想过这样做,但我不想冒险,因为我预计会犯某种形式的错误。那么一对一的解决方案看起来是否足够有效?
  • @ZergOvermind:是否足够高效完全取决于您的应用程序和您的时间限制。 realloc-one-char-at-a-time 解决方案在标准现代台式计算机上每秒读取数十万行。你还需要更多吗?
【解决方案2】:

如果您使用的是 POSIX 系统,请使用 getline(3),这正是您想要的。否则,你可以在很多地方找到getline的免费实现,例如here或here

【讨论】:

    猜你喜欢
    • 2020-02-09
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 2017-06-25
    • 2015-01-22
    • 1970-01-01
    相关资源
    最近更新 更多