1

文字列を他の多くのデータとともにバイナリファイルに保存したいのですが、以下のコードを使用しています(実際に使用すると、文字列はmallocされます)ファイルに書き込むことができます。私はそれを16進エディタで見ました。nullターミネータを正しく書いているかどうかはわかりません(または必要な場合)。読み返すと、保存したのと同じ文字列の長さが得られますが、文字列ではありません。私は何を間違っていますか?

FILE *fp = fopen("mybinfile.ttt", "wb");

char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);    
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);

//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);

fclose(fp);

fp = fopen("mybinfile.ttt", "rb");  

unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);

char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);

//CRASH POINT
printf("%s\n", drumReadString);

fclose(fp); 
4

6 に答える 6

7

いくつかの問題、いくつかの問題、いくつかの文体が見えます。

  • mallocからの戻り値を実際にテストする必要がありますfreadfwrite割り当てが失敗する可能性があり、データの読み取りまたは書き込みが行われない可能性があるためです。
  • sizeof(char)常に1 です。乗算する必要はありません。
  • 文字配列"Hello\0"は、実際には 7 バイトの長さです。余分な null ターミネータを追加する必要はありません。
  • char x[] = "xxx";私は、明確な長さを指定するよりもイディオムを好みます (もちろん、文字列よりも長い配列が必要な場合を除きます)。
  • すると、実際にはポインタが指すメモリではなく、ポインタfread(&drumReadString ...を上書きしています。これがクラッシュの原因です。である必要があります。fread(drumReadString ...
于 2010-03-10T08:54:08.053 に答える
7

あなたは読書中に間違ったことをしています。ポインター変数に & を入れたので、セグメンテーション違反が発生します。

正常に動作し、Hello を正しく返すことを削除しました。

int count = fread(drumReadString, sizeof(char), stringLength, fp);
于 2010-03-10T08:55:38.867 に答える
6

いくつかのヒント:

1

終了\0は、二重引用符文字列では暗黙的であり、最後に追加を追加すると、2 つになります。次の 2 つの初期化は同一です。

char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};

そう

char drumReadString[] = "Hello";

このように初期化する場合、配列のサイズの指定はオプションです。コンパイラは必要なサイズ (6 バイト) を計算します。

2

文字列を書き込むときは、すべての文字を一度に書き込むこともできます (1 文字ずつ sizeOfString 回書き込むのではなく)。

fwrite(drumCString, sizeOfString, 1, fp);

3

通常のデスクトップ PC のシナリオではあまり一般的ではありませんが、malloc は NULL を返す可能性があり、組み込み環境では NULL を取得する可能性が低いわけではないため、結果を常にチェックする習慣を身に付けることでメリットが得られます。

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}
于 2010-03-10T09:09:44.667 に答える
0

paxdiablo と AProgrammer にさらに追加する必要があります。将来的に malloc を使用する場合は、最初から使用してください。これはより良い形式であり、切り替え時にデバッグする必要がないことを意味します。

さらに、unsigned short の使用を完全には見ていません。バイナリ ファイルを作成する予定がある場合は、unsigned char 型は一般にバイト サイズであり、その目的には非常に便利であることを考慮してください。

于 2010-03-10T08:58:48.920 に答える
0

fread関数で&drumReadStringを削除するだけです。ガネーシュが述べたように、その関数でdrumReadStringを使用するだけです.drumReadStringは配列であるため、配列はメモリ位置を直接指すポインターに似ています。

于 2010-03-10T09:40:46.530 に答える
0

終端の NUL を書く必要はありませんが、読むときにそれを追加することを考える必要があります。つまり、malloc stringLength + 1 文字、stringLength 文字を読み取り、読み取っ\0たものの最後に a を追加します。

ここで通常の警告: ここで行っている方法でバイナリ ファイルを作成している場合、多くの明言されていない仮定があり、フォーマットを移植するのが難しくなり、同じコンパイラの別のバージョンに移植することさえ困難になります。コンパイラのバージョン間での構造体の変更。

于 2010-03-10T08:54:52.793 に答える