2

fread を使用してファイルを読み取り、内容を出力しようとしているだけです。部分的に機能しています。すべてを正しく出力しますが、一連のランダムな文字で終了します。

#include <iostream>

using namespace std;

void ReadFile(char* filename,char*& buffer)
{
    FILE *file = fopen(filename,"rb");

    fseek(file,0,SEEK_END);
    int size = ftell(file);
    rewind(file);

    buffer = new char[size];
    memset(buffer,0,size);

    int r = fread(buffer,1,size,file);
    cout << buffer;

    fclose(file);
}

int main()
{
    char* buffer;
    ReadFile("test.txt",buffer);
    cin.get();
}

この例では、「サイズ」が 50 であるとしましょう。何らかの理由で、fread が呼び出された後、バッファーのサイズは 55 または 56 になります。使用前にバッファを空にして出力してみましたが、すべて正常です(空です)。fread を呼び出した直後に、バッファが何らかの形で大きくなり、ランダムな文字でいっぱいになります。テキスト ファイルを 16 進エディタで開いて、表示されていないものがないことを確認しました。ファイルは 50 バイトです。fread は読み取ったバイト数を返します。この場合は「r」に返されます。「r」は本来あるべき値です。それで、これらのバイトはどこから来ているのですか?

簡略化: fread は読み取った正しいバイト数を返しますが、fread が呼び出された後、バッファが何らかの形で大きくなり、ランダムな文字で埋められます。なぜ?

私は一生、これがどのように起こっているのか理解できません。

また、誰かが私に簡単な修正を与える前に、私は buffer[r] = '\0' を実行するだけでランダムな文字を出力しないようにすることができることをすでに知っていますが、なぜこれが起こっているのか知りたいです。

4

3 に答える 3

6

cout<<演算子 onchar*は C 文字列を想定しているため、次のように null で終了する必要がありますbuffer

int size = ftell(file)+1; // Leave space for null terminator
...
int r = fread(buffer,1,size-1,file); 
buffer[r] = '\0';
cout << buffer;

表示される余分な文字は、末尾のメモリ アドレス内のランダム データですbufferoperator <<は文字列が終了したことを認識しないため、最初の'\0'バイトが見つかるまで印刷を続けます。

于 2013-07-17T18:55:23.150 に答える
0

実際に cout は、NULL 文字がなくなるまで文字列を出力します。つまり、終了には NULL が必要でした。

ただし、NULL を割り当てることは、常に良い解決策ではありません。その時点でデータはバイナリである可能性があり、cout は NULL 文字までの出力のみを出力します。つまり、バイナリデータは何でもかまいませんし、読めない文字でもかまいません。cout はそれを NULL 文字と見なします。そのため、文字列またはデータセットの長さまで for ループを使用しても常に安全です。

len = strlen(buffer)
for (int i = 0; i < len; i++)
     printf("%c", buffer[i])     

// または、FILE *fp; を使用することもできます。for (int i= 0; i < len; i++) fprintf(fp, "%c", buffer[i]); 別の良いアプローチは、fwrite を使用することです。

于 2013-07-17T19:22:45.390 に答える
0

おそらく、バッファを null で終了することを忘れているだけでしょう。代わりに、cout.write を使用してバッファの長さを指定します。

少しのエラー処理の追加 (十分ではありませんが、開始)、欠落している include および using ステートメント: http://coliru.stacked-crooked.com/view?id=8bc4f3b7111554c705de96450d806104-f674c1a6d04c632b71a62362c0ccfc51

#include <iostream>
#include <string>
#include <vector>
#include <cstring>

using namespace std;

void ReadFile(const char* filename,char*& buffer)
{
    FILE *file = fopen(filename,"rb");

    if (!file)
         return;

    fseek(file,0,SEEK_END);
    int size = ftell(file);
    rewind(file);

    buffer = new char[size];
    memset(buffer,0,size);

    int r = fread(buffer,1,size,file);
    cout.write(buffer, r);

    fclose(file);
}

int main()
{
    char* buffer;
    ReadFile("test.txt",buffer);
    cin.get();
}
于 2013-07-17T18:55:53.850 に答える