-1

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.
}
dkskfktldi
  • 41
  • 1
  • 6
  • What exactly fails (could you describe the expected and the actual behavior)? Can you tell us what error is being returned? – Simon Doppler Aug 15 '23 at 09:17
  • The values of nLife and nDamage of pCharMan created through CreatCharacter() should be saved to nLife and nDamage of testStruct. When ① was not commented out, it was confirmed that pCharMan's nLife and nDamage values were stored in testStruct's nLife and nDamage. However, if ① is commented out, pCharMan's nLife and nDamage values are not saved in testStruct's nLife and nDamage. ("charinfo.bin" exists.) – dkskfktldi Aug 15 '23 at 09:26
  • There are 10 separate calls to `malloc()` allocating 10 distinct character attribute structures. The code appears to (incorrectly) attempt to write out **1**, then (incorrectly) read back **10**... The best way to learn about pointers and arrays is to draw boxes and connecting arrows on a piece of paper while explaining the program step-by-step to your rubber duck... You'll find, amongst other things, the `&` in the write and read is not doing what you want... (PS: check return codes from `fopen()`, `fwrite()` and `fread()`... Time to study the manual...) – Fe2O3 Aug 15 '23 at 09:35
  • As you said, I checked and there was a problem with reading and writing. So, I modified the code to write and read 10 by modifying writing 1 and reading 10. Certainly, there is no problem with reading and writing this time. But the result is still the same. I read the description of what fopen(), fwrite() and fread() return, but I still don't know the problem... – dkskfktldi Aug 15 '23 at 10:56

3 Answers3

3

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.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
1

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);
}
cforler
  • 179
  • 1
  • 7
  • I realized that I was storing the place where the pointer was pointing, not the contents of the structure. Certainly following your code gave me the results I was looking for. But I have to do dynamic allocation in CreatCharacter(). So, in my existing code, I gave a loop statement and used ```fwrite(pCharMan[i], sizeof(CHARACTER*), MAX, fp);```. (i repeats as much as MAX - 1.) In case of fread(), it was written as ```fread(testStruct, sizeof(CHARACTER*), MAX, op);```. – dkskfktldi Aug 15 '23 at 13:49
  • However, in this case, only the first one reads correctly, and then it becomes garbled. When I thought about it, it seems that the contents of the structure were entered in fwrite(), but why doesn't it work properly? – dkskfktldi Aug 15 '23 at 13:49
  • You can write the i-th character struct with the following command: ```fwrite(&(pCharMan[i]), sizeof(CHARACTER), 1, fp)```; Note that ```sizeof(CHARACTER*)``` returns the size of the pointer that points to CHARACTER and ```sizeof(CHARACTER)``` returns the size of the struct. – cforler Aug 15 '23 at 14:37
0

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);
}
dkskfktldi
  • 41
  • 1
  • 6