5

std::istreamにはプロトタイプistream& read (char* s, streamsize n)があり、実際に読み取られるバイト数は を呼び出して取得する必要がistream::gcount()あり、 の有効性もistreamから知ることができますios::good

私が書こうとしていた別のストリームクラスの実装について同僚と話し合っていたとき、私はこの設計に従うかもしれないと言っていました。しかし、ユーザーに毎回gcountを呼び出させる代わりに、このようにプロトタイプを読み取って、1 回の呼び出しで解決できるようにすることもできistream& read (char* s, streamsize n, size_t &bytes_read)、前者は扱いにくいと彼は言いました。std私はのデザイン選択を弁護できませんでした。背後にある本当の理由は何istream::readですか?

4

4 に答える 4

4

これは、C++ が通常、誰もが必要としない可能性のあるインターフェイスを強制しないためだと思います。read一部の人々が気にしないパラメーターを受け入れる必要がある場合は、追加のコーディング作業が発生します (追加の int をパラメーターとして渡すことを宣言します)。また、クライアントが気にするかどうかに関係なく、読み取ったバイトを常に保存します (一部のクライアントは、eof/fail ビットで示されるように、読み取りが失敗したことだけを気にする場合があります)。

別の方法を使用して、必要な場合とそうでない場合があるさまざまな情報に対してインターフェイスを分離します。

于 2010-10-07T15:41:34.003 に答える
3

代わりに readsome コマンドを試してください。

streamsize readsome ( char* buf, streamsize num );

buf はバッファで、num は読みたいバイト数です。もちろん、最大でもバッファ内で利用可能なバイト数です。

戻り値は、実際に読み取られたバイト数です。

ファイルを最後まで読み取るには、ループできます。

char buf[BUF_SIZE]
streamsize bytesRead;
do
{
   bytesRead = instr.readsome( buf, BUF_SIZE );
   // do stuff with the bytes you read, if any
} while ( bytesRead == BUF_SIZE );
于 2010-10-11T12:29:37.680 に答える
0

元の質問への回答として、Cが若い頃はエラーチェック呼び出しを行うことが一般的なプログラミングスタイルでしたが、すぐに流行しなくなりました。何が起こるかというと、それほど間違っていない小さなことですが、それでも、コミュニティによって呼び出されて悪いとラベル付けされるまで、しばらくの間、ほとんどの場合、ほんの少し劣っています。このコードには、その小さなアンチパターンが広く議論される前に書かれたという不幸があります。

Cash Cowの解決策に応えて、バグがあると思います。IOを待機していて、バッファを部分的に埋めるのに十分な文字がある場合、関数は戻り、ファイルが完全に読み取られる前にwhileループが終了します。したがって、彼のソリューションは、ストレートraw IOの上に記述された場合はおそらく正しく実行されますが、バッファリングされたIO上での実行は失敗します。

もちろん、正しい解決策は、EOFフラグが設定されたときにwhileループを終了することです。現時点では、badbitが設定されている場合の最良の応答はわかりませんが、おそらくその場合も処理する必要があります。

ただし、readsomeがreadの適切な代替手段であることに同意します。

編集:readsomeが利用できない場合があります(一部のVC ++バージョン)。この場合、読み取りは使用できなくなりません。

于 2011-05-20T01:48:07.467 に答える
0

std::istreamにはプロトタイプ istream& read (char* s, streamsize n) があり、実際に読み取られるバイト数は を呼び出して取得する必要が istream::gcount()あり、 の有効性もistreamから知ることができます ios::good

istream::read(char* s, streamsize n)sizeのフォーマットされていないデータ ブロック (NULL終端なし) をn配列 at に読み込みますssは へのポインタですcharが、 を使用istream::readしてバイナリ データを読み取ることができます。たとえば、istreamdouble の配列の値を保持する を使用できます (エンディアンが正しいと仮定します)。

unsigned int count;
input.read(reinterpret_cast<char*>(&count), sizeof(count));
double* data = new double[count];

for (unsigned int i = 0; i < count; ++i)
    input.read(reinterpret_cast<char*>(data[i]), sizeof(double));

istream::gcount()istream::read最後の呼び出しで読み取られたバイト数を返します。この場合、 のサイズcountはおそらく a のサイズと異なることがわかります。したがって、 を使用して配列の最初の要素のサイズを指定するdoubleことはできません。istream::gcount()data

于 2010-10-10T14:40:08.823 に答える