0

ディスク上に5つのバイナリファイルがあるとします。これらの5つのファイルは、すべて異なるタイプであることを除いて、数値のシーケンスを2進形式でエンコードします。それらがSHORTINT、INT、LONG、FLOAT、およびDOUBLEであるとしましょう。ファイルにも異なる数の番号が保存されるようにします。

ここで、実行時にユーザーに尋ねるプログラムがあるとします。

ロードするファイル名を入力します。

ユーザーはこれら5つのファイルのいずれかを選択できます。プログラムでこれらのファイルを配列にロードして、さらに計算を実行できるようにしたいと思います。

ファイルのタイプ(つまり、SHORT INT、INT、LONG、FLOAT、またはDOUBLE)をエンコードする整数値を返す関数(「getfiletype」と呼びます)と、ファイル内の番号(たとえば、1000、9338、8131、0など)(「getfilesize」と呼びます)。実際のエントリ数は、数十億の数になる可能性があります。可能であれば、プログラム内で、ユーザーが選択したファイルの値を保持する配列(「配列」など)に同じ名前を使用したいと思います。そうすれば私は次のようなブロックを持つことができます

N=getfilesize("pickedfile.dat");
for(i=0 ; i<N ; i++ ) {
    doublearray[i]==2.0*(double)array[i]+7.12;
}

配列を変換できます。ここでは、変換された値を保持するために「doublearray」と呼ばれる新しい配列を導入しました。このdouble配列は、DOUBLE形式でファイルに書き込まれるか、他の形式の1つに書き込む前に変換されます。

このようなことをするにはどうすればよいですか?完全に混乱しています。

4

2 に答える 2

2

プログラムは、getfiletype()またはgetfilesize()のいずれかへの最新の呼び出しによって移入される静的(またはグローバル)void*配列を作成できます。次に、それを適切にキャストする必要があります(例で特に2倍にするために行ったように)。ファイルデータアスペクトのロードを解決したことを前提としています。

このアプローチは、使用法に関してはあまりクリーンではありませんが(静的またはグローバルに依存すると、さまざまな会話を実行するためのオプションが制限されます。特に、現在のところ、順番に操作する必要があります)。

よりクリーンなAPIは、おそらくこれらの線に沿ったものになるでしょう。

enum TypeEnum { SHORT_INT, INT, LONG, FLOAT, DOUBLE };
void* getfiledata(char *filename, unsigned int *size, TypeEnum *type);
#define GET_DATA_AND_CAST(filename, array, array_size) \
    do { \
        TypeEnum type; \
        void* arr = getfiledata(filename, array_size, &type); \
        switch(type) { \
            case SHORT_INT: \
                array = (short*)arr; break; \
            case INT: \
                array = (int*)arr; break; \
            case LONG: \
                array = (long*)arr; break; \
            case FLOAT: \
                array = (float*)arr; break; \
            case DOUBLE: \
                array = (double*)arr; break; \
            default: \
                // ASSERT \
        } \
    } while(0)

その後、次のように使用できます。

void process_doubles(void *array) {
    double to_conv[];
    unsigned int size;
    GET_DATA_AND_CAST("pickedfile.dat", to_conv, &size);

    for(i=0; i<size; ++i ) {
        doublearray[i] = 2.0 * to_conv[i] + 7.12;
    }
}

IMHO C ++はこれをさらに良くします(テンプレートを使用できるため)が、この質問はCでのみタグ付けされているため、Cでオプションを提示しているだけです。

于 2012-08-24T08:56:35.237 に答える
1

ポインタを使用して、void *任意のデータ型へのポインタを格納できます。

int num_elements = getfilesize();
size_t element_size;
switch (getfiletype()) {
    case SHORT_INT: element_size = sizeof(short int); break;
    ...
}
void *array = malloc(num_elements * element_size);

...

void process_doubles(void *array) {
    for(i=0 ; i<getfilesize("pickedfile.dat") ; i++ ) {
    doublearray[i] = 2.0 * ((double *) array)[i] +7.12;
}

間接化する前に、配列ポインタをキャストする必要があることに注意してください。

于 2012-08-24T08:45:27.207 に答える