2017-03-01 7 views
1

私は現在、C++のバイナリファイルを研究しています。私はそれのためのサンプルコードを作ったが、うまくいきません。ここC++のバイナリファイルから整数値を取得する際のガーベジの値

#include <iostream> 
#include <fstream> 
using namespace std; 

int main() { 
    ofstream writeFile; 
    ifstream readFile; 
    int temp = 1; 

    writeFile.open("file.dat", ios::binary); 

    for (int i = 5; i <= 10 ; i++) // range 5 to 10 
     writeFile.write((char*)(&i), sizeof(i)); 

    writeFile.close(); 

    readFile.open("file.dat", ios::binary); 
    readFile.seekg(0); 
    while (!readFile.eof()) { 
     readFile.read((char*)(&temp), sizeof(temp)); 
     cout << "temp: " << temp << endl; 
     readFile >> ws; 
    } 
    readFile.close(); 

    system("pause"); 
    return 0; 
} 

結果である:私は9(8に例えば、5)を含まない範囲を変更すると、それは十分

temp: 5 
temp: 6 
temp: 7 
temp: 8 
temp: 167772160 
temp: 167772160 

働きます。また、同じコードをdouble型で作るとうまくいきます。だから私は整数9が問題だと思う。なぜか教えてくれますか?

答えて

4

readFile >> ws;は空白を捨てます。これはバイナリストリームには意味がありません。この場合、文字値9('\t')はスキップされ、ストリームが破損します。単にその行を削除します。

2番目の問題は、値の読み取りと表示の間にストリームの状態をチェックしていないことです。の後にEOFが検出されるのは、の場合のみです。読み取りがファイルの末尾を超えます。このため、無効な値が2回読み込まれ、2回目の読み込みに失敗し、単に前の値のtempになります。詳細はSee this questionをご覧ください。

+0

値9は、実際には、 '\のT 'です。 10は '\ n'です。両方とも空白とみなされているという事実が、この問題の原因です。 – IInspectable

+0

または、 'readFile >> ws'が' \ t'文字だけをスキップし、リトルエンディアンの4バイト整数として解釈される4バイト '00 00 00 0a'を読み取る値は167772160です。これはまだですよく定義されている(私は信じている)。しかし、次の読み取り試行はEOFを超えて読み取ります。これはUBであり、167772160を表示することは、未定義の動作の有効な形式です。 – IInspectable

1

The answer by François Andrieuxには、コードがどのように動作するのかという質問に対する回答が既にあります。

ここでは、問題を解決するための方法がいくつかあります。

  1. 数字を読むにはforループを使用してください。それは、それに書き込むために使用されたループを反映します。

    readFile.open("file.dat", ios::binary); 
    for (int i = 5; i <= 10 ; i++) 
    { 
        readFile.read((char*)(&temp), sizeof(temp)); 
        cout << "temp: " << temp << endl; 
    } 
    readFile.close(); 
    
  2. 正しくwhileループを使用してください。

    readFile.open("file.dat", ios::binary); 
    while (readFile.read((char*)(&temp), sizeof(temp))) 
    { 
        cout << "temp: " << temp << endl; 
    } 
    readFile.close();