プロが教える店舗&オフィスのセキュリティ対策術

16進数で表示すると以下のようなバイナリファイルがあります。

42 b9 e0 a4 3b df ea c0 3a 70 eb dc 37 7c f4 8c

これを4バイトずつfloatに入れて出したいのですが、

本当はこのように出したいのですが、
[0][92.93875]
[1][0.0068334043]
[2][9.190419E-4]
[3][1.50773085E-5]

このような値がでてしまいます
[0][-9.745835E-17]
[1][-7.339750E+00]
[2][-5.301601E+17]
[3][-3.766891E-31]

ソースはこれです。
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
FILE *fp;
long size, n;
float *buf;
int i = 0;

if (argc != 2) return 1;

/* FILE OPEN */
fp = fopen(argv[1], "rb");
if (fp == NULL) return 1;

/* FILE SIZE */
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
printf("FILE SIZE %ld\n", size);

/* FILE READ */
buf = malloc(size);
if (buf == NULL) return 1;
n = fread(buf, 1, size, fp);

/* FILE PRINT */
for(i=0;i<10;i++)
{
printf("[%d][%E]\n", i, buf[i]);
}

return 0;
}

本日一日調べましたが良くわかりませんでした。
開発環境は以下の内容です。

$ uname -a
Linux fedoracore6 2.6.20-1.2962.fc6 #1 SMP Tue Jun 19 19:27:14 EDT 2007 i686 athlon i386 GNU/Linux

$ gcc --version
gcc (GCC) 4.1.2 20070626 (Red Hat 4.1.2-13)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

何かお知恵を拝借出来ないものでしょうか??
よろしくお願い致しますm(_ _)m

A 回答 (4件)

実験的に、こんなコードを書いてみました。


当方の環境はリトルエンディアンのため、
ビッグエンディアンで格納してあるデータの
バイトオーダーを変換しています。

【実行結果】
a4 e0 b9 42 9.293875e+01
c0 ea df 3b 6.833404e-03
dc eb 70 3a 9.190419e-04
8c f4 7c 37 1.507731e-05


#include <stdio.h>
#include <string.h>

int main(void)
{
  unsigned char s[] = { // ファイルから読んだ内容
    0x42, 0xb9, 0xe0, 0xa4, 0x3b, 0xdf, 0xea, 0xc0,
    0x3a, 0x70, 0xeb, 0xdc, 0x37, 0x7c, 0xf4, 0x8c,
  };
  unsigned char t[4];
  float f;
  int i, j;
  
  for (i = 0; i < 4; i++) {
    for (j = 0; j < 4; j++) {
      t[j] = s[4*i-j+3]; // バイトオーダーの変換
      printf("%x ", t[j]);
    }
    memcpy(&f, t, 4);
    printf(" %e\n", f);
  }
  return 0;
}

(注)インデントのため、全角空白を使っています。
    • good
    • 0
この回答へのお礼

なるほど!!と言った感じです。
リトルエンディアン、ビックエイディアンを理解しました♪
解決です有難う御座いました!!

お礼日時:2008/02/26 14:04

(No2 さんの回答で◎解決のことと思いますが・・、バイトの「入れ替え」の方法として、こんなのもあったなぁと・・)



★「共用体」を使ってみました。

なお、お望みの「出力表現」にはなりません。

☆確か「フォーマット指定子」%E の仕様に、
 「値が 0.0 以外の場合、小数点の前は、0 でない1桁の数・・」
 とあったような・・。

[92.93875] → [9.293875E+01]

#define un_char unsigned char
union uCHG{
 float fVal;
 un_char cVal[4];
};
(略)
 un_char cBuf[64];
 union uCHG uWork;
(略)
 for( i = 0; i < 4; i++ ){
  nn = i * 4;
  uWork.cVal[0] = cBuf[nn+3]; //「入れ替え」
  uWork.cVal[1] = cBuf[nn+2];
  uWork.cVal[2] = cBuf[nn+1];
  uWork.cVal[3] = cBuf[nn];

  printf( " %E\n", uWork.fVal );
 }
注:インデントに全角空白を使用しています。
    • good
    • 0
この回答へのお礼

共用体は、ずーと昔「C言語入門シニア編」で見ましたが、
一生使うことがないと思ってました。
これは、便利ですね。有難う御座いました!!

お礼日時:2008/02/26 14:06

ファイルにはビッグエンディアンでデータが格納されているのに、リトルエンディアンとして強引に解釈しようとしているからです。

    • good
    • 0
この回答へのお礼

ビッグエンディアン??リトルエンディアン??
大変興味深いです。調査してみます♪
有難う御座いました。

お礼日時:2008/02/26 12:13

using System;



/*
* 俺はC,C++が殆どかけない人間だが、
* おそらくヒントになるんじゃないかと思うんで
* C#ででも書いておくことにするよ
*/

namespace Q3809521A
{
class Q3809521A
{
public static void Main(string[] args)
{
byte[] b1 = {0x42,0xb9,0xe0,0xa4};
byte[] b2 = {0xa4,0xe0,0xb9,0x42};
byte[] b3 = {0x3b,0xdf,0xea,0xc0};
byte[] b4 = {0xc0,0xea,0xdf,0x3b};
System.Console.WriteLine(BitConverter.ToSingle(b1,0)); /* -9.745835E-17 */
System.Console.WriteLine(BitConverter.ToSingle(b2,0)); /* 92.93875 */
System.Console.WriteLine(BitConverter.ToSingle(b3,0)); /* -7.33975 */
System.Console.WriteLine(BitConverter.ToSingle(b4,0)); /* 0.006833404 */
System.Console.ReadKey(true);


}
}
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
C#やったことないんですよねぇ
気持ちは大変うれしいです♪

お礼日時:2008/02/26 12:11

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