私の父(パソコン初心者)はどこで聞いたのか、「パソコンっていうのは、0と1だけで構成されているんだよな。どうやったら見えるんだ」と言いました。

要するに、ファイルを指定して、0と1でそれが表示できればいいんだと思います。
私のPC(Windows98SE)にはVC++6.0が入ってまして、簡単だったら作ってみようと思いました。
私は、言語はC言語しか知らないので、C言語で考えてみようと思いました。

実は私のてもとには『C言語プログラミングの落とし穴』(柴田望洋著)という本がありまして、「ファイルのダンプ」というほとんどそれに近いようなプログラム(1ページくらい)があり、16進数で表現するようです。

そのプログラムの骨組みを書きます。


main関数とdump関数というもので構成されています。
main関数はファイルをオープンしてファイルポインタ(FILE*)をdumpファイルに渡し、最後にクローズするだけです。
dump関数は、ファイルポインタを受け取ります。dump関数の一番大切と思われるところを抜き出します。

void dump(FILE *src, FILE *dst)
{
.....
while ( (n = fread(buf, 1, 16, src) ) > 0 ){
.....
for( i=0; i<n; i++)
fprintf(dst, "%02X ", (unsigned)buf[i]);
.....
}
.....
}

あとは単に、2進数で表現すればいいのだろうと思います。
そうだとしたら、2進数で表現するにはどうすればよいですか。

16進数を2進数に変換する部分を作ればよいのでしょうか。

尚、父のPCはWindowsXPです。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

以下のように変更したら2進数表示できると思います。


なお、ソースを見やすくするため、スペースは全角にしてあります。コピー&ペーストする場合は半角に変換してください。

for( i=0; i<n; i++)
fprintf(dst, "%02X ", (unsigned)buf[i]);
   ↓
for ( i = 0; i < n; i++ ){
 unsigned int filter = 0x80;
 int j;
 for ( j = 0; j < 8; j++ ){
  fprintf( dst, "%c", ( ( (unsigned)buf[i] & filter ) ? '1' : '0' ) );
  filter >>= 1;
 }
}

なぜこれでいいかと説明しようとも思ったのですが、どうやらCの学習中のようですので、ヒントだけ書きます。

ヒント:3項演算子、ビット演算子

この回答への補足

たいへんご回答ありがとうございました。

自分で解説します。

自分で解説するのもへんですが、、、、

私の質問で挙げた元のプログラムでは、
n = fread(buf, 1, 16, src)
でファイルから読み込むんですが、
1というのは要素1個の大きさ(この場合、1バイト)で、16というのは要素の個数で、
1バイトを16個取ってきて、bufに格納するということです。
bufは16バイトの大きさを持つ配列です。(unsigned char buf[16]; と宣言されている。)
fread1回の読み込みで16バイト読み込みます。

nは読み込み要素数なので、たいてい16になります。(16じゃない場合もあります。)
fprintf(dst, "%02X ", (unsigned)buf[i]); と Xを使って書いてあるので、1バイトが16進数で表現されます。02X というように2桁で 16×16 = 256 となる。

あとは、ご回答どおり、この部分(fprintfの部分)を変えます。

ご回答の部分について解説します。
filter(0x80)とは2進法で 1000 0000 です。(8ビット)
1バイトとは8ビットです。
> for ( j = 0; j < 8; j++ ){
>  fprintf( dst, "%c", ( ( (unsigned)buf[i] & filter ) ? '1' : '0' ) );
>  filter >>= 1;
> }
この部分は、1バイトぶんの処理をしています。
jを0から8未満まで(0から7まで)行うのは、8ビットぶんの処理を行うからです。
& はビット演算子で、論理積をとります。
その結果が真(0以外)ならば、'1'を表示します。0ならば'0'を表示します。
filter >>= 1 で、右にずらしていきます。
buf[i]のなかのビットを左から表現していきます。


まだ実際にやっていません。あとは、やってみるだけです。

補足日時:2002/03/03 15:58
    • good
    • 0
この回答へのお礼

やってみたらできました。多分大丈夫だと思います。
ありがとうございました。

お礼日時:2002/03/04 22:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Q配列の初期化子 { .......} について

配列の初期化子について、以下のような事がありました。

1. 一般に教科書で言われている事ですが、int a[3]={1} ; で初期化すると a[0]=1,a[1]=0,a[2]=0と初期化子が与えられていない要素は0で初期子されます。
2. 今度は,意地悪く全ての要素に初期化子を与えない a[3]={ } ; で初期化すると a[0]=0.a[1]=0, a[2]=0. と全てが0で初期化されました。←問題点
3. 初期化子を与えない int a[3] ; では a[0] a[1] a[2] は当然ながら不定値で初期化されます。

