- ベストアンサー
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
- みんなの回答 (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; } (注)インデントのため、全角空白を使っています。
その他の回答 (3)
- yama5140
- ベストアンサー率54% (136/250)
(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 ); } 注:インデントに全角空白を使用しています。
お礼
共用体は、ずーと昔「C言語入門シニア編」で見ましたが、 一生使うことがないと思ってました。 これは、便利ですね。有難う御座いました!!
- jacta
- ベストアンサー率26% (845/3158)
ファイルにはビッグエンディアンでデータが格納されているのに、リトルエンディアンとして強引に解釈しようとしているからです。
お礼
ビッグエンディアン??リトルエンディアン?? 大変興味深いです。調査してみます♪ 有難う御座いました。
- himajin100000
- ベストアンサー率54% (1660/3060)
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); } } }
お礼
ご回答ありがとうございます。 C#やったことないんですよねぇ 気持ちは大変うれしいです♪
お礼
なるほど!!と言った感じです。 リトルエンディアン、ビックエイディアンを理解しました♪ 解決です有難う御座いました!!