• ベストアンサー

C言語 バイナリファイルをfloatにしたいのですが…

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

質問者が選んだベストアンサー

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.3

実験的に、こんなコードを書いてみました。 当方の環境はリトルエンディアンのため、 ビッグエンディアンで格納してあるデータの バイトオーダーを変換しています。 【実行結果】 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; } (注)インデントのため、全角空白を使っています。

t-hiyori
質問者

お礼

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

その他の回答 (3)

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

(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 );  } 注:インデントに全角空白を使用しています。

t-hiyori
質問者

お礼

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

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

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

t-hiyori
質問者

お礼

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

回答No.1

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); } } }

t-hiyori
質問者

お礼

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

関連するQ&A