1と3については教科書通りですが、2についてはどの様に説明する事ができるのでしょうか。
標準Cに規定があるのでしょうか。それとも環境(コンパイラ)によるものでしょうか。尚私はRed Hat Linuxを使っています。
宜しく願います。

Aベストアンサー

初期化子は、

initializer:
    assignment-expression
    { initializer-list }
    { initializer-list , }

initializer-list:
    designation(opt) initializer
    initializer-list , designation(opt) initializer

ですので、少なくともひとつは式が必要です。
式が何も無い場合は未定義の動作になります。

Qint main()、void main()、void main(void)、int main(void)

今日、大学でC言語の講義の時間、先生が、

#include <stdio.h>

void main(void){

}

と宣言してプログラムを書くと教えていました。
main関数には、
main()
void main()
void main( void )
int main()
int main( void )

と、人によりいくつかの描き方があったりします。
どれが本当は正しいのでしょうか?
void mainはすべきではないとなんかの本で読んだのですが・・。

Aベストアンサー

通称C89という以前の言語規格(現行コンパイラの多くが準拠)では、下記のいずれかが正しい。
int main(int argc, char *argv[])
int main(void)

但し、最新のC言語規格(通称C99)では、
<ISO/IEC9899:1999>
or in some other implementation-defined manner.
</ISO/IEC9899:1999>
となっているので、処理系が戻り値のvoidを認めていればvoidも可。
# 組込み系などで戻り値を使わない環境もあるためでしょうか。

なので、コンパイラのマニュアルで戻り値のvoidにしていい/しろと書いてない限り、
voidは言語仕様的には正しくない。(でも動くものもある)

Qdc.TextOut(0 ,0 , *str) ;について

環境 WIN98 VC++6.0 MFC にて

パターンBはOKですが、パターンAだと不正な処理で落ちてしまいます。

どうしてなのかお教えください。

void CFffView::OnPaint()
{
CPaintDC dc(this);
//パターンA
CString* str ;
str = (CString*)("999");
dc.TextOut(0 ,0 , *str) ;

//パターンB
CString aaa ;
aaa = (CString)("999");
dc.TextOut(0 ,0 , aaa) ;
}

Aベストアンサー

両方ダメ。
Aのパターンで動くのは、たまたま。

CString aaa ;
aaa = "999";
dc.TextOut(0 ,0 , aaa) ;

これで十分。

あえてキャストするんだったら、
CString aaa ;
aaa = (LPCSTR)"999";
dc.TextOut(0 ,0 , aaa) ;


aaa=のところでは、ただの代入が行われているわけではありません。
オーバーロードされたオペレータが呼ばれています。


>str = (CString*)m_array.GetAt(i) ;

これは、m_arrayの要素にCString*を入れていて、初めて成り立つ式です。
値をいれているところと、m_arrayの宣言を確認してください。

str = (CString*)("999");
も、
aaa = (CString)("999");
も、リテラル文字列をつっこもうとしています。
リテラル文字列とCStringはまったく別物です。

Qクリティカルエラー Expression: ("Buffer too small", 0)

VC++2005でコンパイルしたアプリですが、実行すると
クリティカルエラーの次のメッセージが表示されました。
VCの設定で解決できるものなのでしょうか?


Microsoft Visual C++ Debug Library

...

Expression: ("Buffer too small", 0)

Foi infomation how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(press Retry debug the application)

Aベストアンサー

このメッセージはセキュア関数でバッファを飛ばした時に出ます。
プログラムに問題がありますので、VCの設定ではなく問題部分を
突き止めて修正しなければダメです。

QBuffer overrun, data ..

メールソフトで、openssl を使って、
ヤフーメールにPOP接続して、800個ほど溜まっているメールを取り出そうとしています。

メッセージID を確認しながら重複しないように取り出そうとしています。
700個ほど取り出したのですが、
その後、頻繁に

Buffer overrun, data truncated

のメッセージが出て、ストップします。

このメッセージはopenssl が作成しているのでしょうか?
また、原因、対策はなんでしょうか?

Aベストアンサー

http://oshiete.goo.ne.jp/qa/8198656.html
↑を見る限り自分でメッセージを出しているのでは?
その通りであれば、原因や対策も見えてくるはずです。


人気Q&Aランキング

おすすめ情報