2011-01-14 5 views
0

これは私の問題です。私はバイナリモードでファイルを読み込み、バイトをint配列に追加して、その後に値を出力しています。私の問題は、私が結果を出すときに、ランダムな文字がストリームにつけられていることです。文字の配列を印刷するときにランダムな文字が表示される

comp.txt:

this text is a testt1 

main.cppに:

#include <iostream> 
#include <fstream> 
#include <time.h> 


using namespace std; 

void read(ifstream& stream, unsigned int buf[], int size) 
{ 
    for(int i = 0; i < size; ++i) 
    { 
     unsigned char temp[4] = {'\0', '\0', '\0', '\0'}; 
     stream.read((char*)temp, 4); 
     cout << "Temp: " << temp << '\n'; 
     buf[i] = *((int*)temp);  
     cout << "Read: " << buf[i] << endl; 
     memset(temp, '\0', 4); 
    } 
} 

int main() 
{ 

    // open file 
    ifstream f; 
    f.open("comp.txt", ios::binary); 
    cout << "File opened. " << endl; 

    // get size 
    f.seekg(0, ios::end); 
    int l = f.tellg(); 
    int length = (l/4) + 1; 
    f.seekg(0, ios::beg); 
    cout << "Size found: L: " << l << " Length: " << length << endl; 

    // allocate byte arrays 
    unsigned int* buf = new unsigned int[length]; 
    memset(buf, '\0', 4*length); 
    // unsigned short* key = new unsigned short[length]; 
    cout << "Preparing to read..." << endl; 

    // read byte into short 
    cout << "Reading..." << endl; 
    read(f, buf, length); 
    f.close(); 
    delete[] buf; 
    cin.ignore(1000, 10); 
    return 0; 
} 

出力:注意すべき

C:\Users\daminkz\Desktop>encrypt 
File opened. 
Size found: L: 21 Length: 6 
Preparing to read... 
Reading... 
Temp: this 
Read: 1936287860 
Temp: tex☺ 
Read: 2019914784 
Temp: t is☻ 
Read: 1936269428 
Temp: a t♥ 
Read: 1948279072 
Temp: estt♦ 
Read: 1953788773 
Temp: 1 
Read: 49 

もの:

  • 一時にされます4バイトだけですが、5バイトが印刷されます。
+4

アドバイス: 'int'は32ビット幅に依存しないでください。 '#include 'と 'uint32_t'を使います。 – ulidtko

答えて

6

テンポラリで読み込むと、4文字すべてがデータで上書きされ、NULLターミネータなしで残ります。 cout.operator < <(char *)はヌルで終了する文字列を必要とするため、ヌルターミネータに達するまでできるだけ多くの文字を出力します。 tempを5文字にすると、すべて '\ 0'になりますが、バイト数を4にしておくと問題が緩和されます。

+0

私はtempを宣言してbuf [i]にキャストすると問題は起こりませんか? –

+1

@Charlesはポインタを型キャストして4つの文字をint型に変換するのではなく、悪いことです。 'buf [i] = temp [0] +(temp [1] << 8)+(temp [2] << 16)+(temp [3] << 24)のようなものを使ってください。 – ulidtko

+1

それはおそらく問題を引き起こすことはありませんが、ulidtkoは言ったように、あなたはほとんどそれをしたくないと確信しています。実行しているシステムと同じエンディアンで整数を読み込んでいる場合は、intを直接読み込んだり、ビット単位の操作で整数のバイトを手動で設定したりしてください。私はあなたがやっていることの全体的な美しさにコメントしたが、バイナリデータを読む良い方法がある。 – yan

1

印刷中のバッファはヌル終了していません。

2

あなたはヌルで終了する文字列として一時を出力しているが、NULLで終了していないので、あなたが誤って0

1

に実行するまで、あなたは一時と文字化けの未知数のうち4文字を印刷しますchar配列をcoutに渡すと、charポインタに変換されます。つまり、通常「C文字列」と呼ばれています。これは、文字列の終わりを見つけるために、出力ルーティングは最初の0x00 NUL文字を検索することを意味します。

あなたの配列は4文字ですが、4文字がファイルから読み込まれます。これらのどれもNULでなければ、出力はメモリから文字を読み続けるでしょう。それはあなたが見ている変な文字です。別の可能性のある結果はセグメンテーションであることに注意してください。なぜなら、明示的に割り当てなかったメモリを読み書きすることができないからです。

解決策として、4つではなく5つの文字列を宣言することができます。出力を停止するためにNULには常に5番目のままにしておきます。

関連する問題