0

我有一个Person结构如下:

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

哪里#define NUM_CHARS 20

我想将此结构写入二进制文件,因此我编写了两个函数来处理它:

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空白文件: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]元素。结果循环在某个不可预测的时间结束(即,如果它被清零,循环fread甚至不会是单个字符)。

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);
}

将使用未初始化(IOW,包含垃圾)person->name[]作为读取条件。并且可能会在此处读取错误的字节数。

之后以下

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

可以从文件中的错误位置读取整数,而不是从存储所述整数的位置读取整数。

解决方法是先读取一个字符,然后看看它是否'\0'存在。如果是,则字符串已被完全读取。如果不是,请继续阅读字符。

于 2013-04-15T04:35:57.853 回答