Fwrite/Fread 动态声明的结构 **
Fwrite/Fread a dynamically declared struct **
我想 fwrite()
然后 fread()
以下 struct **
其内存已动态分配。
该结构声明如下:
typedef struct {
int num;
char type;
Entity entity;
}Cell;
我声明一个单元格映射如下:
typedef struct {
char name[MAX_STRING];
int width;
int height;
Cell** map;
}Maze;
我分配地图的内存如下:
maze.map = (Cell **)malloc( width*sizeof( Cell* ));
for (int x = 0; x < width; x++ )
{
maze.map[x] = (Cell *)malloc(sizeof( Cell )*height);
}
问题是我不能 fwrite()
/fread()
我的结构是这样的,因为一旦我想 fread()
struct
,我就不会能够分配适当的内存 space。
所以我决定先写高度和宽度然后分配内存然后读取地图。
但是我找不到如何正确地书写或阅读我的地图。
我试过了:
for (int x = 0; x < maze.width; ++x) {
for (int y = 0; y < maze.height; ++y) {
fwrite(&maze.map[x][y], sizeof(Cell), 1, file);
}
}
但它不起作用,否则我不知道我应该如何 write/read 我的地图。
我尝试过的所有方法都没有返回我写的地图,或者它只是崩溃说我:进程已完成,退出代码为 -1073741819 (0xC0000005)
这里有两个写入和读取函数:
void SaveMaze(Maze maze){
FILE *file;
char file_name[MAX_STRING];
strcpy(file_name, maze.name);
strcat(file_name,".save");
file = fopen(file_name, "w");
if(file == NULL)
{
perror("Error Fopen : ");
return ;
}
fwrite(maze.name,sizeof(maze.name), 1, file);
fwrite(&maze.height,sizeof(maze.height), 1, file);
fwrite(&maze.width,sizeof(maze.width), 1, file);
for (int x = 0; x < maze.width; ++x) {
fwrite(&maze.map[x], sizeof(Cell), maze.height, file);
}
// Close the file
fclose(file);
}
Maze LoadMaze(char * name){
FILE *file;
Maze maze;
char file_name[MAX_STRING];
strcpy(file_name, name);
strcat(file_name,".save");
file = fopen(file_name, "r");
if(file == NULL) {
perror("Error Fopen : ");
return maze;
}
fread(maze.name,sizeof(maze.name), 1, file);
fread(&maze.height,sizeof(maze.height), 1, file);
fread(&maze.width,sizeof(maze.width), 1, file);
maze.map = (Cell **)malloc( maze.width*sizeof( Cell* ));
for (int x = 0; x < maze.width; x++ )
{
maze.map[x] = (Cell *)malloc(sizeof( Cell )*maze.height);
}
for (int x = 0; x < maze.width; ++x) {
fread(&maze.map[x], sizeof(Cell), maze.height, file);
}
printf("%c",maze.map[0][0].num);
fclose (file);
return maze;
}
int main() {
int choice;
int width,height;
char name[MAX_STRING],file_name[MAX_STRING];
Maze maze;
do{
printf("1. Generate a new Maze\n");
printf("2. Load an existing maze\n");
printf("3. Play\n");
printf("4. Exit\n");
scanf("%d",&choice);
fflush(stdin);
if(choice == 1){
do {
printf("What is the width of your maze (Odd number only)\n");
scanf("%d", &width);
fflush(stdin);
} while (width%2 == 0);
do {
printf("What is the height of your maze (Odd number only)\n");
scanf("%d", &height);
fflush(stdin);
} while (height%2 == 0);
printf("What is the name of the maze\n");
fgets(name,sizeof(name),stdin);
// Remove the \n from the name
name[strcspn(name, "\n")] = 0;
fflush(stdin);
maze = CreateMaze(width,height,name);
InitialyzeMaze(&maze);
BuildMaze(&maze);
fflush(stdin);
SaveMaze(maze);
}else if(choice == 2){
//system("clear");
//system("ls *.{save}");
printf("What is the name of the maze you want to load ?\n");
fgets(file_name,sizeof(file_name),stdin);
// Remove the \n from the filename
file_name[strcspn(file_name, "\n")] = 0;
fflush(stdin);
maze = LoadMaze(file_name);
}else if(choice == 3){
Play(&maze);
}
}while(choice != 4);
}
由于每个迷宫项目 (maze.map[X]) 中的元素都是连续的,并且是预先分配的,因此您可以使用单个 fwrite 调用写入每个 'maze' 项目:
for (int x = 0; x < maze.width; ++x) {
fwrite(&maze.map[x], sizeof(Cell), maze.height, file);
}
走这条路,你可以用fread代替fwrite来读取元素。
旁注:通常最好使用 calloc(count, sizeof(...)),而不是 malloc(count*sizeof) - 它会将分配的内存初始化为零。
您在数据文件中混合了文本数据和二进制数据。
当您写下姓名、高度和宽度时:
fprintf(file,"%s",maze.name);
fwrite(&maze.height,sizeof(maze.height), 1, file);
fwrite(&maze.width,sizeof(maze.width), 1, file);
这会输出一系列名称字符(假设为 "my_maze"),紧接着是 sizeof(int)
字节的高度和 sizeof(int)
字节的宽度。
所以名称是 7 个字节,高度是 4 个字节(假设 int
是 4 个字节),宽度是 4 个字节。
现在当你回读时:
fscanf(file,"%s",maze.name);
fread(&maze.height,sizeof(maze.height), 1, file);
fread(&maze.width,sizeof(maze.width), 1, file);
fscanf
的 %s
格式说明符读取字符,直到遇到空格。前 7 个字符被正确读取,但紧接着是 height
的二进制数据,那么它在哪里停止读取?结果是您很可能读取的字节数比您缩进的字节数多,现在您读取的其余部分不在正确的位置。
您可以通过使用 fwrite
:
编写整个 name
字段来消除 fprintf
和 fscanf
来解决此问题
fwrite(maze.name,sizeof(maze.name), 1, file);
并用 fread
阅读:
fread(maze.name,sizeof(maze.name), 1, file);
你这里也有问题:
fwrite(&maze.map[x], sizeof(Cell), maze.height, file);
这里:
fread(&maze.map[x], sizeof(Cell), maze.height, file);
&maze.map[x]
不是你分配的内存地址而是它指向的指针的地址。因此,不是 reading/writing 为每行单元格预留的内存,而是 reading/writing 用于每个单元格的指针行的内存。当你这样做时,你最终 reading/writing 超过了分配内存的末尾。
去掉此处的寻址运算符,将指针传递给您所在的实际内存 reading/writing:
fwrite(maze.map[x], sizeof(Cell), maze.height, file);
...
fread(maze.map[x], sizeof(Cell), maze.height, file);
我想 fwrite()
然后 fread()
以下 struct **
其内存已动态分配。
该结构声明如下:
typedef struct {
int num;
char type;
Entity entity;
}Cell;
我声明一个单元格映射如下:
typedef struct {
char name[MAX_STRING];
int width;
int height;
Cell** map;
}Maze;
我分配地图的内存如下:
maze.map = (Cell **)malloc( width*sizeof( Cell* ));
for (int x = 0; x < width; x++ )
{
maze.map[x] = (Cell *)malloc(sizeof( Cell )*height);
}
问题是我不能 fwrite()
/fread()
我的结构是这样的,因为一旦我想 fread()
struct
,我就不会能够分配适当的内存 space。
所以我决定先写高度和宽度然后分配内存然后读取地图。
但是我找不到如何正确地书写或阅读我的地图。
我试过了:
for (int x = 0; x < maze.width; ++x) {
for (int y = 0; y < maze.height; ++y) {
fwrite(&maze.map[x][y], sizeof(Cell), 1, file);
}
}
但它不起作用,否则我不知道我应该如何 write/read 我的地图。
我尝试过的所有方法都没有返回我写的地图,或者它只是崩溃说我:进程已完成,退出代码为 -1073741819 (0xC0000005)
这里有两个写入和读取函数:
void SaveMaze(Maze maze){
FILE *file;
char file_name[MAX_STRING];
strcpy(file_name, maze.name);
strcat(file_name,".save");
file = fopen(file_name, "w");
if(file == NULL)
{
perror("Error Fopen : ");
return ;
}
fwrite(maze.name,sizeof(maze.name), 1, file);
fwrite(&maze.height,sizeof(maze.height), 1, file);
fwrite(&maze.width,sizeof(maze.width), 1, file);
for (int x = 0; x < maze.width; ++x) {
fwrite(&maze.map[x], sizeof(Cell), maze.height, file);
}
// Close the file
fclose(file);
}
Maze LoadMaze(char * name){
FILE *file;
Maze maze;
char file_name[MAX_STRING];
strcpy(file_name, name);
strcat(file_name,".save");
file = fopen(file_name, "r");
if(file == NULL) {
perror("Error Fopen : ");
return maze;
}
fread(maze.name,sizeof(maze.name), 1, file);
fread(&maze.height,sizeof(maze.height), 1, file);
fread(&maze.width,sizeof(maze.width), 1, file);
maze.map = (Cell **)malloc( maze.width*sizeof( Cell* ));
for (int x = 0; x < maze.width; x++ )
{
maze.map[x] = (Cell *)malloc(sizeof( Cell )*maze.height);
}
for (int x = 0; x < maze.width; ++x) {
fread(&maze.map[x], sizeof(Cell), maze.height, file);
}
printf("%c",maze.map[0][0].num);
fclose (file);
return maze;
}
int main() {
int choice;
int width,height;
char name[MAX_STRING],file_name[MAX_STRING];
Maze maze;
do{
printf("1. Generate a new Maze\n");
printf("2. Load an existing maze\n");
printf("3. Play\n");
printf("4. Exit\n");
scanf("%d",&choice);
fflush(stdin);
if(choice == 1){
do {
printf("What is the width of your maze (Odd number only)\n");
scanf("%d", &width);
fflush(stdin);
} while (width%2 == 0);
do {
printf("What is the height of your maze (Odd number only)\n");
scanf("%d", &height);
fflush(stdin);
} while (height%2 == 0);
printf("What is the name of the maze\n");
fgets(name,sizeof(name),stdin);
// Remove the \n from the name
name[strcspn(name, "\n")] = 0;
fflush(stdin);
maze = CreateMaze(width,height,name);
InitialyzeMaze(&maze);
BuildMaze(&maze);
fflush(stdin);
SaveMaze(maze);
}else if(choice == 2){
//system("clear");
//system("ls *.{save}");
printf("What is the name of the maze you want to load ?\n");
fgets(file_name,sizeof(file_name),stdin);
// Remove the \n from the filename
file_name[strcspn(file_name, "\n")] = 0;
fflush(stdin);
maze = LoadMaze(file_name);
}else if(choice == 3){
Play(&maze);
}
}while(choice != 4);
}
由于每个迷宫项目 (maze.map[X]) 中的元素都是连续的,并且是预先分配的,因此您可以使用单个 fwrite 调用写入每个 'maze' 项目:
for (int x = 0; x < maze.width; ++x) {
fwrite(&maze.map[x], sizeof(Cell), maze.height, file);
}
走这条路,你可以用fread代替fwrite来读取元素。
旁注:通常最好使用 calloc(count, sizeof(...)),而不是 malloc(count*sizeof) - 它会将分配的内存初始化为零。
您在数据文件中混合了文本数据和二进制数据。
当您写下姓名、高度和宽度时:
fprintf(file,"%s",maze.name);
fwrite(&maze.height,sizeof(maze.height), 1, file);
fwrite(&maze.width,sizeof(maze.width), 1, file);
这会输出一系列名称字符(假设为 "my_maze"),紧接着是 sizeof(int)
字节的高度和 sizeof(int)
字节的宽度。
所以名称是 7 个字节,高度是 4 个字节(假设 int
是 4 个字节),宽度是 4 个字节。
现在当你回读时:
fscanf(file,"%s",maze.name);
fread(&maze.height,sizeof(maze.height), 1, file);
fread(&maze.width,sizeof(maze.width), 1, file);
fscanf
的 %s
格式说明符读取字符,直到遇到空格。前 7 个字符被正确读取,但紧接着是 height
的二进制数据,那么它在哪里停止读取?结果是您很可能读取的字节数比您缩进的字节数多,现在您读取的其余部分不在正确的位置。
您可以通过使用 fwrite
:
name
字段来消除 fprintf
和 fscanf
来解决此问题
fwrite(maze.name,sizeof(maze.name), 1, file);
并用 fread
阅读:
fread(maze.name,sizeof(maze.name), 1, file);
你这里也有问题:
fwrite(&maze.map[x], sizeof(Cell), maze.height, file);
这里:
fread(&maze.map[x], sizeof(Cell), maze.height, file);
&maze.map[x]
不是你分配的内存地址而是它指向的指针的地址。因此,不是 reading/writing 为每行单元格预留的内存,而是 reading/writing 用于每个单元格的指针行的内存。当你这样做时,你最终 reading/writing 超过了分配内存的末尾。
去掉此处的寻址运算符,将指针传递给您所在的实际内存 reading/writing:
fwrite(maze.map[x], sizeof(Cell), maze.height, file);
...
fread(maze.map[x], sizeof(Cell), maze.height, file);