0

私はフォーラムに不慣れです。奇妙な問題があります。read() 関数を使用してファイルからフォーマットされていないデータを読み取る単純なコードがあります。コードを以下に示します。

int main () {
    ifstream meshfile;
    char buf[1000], ch;
    memset(buf, 0, 1000);
    meshfile.open ("sometextfile");
    meshfile.read (buf, 1000);//38+62+(19*47) + 7);
    cout << strlen(buf) << std::endl;
    cout << buf << std::endl;
}

以下のサンプル入力ファイルでコードを実行すると、buf の長さとして 1006 が与えられ、buf の追加文字が出力されます。奇妙なことに、これは bufsize が 1000 で 1000 文字が読み取られた場合にのみ発生します。bufsize を > 1000 に変更して 1000 文字を読み取っても、このエラーは発生しません。これはコーディングの問題でしょうか?

サンプル入力ファイルは

fdjgjdskgggggggggggggggggggggggggggggj bvjgdsv dsjkvgds gvdsj gvjdsgvjksdjkfgdsjkgfdsjgfsdjgfjkdsgfkjsdgjfgsdjfgdsjgfsdjgfjsdgfjsgfjsdgfjgsdjfgsdjfgdsjgfsdjgfsdjgfjsdgfjsdgfjsdg fdjgjdskgggggggggggggggggggggggggggggj bvjgdsv dsjkvgds gvdsj gvjdsgvjksdjkfgdsjkgfdsjgfsdjgfjkdsgfkjsdgjfgsdjfgdsjgfsdjgfjsdgfjsgfjsdgfjgsdjfgsdjfgdsjgfsdjgfsdjgfjsdgfjsdgfjsdg fdjgjdskgggggggggggggggggggggggggggggj bvjgdsv dsjkvgds gvdsj gvjdsgvjksdjkfgdsjkgfdsjgfsdjgfjkdsgfkjsdgjfgsdjfgdsjgfsdjgfjsdgfjsgfjsdgfjgsdjfgsdjfgdsjgfsdjgfsdjgfjsdgfjsdgfjsdg fdjgjdskgggggggggggggggggggggggggggggj bvjgdsv dsjkvgds gvdsj gvjdsgvjksdjkfgdsjkgfdsjgfsdjgfjkdsgfkjsdgjfgsdjfgdsjgfsdjgfjsdgfjsgfjsdgfjgsdjfgsdjfgdsjgfsdjgfsdjgfjsdgfjsdgfjsdg fdjgjdskgggggggggggggggggggggggggggggj bvjgdsv dsjkvgds gvdsjgvjdsgvjksdjkfgdsjkgfdsjgfsdjgfjkdsgfkjsdgjfgsdjfgdsjgfsdjgfjsdgfjsgfjsdgfjgsdjfgsdjfgdsjgfsdjgfsdjgfjsdgfjsdgfjsdg fdjgjdskgggggggggggggggggggggggggggggj bvjgdsv dsjkvgds gvdsj gvjdsgvjksdjkfgdsjkgfdsjgfsdjgfjkdsgfkjsdgjfgsdjfgdsjgfsdjgfjsdgfjsgfjsdgfjgsdjfgsdjfgdsjgfsdjgfsdjgfjsdgfjsdgfjsdg

4

4 に答える 4

1

あなたの問題は の使用です でstrlen 終わる文字列が必要\0です。

readバッファの末尾にa を追加しない\0ため、strlen はバッファの端を超えて読み取ります。

于 2012-11-06T08:06:27.903 に答える
0

ここにいる人たちと私が言いたいのは、次のことだと思います。

1)read(..) は null ターミネータを追加しません。

2) memset を使用してバッファを 0 に初期化しました。1000 文字未満を読み取ると、最後に読み取られた文字の後に続く配列要素はすべて 0 のままです (その値に初期化されているため、実質的に null です)。壊れませんでした。これが、Jive Dadson がバッファのサイズを 1001 文字に変更し、配列を 0 に初期化するように要求する理由です。これにより、1000 文字で読み取っても、1001 番目の文字は 0 のままで、ヌル ターミネータとして機能します。

しかし、これは実際にはバグです。< BUF_SIZE の最後の行を読み込むとどうなるか考えてみてください。したがって、一部のポスターで示唆されているように、各ターンで読み取られる文字数を確認することをお勧めします。

3) 1000 文字を超える読み取りを行った場合、より大きなバッファーに変更し、このより大きなバッファー用にバッファーを「0」に初期化しましたか? その場合は、上記と同じ状況になるため、当然問題はありません。そうでない場合は、1000 文字を超える文字を 1000 文字のバッファーに読み込む方法に興味があります。

4)基本的に、現在のデータ読み取り方法は信頼できません。バッファのサイズを変更して、読み取る予定の最大要素よりも 1 つ多くの要素を含める必要があります。buf を文字列として渡し、copy、printf などの操作を実行する場合は、読み取りごとに実際に読み取られた文字数を取得し、ヌル ターミネータを設定する必要があります。

于 2012-11-06T09:12:32.260 に答える
0

バッファーを 1001 文字の長さにし、ヌル終了の余地を残します。メムセット1001もございます。その nul ターミネータがないと、strlen は機能しません。

さらに良いのは、<array> を使用し、memset を使用しないことです。単純な buf[1000] = 0 で十分です。

于 2012-11-06T08:04:53.200 に答える
0

ファイルから読み取られるのは、'\0' で終了する文字列ではなく、生データです。実際にバッファに読み込まれたバイト数を含む stream.gcount() の戻り値を確認し、後続のコードで使用する必要があります。マニュアルはこちら

  size_t size = meshfile.read(buf, sizeof(buf)/sizeof(*buf)).gcount();
  std::cout << size << std::endl;
于 2012-11-06T08:06:12.000 に答える