我有一个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);
}
有什么问题?
答案 0 :(得分: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
前缀数据,并读取多个字符。
答案 1 :(得分: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'
。如果是,则完全读取字符串。如果不是,请继续阅读字符。