#include <stdio.h>
#include <stdlib.h>
struct birdhome{
int area;
int heightcm;
int feederquantity;
char hasNest[6];
};
struct bird{
char isRinged[6];
char nameSpecies[50];
int birdAgeMonths;
struct BirdHome *hom;
char gender[7];
};
int save(char * filename, struct bird *st, int n);
int load(char * filename);
int main(void)
{
char * filename = "birds.dat";
struct bird birds[] = { "True","sparrow",3,10,20,2,"False","Male","False","crane",24,50,100,6,"True","Female","False","False","griffin",10,100,80,1,"False","Male" };
int n = sizeof(struct bird) / sizeof(birds[0]);
save(filename, birds, n);
load(filename);
return 0;
}
int save(char * filename, struct bird * st, int n)
{
FILE * fp;
char *c;
int size = n * sizeof(struct bird);
if ((fp = fopen(filename, "wb")) == NULL)
{
perror("Error occured while opening file");
return 1;
}
c = (char *)&n;
for (int i = 0; i<sizeof(int); i++)
{
putc(*c++, fp);
}
c = (char *)st;
for (int i = 0; i < size; i++)
{
putc(*c, fp);
c++;
}
fclose(fp);
return 0;
}
int load(char * filename){
FILE * fp;
char *c;
int m = sizeof(int);
int n, i;
int *pti = (int *)malloc(m);
if ((fp = fopen(filename, "r")) == NULL)
{
perror("Error occured while opening file");
return 1;
}
c = (char *)pti;
while (m>0)
{
i = getc(fp);
if (i == EOF) break;
*c = i;
c++;
m--;
}
n = *pti;
struct bird * ptr = (struct bird *) malloc(n * sizeof(struct bird));
c = (char *)ptr;
while ((i= getc(fp))!=EOF)
{
*c = i;
c++;
}
printf("n%d birds in the file storednn", n);
for (int k = 0; k<n; k++)
{
printf("%-10d %-6s %-50s %-24d %-100d %-100d %-10d %-10s %-10s n", k + 1, (ptr + k)->isRinged, (ptr + k)->nameSpecies,(ptr + k)->birdAgeMonths,(ptr + k)->hom.area,(ptr + k)->hom.heightcm,(ptr + k)->hom.feederquantity,(ptr + k)->hom.hasNest,(ptr + k)->gender);
}
程序理论上是可以运行的。问题在于load
函数中的printf
。
错误提示struct Birdhome
中所有的结构类型都是a我应该使用->
而不是.
。
但是当我这样做的时候,它说我应该把.
改成->
。
问题是bird.hom
是一个指针。保存指向文件的指针并不是一件有用的事情,因为内存地址会随着进程的不同而变化。它也没有保存BirdHome
结构的内容。并且birds
的初始化不起作用,因为不能将间接结构体的成员初始化为主结构体的一部分。
你应该将它声明为一个嵌入式结构体,而不是指针。
struct bird{
char isRinged[6];
char nameSpecies[50];
int birdAgeMonths;
struct BirdHome hom;
char gender[7];
};
如果你想要一个动态大小的home数组,或者你想让多个bird引用同一个BirdHome
结构体,那么将它声明为一个指针是很有用的。如果这是您真正需要的,则需要重新设计save和load函数,以便它们解引用指针并保存指针指向的内容。如果你有一个动态大小的BirdHome
数组,你需要在bird
中包含数组的大小。
代码中的其他错误:
在birds
的初始化列表中有一个额外的"False"
。应该是:
struct bird birds[] = { "True","sparrow",3,10,20,2,"False","Male","False","crane",24,50,100,6,"True","Female","False","griffin",10,100,80,1,"False","Male" };
你计算的n
不正确。应该是:
int n = sizeof(birds) / sizeof(birds[0]);