• ベストアンサー

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% (2126/6288)
回答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

  • C言語→C#に変換

    C言語→C#に変換 C言語からC#に変換したいのですが、わからないところがあります。 コマンドライン引数からファイル名とキーワードを入力して、キーワードがある行をアウトプットファイルに書き込むという処理です。 C言語のソースは、 main(int argc,char *argv[]){ FILE *fp; FILE *fpp; int i; char KEYWORD[256]; char buf[256]; //(1)アウトプットファイルのオープン fpp=fopen("output.txt","w"); for(i=1;i<argc-1;i++){ if(strcmp(argv[i],"-a")==0){ //(2)入力ファイルのオープン if((fp=fopen(argv[i],"r"))==NULL){ printf("open error!\n"); exit(1); } } //(3)キーワードの代入 if(strcmp(argv[i],"-b")==0){ strcpy(KEYWORD,argv[i]); } } //(4)一行読み込む while(fgets(buf,sizeof(buf),fp)!=NULL){ //(5)キーワードの条件で文字列抽出 if(strstr(buf,KEYWORD)!=NULL){ //(6)アウトプットファイルに出力 fprintf(fpp,"%s",buf); } } //ファイルクローズ fclose(fp); fclose(fpp); } です。 (3)キーワードの代入と、(5)文字列抽出の部分がネットなどで調べてもよくわかりません。 分かる方いらっしゃいましたら教えていただけると幸いです。 宜しくお願いします。 .

  • C言語の質問です

    下記のプログラムはテキストファイルを読み込み、AからZまでの文字(小文字、大文字は区別しない)がそれぞれ何回 現れたかを数えるプログラムです。 #include <stdio.h> #include <stdlib.h> #include <ctype.h> int count[26]; int main(int argc, char *argv[]) { FILE *fp; char ch; int i; /* ファイル名の指定を調べる */ if(argc!=2) { printf("ファイル名の指定がありません\n"); exit(1); } if((fp = fopen(argv[1], "r"))==NULL) { printf("ファイルを開くことができません\n"); exit(1); } while((ch=fgetc(fp))!=EOF) { ch = toupper(ch); if(ch>='A' && ch<='Z') count[ch-'A']++; } for(i=0; i<26; i++) printf("%c は %d 回出現\n", i+'A', count[i]); fclose(fp); return 0; } 1)int count[26]; で、なぜ26なのかが分かりません。 2)count[ch-'A']++; はどういう動作をするのか詳しく教えてほしいです。 3)よって、for文がどういう動作で表示しているのかが分かりません。 未熟者の私ですが、どなたか教えていただけないでしょうか?

  • 【C言語】ファイルを読み込んで16進数で表示する

    ファイルをバイナリモードで読み込んで16進数で表示するプログラムについて質問です。 以下の処理内容が理解できません。どのような処理を行っているのでしょうか?? (xdump.c)********************************* #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { int i, j; FILE *fp; if(NULL == (fp = fopen(argv[1], "rb"))) { fprintf(stderr, "Cannot open FILE[%s].\n", argv[1]); exit(1); } for(i=0; i<0x7FFF; ++i) { printf("%08X :", ftell(fp)); for(j=0; j<16; ++j) { int c; c = 0x00FF & getc(fp); if(ferror(fp)) { puts("\a>>>> Read Error ! <<<<"); break; } if(feof(fp)) break; /* 16進数で表示 */ printf(" %2X", c); } printf(" : %08X\n", ftell(fp)-1); /* : */ /* : */ /* 以下省略 */ ****************************************** 上記に関して、 最初のfor文から"c = 0x00FF & getc(fp);"までの処理内容が よくわかりません。どなたかご教授願えますでしょうか?

  • ファイルの内容の表示

    実行時のコマンドライン引数で指定したファイルの内容を、行番号付きで画面に表示するプログラムを作る という問題です。ヒントも与えられています。 行番号付きの表示、コマンドライン引数の利用。両者を組み合わせればできるはずだ >  main関数の引数にargcとargvを指定して、コマンドライン引数をファイル名として利用する。キーボード入力を促す文(プロンプト)や改行チェックは不要なので書かないこと >  コマンドライン引数が指定されない場合は、メッセージを表示してプログラムを終了 >  ファイルの内容を画面表示する処理は、ユーザー定義関数put_file_contentsに記述する。仮引数には文字型のポインタ変数をひとつ指定し、ファイル名を受け渡せるようにする。put_file_contents自体の型は整数型(int)で、正常終了なら返り値0を返すこと。 行番号付きのプログラム#include<stdio.h> > int put_file(char *filename); > > int main() > { > char line[50]; > char *ptr; > > printf("ファイル名を入力:"); > fgets(line,sizeof(line),stdin); > ptr = line + strlen(line) - 1; > if(*ptr == '\n') { > *ptr = '\0'; > } > > put_file(line); > > return 0; > } > > int put_file(char *filename) > { > FILE *fp; > char buf[100]; > int line_no; > > fp = fopen(filename,"r"); > if (fp == NULL){ > printf("%sを開けません\n",filename); > return 1; > } > line_no = 1; > while (fgets(buf,sizeof(buf),fp) != NULL){ > printf("%3d: ",line_no); > printf("%s",buf); > line_no++; > } > fclose(fp); > > return 0; > } で、コマンドライン引数のプログラムは#include<stdio.h> void write_key_inputs(char *filiname); int main(int argc, char *argv[1]) { write_key_inputs(argv[1]); return 0; } void write_key_inputs(char *filename) { FILE *fp; char buf[100] ; fp = fopen(filename,"w"); while(fgets(buf, sizeof(buf),stdin) != NULL) { fputs(buf, fp); } fclose(fp); return ; } です。これらを組み合わせて少しいじると出来るみたいなのですが、できていません。ちなみに私が考えたプログラムは #include<stdio.h> int put_file_contents(char *filename); int main(int argc,char *argv[]) { int i; if(argc == 1){ printf("コマンドライン引数がありません\n"); return 1; } for(i = 0;i<argc;i++) printf("argv[%d]は「%s」です\n",i,argv[i]); put_file(i); return 0; } int put_file(char *filename) { FILE *fp; char buf[100]; int line_no; fp = fopen(filename,"r"); line_no = 1; while (fgets(buf,sizeof(buf),fp) != NULL){ printf("%3d: ",line_no); printf("%s",buf); line_no++; } fclose(fp); return 0; } です。コマンドライン引数は表示されるのですが、行番号が表示されません。どうしたらいいでしょうか??

  • バイナリファイルの読み込み(C言語)

    raw(音楽ファイル)データを配列rawに読み込みたいのですが,バイナリファイルの読み込み方がわかりません. サンプルで以下のようなソース(途中略)があるのですが, ・なぜrawの型としてshortを使っているのか ・データ数の半分(file_size = ftell(fp) / 2)しか読み込んでいない ・fgetc(fp) << 8 あたりの意味がわからないので教えて下さい. -------------------------------------------------------- short *raw; if((fp=fopen(argv[1], "rb")) == NULL){ fprintf(stderr, "can't open %s.\n", argv[1]); exit(1); } fseek(fp, 0, SEEK_END); file_size = ftell(fp) / 2; fseek(fp, 0, SEEK_SET); raw = (short *)malloc((size_t)(file_size * sizeof(short))); if(raw == NULL){ fprintf(stderr, "malloc error\n"); exit(1); } for(i=0;i<file_size;i++) raw[i] = (short)((fgetc(fp) << 8) | fgetc(fp)); -----------------------------------------------------

  • ファイルコピープログラムについて

    まだC言語とか始めたばかりであまりよく分からないのですが、 今、ドラッグしたファイルをデスクトップにコピーするプログラムを作成してるのですが、少し困ったことになりました・・・・ 一応ファイルのコピーをデスクトップに作成はできるのですが、 何故か、作成されたファイルのサイズが2バイト程大きくなります・・・。 ファイルサイズを変えずにコピーする方法が分かりません・・・ ソースを張っておきますので、誰か解決策を教えていただけないでしょうか? #include <stdio.h> #include <windows.h> int main(int argc,char *argv[]) { FILE *fp,*copy; int buf; if(argc>1){ rename(argv[1],"DATA.bin"); fp=fopen("DATA.bin","rb"); copy=fopen("c:/xxx/yyy/Desktop/COPY.bin","wb"); while(1){ fread(&buf,sizeof(buf),1,fp); fwrite(&buf,sizeof(buf),1,copy); if(feof(fp)){ puts("OK"); fclose(fp); fclose(copy); rename("DATA.bin",argv[1]); rename("COPY.bin",argv[1]); exit(1); } } } return 0; }

  • C言語 複数指定したファイルの内容表示

    C言語の質問です。 「実行したファイル名を除いたコマンド ライン引数に、 複数個指定したすべてのファイルの内容を標準出力に表示する」 というプログラムを作成しようと思うのですが。。。 どうしても上手くいきません。 1つのファイルの内容を標準出力に表示するプログラムになってしまいます。 どなたかお力を貸してください。 ちなみに、私が作成したプログラムは、以下です。↓↓ #include <stdio.h> int main(int argc, char *argv[]) { FILE *fp; int c; if(argc != 2) { return 1; } if((fp=fopen(argv[1], "r"))==NULL) { return 1; } while((c=fgetc(fp)) !=EOF) { fputc(c, stdout); } fclose(fp); return 0; }

  • c言語 iconv

    msys環境で実行して,指定されたファイルの文字コードをShift-JISに変換して表示するコードを作成しているのですがうまく表示されません.何がいけないのでしょうか.第1引数に変換対象のファイル名,第2引数にファイルの文字コードを指定しています. #include <stdio.h> #include <string.h> #include <iconv.h> int main(int argc, char *argv[]) { iconv_t conv; char src[10000]; char dst[10000]; int src_len = strlen(src); int dst_len = sizeof(dst) - 1; char *buf_in; char *buf_out; FILE *fp; fp = fopen(argv[1], "r"); if(NULL == fp) { printf("ファイルを開けません\n"); } else { while(fgets(src, 10000, fp) != NULL) { buf_in = src; buf_out = dst; /* 変換器を作成 */ conv = iconv_open("Shift-JIS", argv[2]); /* 変換 */ iconv(conv, &buf_in, &src_len, &buf_out, &dst_len); *buf_out = '\0'; /* 終末処理 */ /* 文字コード後の文字列を表示 */ printf("%s\n", dst); } /* 変換器を終了 */ iconv_close(conv); /*ファイルを閉じる*/ fclose(fp); } return 0; }

  • C言語 Segmentation fault

    program SPROGRAM 17 4 pas104 SIDENTIFIER 43 4 ( SLPAREN 33 4 上記のようなファイルを読みこんで、1行づつ各トークン(programとか17とか)を構造体に格納する関数reader()を作りましたが、これを以下のparser.cで呼びだすと「Segmentation fault(core dumped)」となってしまいます。gdbのrunコマンドでプログラムを実行すると、関数を呼び出す所で Program received signal SIGSEGV, Segmentation fault. 0x0040140f in reader () と表示されました。が,どうすればよいか全然分かりません・・・ どうすれば正しく動作してくれるのか、どなたか教えてください・・・ 以下ソース /*read.c*/ #include "head.h" void reader(void) { fprintf(stdout,"check"); char buf[BUF_LEN]; if (fgets(buf,sizeof(buf),fp) == NULL)/*ここで1行読みこむ*/ {/*いきなりNULLの場合*/ strcpy(t.str, ""); t.num = SEOF; t.line = 1; } else { 省略 } return; } /*parser.c*/ #include "head.h" struct tokenbox t; FILE *fp; int main(int argc, char *argv[]) { if (argc != 2)/*引数チェック*/ { fprintf(stderr,"Usage: (./parser) (file.ts)\n"); return -1; } int len; len = strlen(argv[1]);/*file.ts の長さ取得*/ if((argv[1][len-1] == 's') && (argv[1][len-2] =='t') && (argv[1][len-3] == '.'))/*tsファイルが指定されているかどうか*/ { fp = fopen(argv[1],"r");/*ファイルオープン*/ if (fp == NULL) { fprintf(stderr,"Such ts file is not exist\n"); return -1; } fprintf(stdout,"authenticate ts file!\n");//←これは出力される reader(); //←ここでSegmentation faultと思われる printf("t.str = %s\n", t.str); printf("t.str[0] = %c\n", t.str[0]); printf("t.num = %d\n", t.num); printf("t.line = %d\n", t.line); fclose(fp); return 0; } else { fprintf(stderr,"the file is not ts\n"); return -1; } } ヘッダファイル一部抜粋 /*head.h*/ #include <stdio.h> #include <string.h> #include <stdbool.h> #define BUF_LEN 128 #define TOKEN_LEN 128 struct tokenbox {/*tsファイルの各情報を格納する構造体*/ char str[TOKEN_LEN]; int num; int line; }; extern struct tokenbox t;/*構造体をtと置く*/ extern FILE *fp; /*ファイルポインタ*/

  • c言語でデータの指定列の度数分布をつくろうとしています。

    c言語でデータの指定列の度数分布をつくろうとしています。 以下のように1列のデータに対してはプログラムを組むことができます。 #include<stdio.h> #include<stdlib.h> #define UPPERBOUND 2.0 #define LOWERBOUND -2.0 #define RANGE 0.1 int main(int argc, char* argv[]){ int i; FILE *fp; FILE *fp2; char str[256]; if(argc != 2 && argc != 3){ printf("***usage: %s <datafilename>\n", argv[0]); exit(-1); } if((fp = fopen(argv[1], "r")) == NULL){ printf("can't open file\n"); exit(-1); } if(argc == 3){ if((fp2 = fopen(argv[2], "w")) == NULL){ printf("can't open outputfile\n"); exit(-1); } } int tablesize = (UPPERBOUND-LOWERBOUND)/RANGE; int table[tablesize]; for(i=0; i<tablesize; i++){ table[i] = 0; } while((fgets(str, 256, fp)) != NULL){ double dbl = atof(str); if(!(dbl < LOWERBOUND || dbl > UPPERBOUND)){ int n = (dbl-LOWERBOUND)/RANGE; table[n]++; } } for(i=0; i<tablesize; i++){ printf("%lf~%lf\t: %d\n", LOWERBOUND+(i*RANGE), LOWERBOUND+((i+1)*RANGE), table[i]); if(argc == 3){ fprintf(fp2, "%lf~%lf\t: %d\n", LOWERBOUND+(i*RANGE), LOWERBOUND+((i+1)*RANGE), table[i]); } } return 0; } そこで複数列のデータに対して、例えば10列100行のデータに対して6列目だけを見たいときはどうすればできますでしょうか?

専門家に質問してみよう