How do I write and read a struct pointer to a binary file?

81 Views Asked by At

Inside the structure, there are two int data type variables (nLife, nDamage).

Allocate this as much as MAX through the CreatCharacter() function, and insert values into nLife and nDamage.

Save the input values to a binary file.

The problem is that the saved file is not read with fread.

The curious thing is that reading the binary file immediately after creating it works fine, but there is a problem when only reading it.

Why is this problem occurring?

#define MAX 10

typedef struct
{
    int nDamage;
    int nLife;
} CHARACTER;
int CreatCharacter(CHARACTER* pCharMan[], int max)
{
    for (int i = 0; i < max; i++)
    {
        pCharMan[i] = (CHARACTER*)malloc(sizeof(CHARACTER));
        if (pCharMan[i] == NULL)
        {
            printf("fail\n");
            return 0;
        }

        pCharMan[i]->nLife = rand() % 51 + 50;
        pCharMan[i]->nDamage = 0;
    }

    return pCharMan;
}
void main()
{
    FILE* fp, *op;
    srand((unsigned)time(NULL));
    CHARACTER* pCharMan[MAX];
    CHARACTER* testStruct[MAX];

    CreatCharacter(pCharMan, MAX);
    // ①
    //fp = fopen("charinfo.bin", "wb");                 // If ① is not commented out, it works normally.
    //fwrite(pCharMan, sizeof(CHARACTER*), MAX, fp);
    //fclose(fp);

    // ②
    op = fopen("charinfo.bin", "rb");
    fread(testStruct, sizeof(CHARACTER*), MAX, op);     // When ① is commented out and only ② is executed, it fails.
    fclose(op);                                         // "charinfo.bin" exists.
}
3

There are 3 best solutions below

0
Chris Dodd On

The basic problem is that you're writing (just) the values of the pointers to the file, and not any of the data those pointers are pointing at -- the contents of the structs.

When you read it back, you just get a pointers, but those pointers don't point anywhere useful unless you do it in the same process that just wrote the pointers and the pointed at memory is still alive.

To do this usefully, you need to write out the contents of the structs and not any of the pointers (they are not useful to save as they are just private to the process that allocated them). To read it back, you need to allocate memory and then read the contents of the file into that memory.

3
cforler On

Here is a version of your program that writes the actual content of the structs into charinfo.bin and not their addresses. Furthermore, I took care of possible upcoming misalignment issues by packing the struct. Finally, I want to point out that I've maintained your naming conventions.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define MAX 10

typedef struct  __attribute__((__packed__)) {
    int nDamage;
    int nLife;
} CHARACTER;

void CreatCharacter(CHARACTER pCharMan[], int max) {
    for (int i = 0; i < max; i++)  {
        pCharMan[i].nLife = rand() % 51 + 50;
        pCharMan[i].nDamage = 0;
    }
}

int main() {
    srand((unsigned)time(NULL));
    CHARACTER *pCharMan    = malloc(sizeof(CHARACTER)*MAX);
    CHARACTER *testStruct  = malloc(sizeof(CHARACTER)*MAX);

    CreatCharacter(pCharMan, MAX);

    FILE *fp = fopen("charinfo.bin", "wb");
    fwrite(pCharMan, sizeof(CHARACTER), MAX, fp);
    fclose(fp);

    FILE *op = fopen("charinfo.bin", "rb");
    fread(testStruct, sizeof(CHARACTER), MAX, op);
    fclose(op);

    free(pCharMan);
    free(testStruct);
}
0
dkskfktldi On

Through the help above I found the answer.

#define MAX 10

typedef struct
{
    int nDamage;        // 공격 받은 정도
    int nLife;          // 생명
} CHARACTER;
int CreatCharacter(CHARACTER* pCharMan[], int max)
{
    for (int i = 0; i < max; i++)
    {
        pCharMan[i] = (CHARACTER*)malloc(sizeof(CHARACTER));
        if (pCharMan[i] == NULL)
        {
            printf("fail\n");
            return 0;
        }

        pCharMan[i]->nLife = rand() % 51 + 50;
        pCharMan[i]->nDamage = 0;
    }

    return pCharMan;
}
void main()
{
    FILE* fp, *op;
    srand((unsigned)time(NULL));
    CHARACTER* pCharMan[MAX];
    CHARACTER testStruct[MAX];
    int nDieHumanArr[MAX];

    CreatCharacter(pCharMan, MAX);
    // ①
    fp = fopen("charinfo.bin", "wb")
    for(int i=0; i<MAX; i++)
        fwrite(pCharMan[i], sizeof(CHARACTER), 1, fp);
    fclose(fp);
    
    // ②
    op = fopen("charinfo.bin", "rb");
    for(int i=0; i<MAX; i++)
        fread(&testStruct[i], sizeof(CHARACTER), 1, op);
    fclose(op);
}