2013-04-15 64 views
0

我有一个Person STRUCT如下所示:fread无法读取一个unsigned int? [C]

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

问题是什么?

+0

您可能想更改'readPerson'中的注释:) :) –

回答

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'。如果是,则字符串已被完全读取。如果不是,请继续阅读角色。

+0

非常感谢:) – Billie

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前缀数据与长度的字符串的文件和读取许多字符。