
元ネタ
http://oshiete1.goo.ne.jp/qa3809521.html
/*
C#
*/
using System;
namespace Q3809521A
{
class Q3809521A
{
public static void Main(string[] args)
{
byte[] b1 = {0x42,0xb9,0xe0,0xa4,0x3b,0xdf,0xea,0xc0,0x3a,0x70,0xeb,0xdc,0x37,0x7c,0xf4,0x8c};
System.IO.FileStream f = new System.IO.FileStream("C:\\hogefuga.bin",System.IO.FileMode.Create, System.IO.FileAccess.Write);
f.Write(b1,0,b1.Length);
System.Console.WriteLine(BitConverter.ToString(b1));
f.Close();
System.Console.ReadKey(true);
}
}
}
という風に作ったhogefuga.binを
bccでコンパイルした以下のプログラムで読み込ませたところ,
#include <iostream>
#include <fstream>
int main () {
unsigned char buf[4];
float *hoge;
std::ifstream ifs ( "hogefuga.bin" , std::ifstream::in );
while(!ifs.eof()){
// Debug
// std::cout << (ifs.eof() == true ? "TRUE" : "FALSE") << std::endl ;
for (int i = 0;i < 4;i++ ){
buf[3 - i] = (unsigned char) ifs.get();
}
hoge = (float *)buf;
std::cout << (*hoge) <<std::endl;
}
ifs.close();
return 0;
}
92.9388
0.0068334
0.000919042
1.50773e-05
と、期待通り表示された後も
ifs.eof()がtrueにならず,続きを読み込もうとして
クラッシュします。
どうやって回避するのが普通なのでしょう?
#バイト数を先に把握するってのも一つの手かもしれないけど,普通じゃないような気がする
No.2ベストアンサー
- 回答日時:
よくある間違いですが,CのfeofやC++のbasic_ios::eof()は,何らかの読み込み処理をした結果がEOFだった場合に真を返すようになります。
今回の場合,ifs.get()がstd::char_traits<char>::eof()を返したタイミングで,basic_ios::eof()がtrueを返すようになります。
そのため,ifs.get()で判別しなければなりません。
あと,コンストラクタでinの他にbinaryを指定しておかないと,0x0D 0x0Aが含まれた場合などに0x0D扱いされて1バイト不足する事態が起きますよ。
この回答への補足
#include <iostream>
#include <fstream>
int main () {
unsigned char buf[4];
float *hoge;
std::ifstream ifs ( "hogefuga.bin" , std::ifstream::in | std::ifstream::binary );
while(true){
for (int i = 0;i < 4;i++ ){
buf[3 - i] = (unsigned char) ifs.get();
}
if ( !ifs.eof() ){
hoge = (float *)buf;
std::cout << (*hoge) << std::endl; /* エラーは EOFだった時にここで出ているようだ */
}else{
break;
}
}
ifs.close();
return 0;
}
/* 一応エラーが出なくなったけど、こういうことだろうか? */
No.3
- 回答日時:
>#とはいえ、俺自身はNANを表示させるコードのつもりはなかったんですが
>何で表示されているんだろう・・・(NANの時にeofになるんだと思ってた)
これは#2の方の説明にあるように、ファイルの末尾に達して(最後のキャラクタを読んだ状態で)から
さらに読み進めてたときに eof() が true になるので、
>while(!ifs.eof()){
これだとかならず末尾に一つゴミデータが発生します。
そのゴミがたまたま VC++もg++もNaNとみなすような
ものだったということでしょう。
#って、全bit Onのデータになるのかな?
> while(true){
> for (int i = 0;i < 4;i++ ){
> buf[3 - i] = (unsigned char) ifs.get();
> }
>
>if ( !ifs.eof() ){
半端なバイトデータがあったときに空読みが発生してるのを無視している
(unsigned charにキャストしている)のが気になりますが
ゴミデータはでないですね。
まあ好みの問題ですが、わたしなら ifsteram.read() で sizeof (float) 読み込んでおいて
その結果を swap するなどします。
C++入出力
http://www.cppll.jp/cppreference/cppio_details.h …
この回答への補足
>半端なバイトデータがあったときに空読みが発生してるのを無視している
意図的にやってました。変数一個増やしてぐちゃぐちゃ書くのが悔しかったので。
#include <iostream>
#include <fstream>
int main () {
unsigned char buf[4];
float *hoge;
std::ifstream ifs ( "hogefuga.bin" , std::ifstream::in | std::ifstream::binary );
while(true){
for (int i = 0;i < 4;i++ ){
unsigned char c = (unsigned char) ifs.get();
if ( c != (unsigned char) std::char_traits<char>::eof()){
buf[3 - i] = c;
}else{
break;
}
}
if ( !ifs.eof() ){
hoge = (float *)buf;
std::cout << (*hoge) << std::endl;
}else{
break;
}
}
ifs.close();
return 0;
}
No.1
- 回答日時:
eof の判定位置がよろしくないような気がしますがそれはおいといても
VC++
92.9388
0.0068334
0.000919042
1.50773e-005
-1.#QNAN
g++
92.9388
0.0068334
0.000919042
1.50773e-05
nan
のどちらも、NaNを出力した後で正常終了してます。
クラッシュというのはSEGVでもおきているんでしょうか?
#include <iostream>
#include <fstream>
int main () {
unsigned char buf[4];
float *hoge;
std::ifstream ifs ( "hogefuga.bin" , std::ifstream::in );
while(!ifs.eof()){
// Debug
// std::cout << (ifs.eof() == true ? "TRUE" : "FALSE") << std::endl ;
for (int i = 0;i < 4;i++ ){
buf[3 - i] = (unsigned char) ifs.get();
}
#if 0
if (ifs.eof()) {
std::cerr << "quit (1)" << std::endl;
break;
}
#endif
hoge = (float *)buf;
std::cout << (*hoge) <<std::endl;
#if 0
#ifdef HAVE_ISNAN
if (isnan(*hoge)) {
std::cerr << "quit (2)" << std::endl;
break;
}
#else
float x;
float y;
x = *hoge;
y = *hoge;
if (x!=y) {
std::cerr << "quit (2)" << std::endl;
break;
}
#endif
#endif
}
ifs.close();
return 0;
}
この回答への補足
ご指摘の通り
俺のコードもsakusaker7さんに書いてもらったコードも,
g++/MinGW v5.1.3(installer) では正常終了します。
#とはいえ、俺自身はNANを表示させるコードのつもりはなかったんですが
何で表示されているんだろう・・・(NANの時にeofになるんだと思ってた)
#個人的にあまり色々入れたくないのでVC++は入れてません。
(俺のコード)
bcc32 5.5.1
==================
q3810761-1.exe - アプリケーションエラー
例外 unknown software exception (0xc0000090)がアプリケーションの0x004117e1で発生しました。
q3810761-1.exe - アプリケーションエラー
例外 unknown software exception (0xc0000090)がアプリケーションの0x004117e1で発生しました。
q3810761-1.exe - アプリケーションエラー
例外 unknown software exception (0xc0000027)がアプリケーションの0x7c80df2cで発生しました。
==============================
>eof の判定位置がよろしくないような気がしますが
これはどのような理由でしょうか?
確かに,4(sizeof(float))バイトで割り切れないファイルがあった時,eofになるのか疑問ですが,今回は16バイトですから,変な現象に遭うことはないんじゃないかなあと思ってますが・・・
#念のため,前置判定じゃなく、後置判定にしてみたけど駄目だった
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テイラー展開とその精度について
-
VC++で文字列から任意の文字を...
-
#include "fstream.h"
-
VC++ iostreamの不具合(?)
-
shared_ptr クラスについて
-
switch文のエラーについて
-
#define中の#のエスケープ
-
「Aに対するBの割合」と「Aに対...
-
「指定されたキャストは有効で...
-
Enterキーを押されたら次の処理...
-
エクセルで可視セルにのみ値貼...
-
DWORDの実際の型は何でしょうか
-
数字以外が入力されたらエラー...
-
プログラムでの数字につく”f”の...
-
2÷3などの余りについて
-
隣接行列を読み込んで有向グラ...
-
信頼区間の1.96や1.65ってどこ...
-
Aの値からBの値を除するとは??
-
静的でないメンバ関数の呼び出...
-
C 開放してるのにエラー(doubl...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VC++で文字列から任意の文字を...
-
なぜ、C++の標準ヘッダをインク...
-
switch文のエラーについて
-
VxWorks 6.4ソケット接続につい...
-
gccでコンパイル時のエラー
-
iostream インクルード時に発生...
-
#include "fstream.h"
-
【C++】ヘッダ内でstringを格納...
-
#defineの使い方について
-
構文エラーが出ているのですが...
-
C言語のポインターで詰まっている
-
std::map の const 修飾について
-
C++での <iostream.h>と<iostre...
-
enumの値から定義名を文字列化...
-
MingwでC++のソースがコンパイ...
-
違い
-
VC++で
-
C++で日本語の処理がしたいです
-
継承されたABのクラスのポイン...
-
C++でShowCursorを使いたい。
おすすめ情報