我想保存一个包含我用作动态数组的指针的结构但是当我加载struct和malloc这个指针时,它会失败。
我有三个结构(Orientation,ShipType,Status和PlayerType是枚举,你可以用Int替换它们):
struct Map
{
int width, height;
int* cases;
};
typedef struct Map Map;
struct Ship
{
int x, y, length, firstShoot, color;
int hasBeenDiscovered;
Orientation orientation;
ShipType type;
Status status;
};
typedef struct Ship Ship;
struct Player
{
int activeShips;
Map map[2];
char lastMoves[5][128];
Ship ships[10];
PlayerType type;
int shipcolor[4];
int color;
};
typedef struct Player Player;
我声明了一个2 Player的数组,如下所示:Player players[2];
并初始化它们的属性。然后我想将结构保存在一个文件中,以便以后加载它。
另外,我使用Map结构作为2d动态数组,使用四个函数:
void mallocMap(Map* map, int width, int height)
{
map->cases = malloc(sizeof(int) * width * height);
map->width = width;
map->height = height;
if (map->cases == NULL)
{
printf("Erreur d'allocation de memoire\n");
exit(0);
}
}
void freeMap(Map* map)
{
free(map->cases);
}
int getMapValue(Map map, int x, int y)
{
return *(map.cases + y*map.width + x);
}
void setMapValue(Map* map, int value, int x, int y)
{
*(map->cases + y*map->width + x) = value;
}
因此,当我存储结构时,map.cases
只是一个指针,我需要将值分别存储在其地址中,如下所示:
int save(Player players[2])
{
int* i;
FILE* file = NULL;
file = fopen("save.txt","w+");
if (file != NULL)
{
fwrite(players, sizeof(Player), 2, file);
fwrite(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fwrite(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fwrite(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fwrite(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
}
else
{
// error
}
fclose(file);
return 1;
}
每个玩家都有2张地图,所以最后有4张地图存放。
问题出在我的load()
函数中:
int load(Player players[2])
{
FILE* file = NULL;
file = fopen("save.txt","r");
if (file != NULL)
{
int *i;
fread(players, sizeof(Player), 2, file);
mallocMap(&players[0].map[0], players[0].map[0].width, players[0].map[0].height);
mallocMap(&players[0].map[1], players[0].map[1].width, players[0].map[1].height);
mallocMap(&players[1].map[0], players[1].map[0].width, players[1].map[0].height);
mallocMap(&players[1].map[1], players[1].map[1].width, players[1].map[1].height);
fread(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fread(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fread(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fread(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
}
else
{
// error
}
fclose(file);
return 1;
}
当我拨打mapAlloc()
时,它无法分配内存和exit(0)
;我的程序停止了。
答案 0 :(得分:1)
您宣布load
功能的方式并不合适:
int load(Player* players[2])
这需要一个指向Player 的指针数组,而你的save
例程需要一个Player数组(即Player players[2]
)。您可能需要将其更改为:
int load(Player players[2])
您还要将值重新读回错误的地址:
for(i = players[0]->map[0].cases; i < players[0]->map[0].cases + players[0]->map[0].width * players[0]->map[0].height; i++)
fread(&i, sizeof(int), 1, file);
您已将fread
的地址传递给i
。这意味着您正在int
中阅读并将其存储在i
中,这是一个本地int *
而不您想要的动态分配数组写信给。
在此处删除地址运算符并直接传递i
,就像使用fwrite
fread(i, sizeof(int), 1, file);
这会将您读入的int
写入数组。
此外,这里不需要使用循环来读/写单个int。只需执行一次读/写传递数值即可读/写。
所以储蓄将是:
fwrite(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fwrite(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fwrite(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fwrite(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
加载将是:
fread(players[0].map[0].cases, sizeof(int), players[0].map[0].width * players[0].map[0].height, file);
fread(players[0].map[1].cases, sizeof(int), players[0].map[1].width * players[0].map[1].height, file);
fread(players[1].map[0].cases, sizeof(int), players[1].map[0].width * players[1].map[0].height, file);
fread(players[1].map[1].cases, sizeof(int), players[1].map[1].width * players[1].map[1].height, file);
编译代码时,不应该有任何警告。如果有,你可能做错了你需要解决的问题。