【问题标题】:How to load data from file into float* in C如何将文件中的数据加载到C中的float *
【发布时间】:2013-01-22 20:21:49
【问题描述】:

我有一个 ASCII 文件,其中存储了向量的条目。我不知道文件的长度(行数),也无法估计它的大小,因为它可能从几行到几万行不等。我需要一种有效的方法来读取存储在该文件中的数据并将它们加载到 float* 变量中。代码应该在 C 中。

我的问题是如何为我需要创建的向量分配内存,因为我事先不知道它的大小?可以举个例子吗?

最后,您认为最适合此类功能的原型是什么?应该是这样的:

load_data(const char* filename, float* data, int* vector_size);

?

更新 1.: 在进行一些初始测试时,我编写了以下代码:

void create_random_matrix(float* matrix, const int nrows) {
    matrix = (float *) malloc(sizeof (float) * nrows);
    short i;
    for (i = 0; i < nrows; i++) {
        matrix[i] = 7.0f;
    }
}

它应该返回一个所有元素都等于 7.0f 的数组。相反,当我从 main.c 调用它时:

float *a;
create_random_matrix(a, 10);    
printf("%f",a[0]);

它打印 0.0f。这怎么可能?!

更新 2. 如果不是您的帮助,就不会编写以下(工作)代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#define LINE_SIZE 10
#define ALLOCATION_CHUNK 50

int load_vector_data(const char* filename, float** vector, int* length) {
    *vector = malloc(sizeof (float) * ALLOCATION_CHUNK);
    int allocated_rows = ALLOCATION_CHUNK;
    u_short i = 0;
    FILE* fr = fopen(filename, "r");
    if (fr == NULL) {
        exit(FILE_NOT_FOUND);
    }
    char line[LINE_SIZE];
    while (fgets(line, LINE_SIZE, fr) != NULL) {
        if (i >= allocated_rows){           
            allocated_rows += ALLOCATION_CHUNK;
            *vector = realloc(*vector, sizeof (float) * allocated_rows);
        }
        strip_newline(&line, LINE_SIZE);
        (*vector)[i] = strtod(line, (char **) NULL);
        i++;
    }
    *length = i;
    *vector = realloc(*vector, sizeof (float) * i);
    fclose(fr);
}

void strip_newline(char *str, int size) {
    u_short i;
    for (i = 0; i < size; ++i) {
        if (str[i] == '\n') {
            str[i] = '\0';
            return;
        }
    }
}

我用一个 8000 行的文件试了一下,似乎工作得很好!请随时发表评论。

【问题讨论】:

  • 按固定大小的部分读取文件,将每个部分复制到结果缓冲区,每次调整大小为realloc
  • @Pantelis Sopasakis:(在 Update1 上)您应该在函数的参数中传递 float **matrix,使用 *matrix = (float *) malloc ... 分配内存并相应地填充矩阵。
  • @someguy 非常感谢!的确,你是对的!那么,我的方法的原型毕竟应该是load_data(const char* filename, float** data, int* vector_size);,对吧?
  • @Pantelis Sopasakis:是的。这是解决方案之一。

标签: c file pointers file-io


【解决方案1】:

fgets 是您从文件中读取数据的朋友(如果我假设每一位数据都在换行符上是正确的)。逐一阅读每一行,并在阅读的文本上使用strtof。阅读文本并转换为浮点数本质上是一个缓慢的过程,所以我认为上述内容已经足够好了。

至于你的第二个问题,有几种方法可以做到。您可以传入一个 float** 并在函数内创建 malloc。尽管这有一个缺点,即您需要在函数之外释放它,这并不十分明显。我能想到的唯一另一种方法是扫描文件并计算换行符的数量,然后为此预先分配数组长度。

很难说执行 malloc 和一堆 realloc 是否比扫描来计算行数更有效,可能值得尝试这两种方法(都不是特别难)并看看哪个是更快。

【讨论】:

  • 使用strtod 而不是atof
  • @WilliamPursell atofstrtod 的本质区别是什么?
  • atof,如果值无法表示,则行为未定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-15
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多