0

ベクトルのエントリが格納されている 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 行のファイルで試してみたところ、問題なく動作しているようです。お気軽にコメントください。

4

1 に答える 1

1

fgetsは、ファイルからデータを読み取るための友人です (データの各ビットが改行にあるという私の仮定が正しい場合)。各行を 1 つずつ読み取り、読み取ったテキストに対してstrtofを使用します。テキストの読み取りとフロートへの変換は本質的に遅いプロセスなので、上記で十分であると思います。

2 番目の質問については、いくつかの方法があります。float** を渡して、関数内で malloc を作成できます。これには、関数の外で解放する必要があるという欠点がありますが、これは明確ではありません。私が考えることができる他の唯一の方法は、ファイルをスキャンして改行の数を数え、そのために配列の長さを事前に割り当てることです。

malloc と一連の reallocs を実行する方が、スキャンして行数をカウントするよりも効率的かどうかを判断するのは難しいですが、おそらく両方の方法を試して (どちらも特に難しいわけではありません)、どちらが速いかを確認する価値があります。 .

于 2013-01-22T20:31:33.943 に答える