0

次のようなPerson構造体があります。

typedef struct Person {
    char name[NUM_CHARS];
    unsigned int age;
} Person;

どこで#define NUM_CHARS 20

この構造をバイナリ ファイルに書き込みたいので、それを処理する 2 つの関数を作成しました。

int writePerson(Person* person, FILE* _fp) {
    int i = 0;
    int count = 0;
    int len = strlen(person->name);
    // Write name
    for(i = 0; i < len+1; i++) {
        count += fwrite(&(person->name[i]), sizeof(char), 1, _fp);
    //  fseek(_fp, 1, SEEK_CUR);
    }
    // Continue
    // Write age
    count += fwrite(&(person->age), sizeof(unsigned int), 1, _fp);

    return count;
}

int readPerson(Person* person, FILE* _fp) {
    int i = 0;
    int count = 0;
    // Write name
    for(i = 0;person->name[i] != NULL;i++) {
        count += fread(&(person->name[i]), sizeof(char), 1, _fp);
    }
    // Continue
    // Write age
    count += fread(&(person->age), sizeof(unsigned int), 1, _fp);

    return count;
}

そこで、事前に作成Personした空のファイルに aを書きました。Px.bin

int main() {
    FILE* fp = fopen("Px.bin", "r+b");
    Person person = {"Billie", 40};
//  Person y ;
    int x = writePerson(&person, fp);
    printf("%d", x);
//  printPerson(&y);
    getchar();
    fcloseall();
    return 0;
}

うまくいくようです、印刷し8ます。

しかし、このファイルを読み込もうとすると:

int main() {
    FILE* fp = fopen("Px.bin", "r+b");
//  Person person = {"Billie", 40};
    Person y ;
    int x = readPerson(&y, fp);
    printf("%d\n", x);
    printPerson(&y);
    getchar();
    fcloseall();
    return 0;
}

私はこの結果を得ています:

11
Billie
-858993460

printPerson の場所:

void printPerson(Person* p) {
    printf("%s\n%d\n", p->name, p->age);
}

何が問題ですか?

4

2 に答える 2

0

名前を読み取るコードは、おそらく初期化されていない (またはゼロになっている)person->name[i]要素をチェックします。その結果、ループは予測不可能な時間に終了します (つまり、ループがゼロに設定されている場合、ループはfread1 文字でさえありません)。

for(i = 0;person->name[i] != NULL;i++) {
    count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}

do/ループに変更するwhileか、ファイル文字列内のプレフィックス データまで読み取る代わりに0、長さを指定してその文字数を読み取る必要があります。

于 2013-04-15T04:35:45.470 に答える
0

このビット

for(i = 0;person->name[i] != NULL;i++) {
    count += fread(&(person->name[i]), sizeof(char), 1, _fp);
}

person->name[]読み取りの条件として、初期化されていない (IOW、ガベージを含む) を使用します。そして、ここで間違ったバイト数が読み取られる可能性があります。

その後は以下

count += fread(&(person->age), sizeof(unsigned int), 1, _fp);

整数が保存されている場所ではなく、ファイル内の誤った場所から整数を読み取ることができます。

修正は、最初に文字を読み取ってから、それがそうであるかどうかを確認すること'\0'です。そうであれば、文字列は完全に読み取られています。そうでない場合は、文字を読み続けます。

于 2013-04-15T04:35:57.853 に答える