1

「n」要素の配列をバイナリ出力ファイルに書き込む関数を作成する必要があります。書き込みたいデータの種類 (int、float、double など) ごとに個別の関数を作成する必要は避けたいと思います。

関数の引数としてデータ型 (おそらくバイト数) を指定し、その処理方法を関数に決定させる方法はありますか?

例えば

f_writebinary(??? *data, int size, long n) {

   for(i=0;i<n;i++) {

        fwrite((data+i),size,1,stdout); 

    }
}

...または、これは C に期待するのはまったくばかげたことですか?

4

2 に答える 2

2

はい、まさにその通りfwrite()です。const void *「任意の型のデータへのポインタ」を意味する a を使用し、バイトへのポインタとして扱います。

したがって、ラッパーは実際には必要ありません。正しいサイズの呼び出しをfwrite()すぐに実行して、配列を書き込むことができます。

const int my_ints[3] = { 1, 2, 3 };
const double my_doubles[5] = { 5, 4, 3, 2, 1 };

fwrite(my_ints, sizeof *my_ints, sizeof my_ints / sizeof *my_ints, stdout);
fwrite(my_doubles, sizeof *my_doubles, sizeof my_doubles / sizeof *my_doubles, stdout);

へのバイナリ データの書き込みstdoutは多少失礼な場合があることに注意してください。また、I/O 呼び出しのエラーをチェックする必要があることにも注意してください。

の API が使用する「y バイトの x 要素」モデルを削除し、fwrite()それらをバイトの単一のチャンクとして扱うだけで、呼び出しを簡素化できます。

fwrite(my_ints, sizeof my_ints, 1, stdout);
fwrite(my_doubles, sizeof my_doubles, 1, stdout);

ループには意味がないことに注意してください。各配列の数値はメモリ内で隣接するためfwrite()、一度にすべて書き込むことができます。一般的には、実行される I/O 呼び出しの数をできるだけ少なくするのが最善です。そのため、バイトごとに書き込むのではn * mなく、1 回のバイト書き込みを行うことができれば、ほとんどの場合、そのほうが優れています。書き込むデバイスの多くはブロック指向であり、データのブロック全体を取得することで多くのメリットが得られることに注意してください。nm

于 2013-06-07T10:13:14.637 に答える
1

???に置き換えるだけcharです。または、関数内で使用voidしてキャストするため、関数を呼び出すときchar*にキャストする必要はありません。andの代わりにchar*使用することをお勧めします。size_tintlong

#include <stdio.h>
...

size_t f_writebinary(void * data, size_t size, size_t n) 
{
  size_t result = 0;

  for (size_t i = 0; i < n; ++i) 
  {    
    size_t result_inner = fwrite(((char *) data) + (i * size), size, 1, stdout); 
    if (!result_inner)
    {
      /* handle error here */
    }
    else
    {
      ++result;
    }
  }

  return result;
}

最適化されたバージョン:

size_t f_writebinary(void * data, size_t size, size_t n) 
{
  size_t result = 0;

  n *= size;
  for (size_t i = 0; i < n; i += size) 
  {    
    size_t result_inner = fwrite(((char *) data) + i, size, 1, stdout); 
    if (!result_inner)
    {
      /* handle error here */
    }
    else
    {
      ++result;
    }
  }

  return result;
}

手短に言えば、署名fwrite()が使用するものを模倣するだけです。

于 2013-06-07T10:32:06.643 に答える