24

命令パイプライン シミュレータを構築しようとしていますが、開始するのに多くの問題があります。私がする必要があるのは、標準入力からバイナリを読み取り、データを操作している間、何らかの方法でメモリに格納することです。正確に 32 ビットのチャンクを次々と読み取る必要があります。

一度に正確に 32 ビットのチャンクを読み取るにはどうすればよいですか? 第二に、後で操作するためにどのように保存しますか?

これが私がこれまでに得たものですが、さらに読んだバイナリチャンクを調べると、正しく見えません.必要な32ビットを正確に読んでいるとは思いません.

char buffer[4] = { 0 }; // initialize to 0
unsigned long c = 0;
int bytesize = 4; // read in 32 bits
while (fgets(buffer, bytesize, stdin)) {
  memcpy(&c, buffer, bytesize); // copy the data to a more usable structure for bit manipulation later
  // more stuff
  buffer[0] = 0; buffer[1] = 0; buffer[2] = 0; buffer[3] = 0; // set to zero before next loop
}
fclose(stdin);

一度に 32 ビット (すべて 1/0、改行なしなど) を読み取るにはどうすればよいchar[]ですか?

編集:バイナリを読み取ることはできますが、正しい順序でビットを生成する答えはありません-それらはすべて混乱しており、エンディアンと、一度に8ビット(1文字)を読み取って移動する際の問題が疑われます-これWindows と C で動作する必要があります ... ?

4

8 に答える 8

29

必要なのはfreopen(). マンページから:

filename が null ポインターの場合、freopen() 関数は、ストリームに現在関連付けられているファイルの名前が使用されたかのように、ストリームのモードを mode で指定されたモードに変更しようとします。この場合、freopen() の呼び出しが成功した場合、ストリームに関連付けられたファイル記述子を閉じる必要はありません。モードのどの変更が許可されるか (ある場合)、およびどのような状況で許可されるかは実装定義です。

基本的に、あなたが本当にできる最善のことはこれです:

freopen(NULL, "rb", stdin);

これは再びstdin同じ入力ストリームになりますが、バイナリ モードになります。通常モードでは、Windows から読み取るstdin\r\n(Windows 改行) 1 文字の ASCII 10 に変換されます。"rb"このモードを使用すると、この変換が無効になり、バイナリ データを正しく読み取ることができます。

freopen()ファイルハンドルを返しますが、それは以前の値 (バイナリモードにする前) であるため、何にも使用しないでください。その後、fread()前述のように使用します。

ただし、懸念事項については、「32ビット」で読み取っていない可能性がありますが、使用fread()する4char秒で読み取られます(これはCで実行できる最善の方法です-少なくとも8ビットでcharあることが保証されていますが、歴史的な組み込みプラットフォームには 16 ビットの s があります (18 ビット以下のものもあります)。使用すると、4バイトで読み込まれることはありません。少なくとも 3 つ (改行かどうかによって異なります) を読み込みます。4 番目のバイトは、C 文字列がヌル文字で終了し、読み込んだものをヌル文字で終了するためです (良い関数のように)。明らかに、これはあなたが望むものではないので、 を使用する必要があります。charfgets()'\0'fgets()fread()

于 2009-10-21T06:44:40.867 に答える
19

SET_BINARY_MODEマクロと の使用を検討してくださいsetmode:

#ifdef _WIN32
# include <io.h>
# include <fcntl.h>
# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY)
#else
# define SET_BINARY_MODE(handle) ((void)0)
#endif

SET_BINARY_MODEマクロの詳細については、 「標準 I/O によるバイナリ ファイルの処理」を参照してください。

詳細はsetmodeこちら: "_setmode "

于 2009-10-23T14:02:16.423 に答える
1

Windows の場合、次のMicrosoft _setmode の例は、stdin をバイナリ モードに変更する方法を具体的に示しています。

// crt_setmode.c
// This program uses _setmode to change
// stdin from text mode to binary mode.

#include <stdio.h>
#include <fcntl.h>
#include <io.h>

int main( void )
{
   int result;

   // Set "stdin" to have binary mode:
   result = _setmode( _fileno( stdin ), _O_BINARY );
   if( result == -1 )
      perror( "Cannot set mode" );
   else
      printf( "'stdin' successfully changed to binary mode\n" );
}
于 2020-09-21T19:18:42.930 に答える
0

ここで fgets() はすべて間違っています。これは、バイナリ データではなく、行末文字で終了する人間が判読できる ASCII テキストを対象としており、必要なものは得られません。

私は最近、 read()呼び出しを使用して、まさにあなたが望むことをしました。プログラムが stdin を明示的に閉じていない限り、最初の引数 (ファイル記述子) には、stdin に定数値 0 を使用できます。または、POSIX システム (Linux、Mac OS X、またはその他の最新の Unix バリアント) を使用している場合は、STDIN_FILENO を使用できます。

于 2009-10-21T06:20:37.513 に答える
-1

fread()は、バイナリ データの読み取りに最適です。

はい、バイトごとに処理する予定がある場合は、char 配列で問題ありません。

于 2009-10-21T06:12:08.840 に答える
-1

実行しているOSはわかりませんが、通常、「標準入力をバイナリで開く」ことはできません。次のようなことを試すことができます

int fd = fdreopen (fileno (stdin), outfname, O_RDONLY | OPEN_O_BINARY);

強制しようとします。次に使用します

uint32_t opcode;
read(fd, &opcode, sizeof (opcode));

しかし、私は実際に自分で試したことはありません。:)

于 2009-10-21T06:19:09.190 に答える
-2

私はntohlが必要だったことを除いて、最初は正しかった... Cエンディアン変換:ビットごと

于 2009-10-23T19:01:19.627 に答える