Save struct with pointer members in file

北城余情 提交于 2020-08-10 20:12:17

问题


I'm trying to save a struct into a .dat file and read it back in later.

struct myStruct{
  char **one;
  mytype **two;
  mytype2 *three;
}

With an assigning function:

struct MyStruct get_struct() = {
char **pi = ...;
mytype **pa = ...;
mytype2 **po = ...;
MyStruct n = {pi, pa, po};
return n;
}

I originally tried to save this struct into a .dat file by doing this:

struct MyStruct s = get_struct();
myoutfile = fopen("file.dat", "w");
if (myoutfile == NULL) {
    fprintf(stderr, "\nError opend file\n");
    exit(1);
}
fwrite(&s, sizeof(struct MyStruct), 1, myoutfile);
fclose(myoutfile);

and read it back in with:

fread(&t, sizeof(struct MyStruct), 1, myinfile)

Now I learned, that this does not work (segmentation error), because I only save the location where the pointer points to, not the actual thing.

Now my question is, how can I do it properly? I have found some solutions for C++ but I need to stay in C.

EDIT: Later on, I want to call a function which looks like this:

void work_with_struct(MyStruct s){
   char ** xone = s.one;
   mytype **xtwo = s.two;
   mytype2 *xthree = s.three;
}

This post is related to this post, but as I could specify my mistake now, asking in a new post makes more sense to me.


回答1:


As always in programming, you break up the task to smaller chunks, and break up smaller chunks to yet smaller chunks, until every chunk is easy.

int saveMyStruct (struct myStruct* myStruct, FILE* file) {
   // what do I do here?!?!
   // well it has three members
   // so treat each one in sequence
   int result;
   result = saveStringArray(myStruct->one, file);
   if (result >= 0)
     result = saveMyTypeArray (myStruct->two, file);
   if (result >= 0)
     result = saveMyType (myStruct->three, file);
   return result;
}

Note how the status is checked all the time. If you work with files, you need to check the status all the time.

What next? You need to write three functions mentioned above.

 saveStringArray(char** stringArray, FILE* file)
 {
     // first save the length of the array, then save each individual string
     int length = getStringArrayLength(stringArray);
     int result = fwrite(&length, sizeof(length), 1, file);
     if (result != 1)
        return -1;
     for (i = 0; i < length; ++i)
     {
        result = saveString(stringArray[i], file);
        if (result < 0)
           return -1;
     }
     return i;            
 }

And so on and so forth. I presume your array of pointers is NULL-terminated; if not, you need to have some other way to know its length.

Note how array length is always saved before array elements. This is because you will need to read your array later, and you will need to know where to stop. It will also be easy to allocate your array when you read it.




回答2:


You do it by saving the actual data that you need. So in this example I can see that you want to store this:

struct myStruct{
  char **one;
  mytype **two;
  mytype2 *three;
}

And you also have this function

struct MyStruct get_struct() = {
    char **pi = ...;
    mytype **pa = ...;
    mytype2 **po = ...;
    MyStruct n = {pi, pa, po};
    return n;
}

Now in order to save the actual data you would need to derefrence the pointers and change your struct accordingly.

So this is how your struct would look

struct myStruct{
  char one[1000]; // change 1000 to the maximum size your save data can be
  mytype two;
  mytype2 three;
}

And your get_struct() function would need to look like this

struct MyStruct get_struct() {
    char * one = *(pointer);
    mytype two = **(pointer);
    mytype2 three = *(pointer);
    struct MyStruct n;
    strcpy(n.one, one);
    n.two = two;
    n.three = three;
    return n;
}

I am unsure how the rest of your code looks so you might need to change the get_struct() functions level of dereferencing. But you can get the general idea from this.

EDIT This is your current work_with_stuct().

void work_with_struct(MyStruct s){
   char ** xone = s.one;
   mytype **xtwo = s.two;
   mytype2 *xthree = s.three;
}

The problem is that you are treating actual data like a pointer. What you need to do is save the addresses of the data you read from the struct into your pointers. Something like this:

void work_with_struct(struct MyStruct s){
  char * xone = s.one;
  int *xtwo = &s.two;
  int *xthree = &s.three;
  // do something with it
 }

Also this is a working example of saving data like this

#include <stdio.h>
#include <string.h>

struct MyStruct{
  char  test[1000];
  int a;
  int b;
};

int ** p1;
int * p2;

struct MyStruct get_struct() {
    char * pi = "aasda";
    int pa = **p1;
    int po = *p2;
    struct MyStruct n;
    strcpy(n.test, pi);
    n.a = pa;
    n.b = po;
    return n;
}

void work_with_struct(struct MyStruct s){
  char * xone = s.test;
  int *xtwo = &s.a;
  int *xthree = &s.b;
  puts(xone);
  printf("A: %d\n", *xtwo);
  printf("B: %d\n", *xthree);
 }

int main(void) {
  
  int a = 5;
  int* pa = &a;
  p1 = &pa;
  
  int b = 3;
  p2 = &b;

  struct MyStruct s = get_struct();
    FILE * myoutfile = fopen("file.dat", "w");
  if (myoutfile == NULL) {
      fprintf(stderr, "\nError opening file\n");
      return 1;
  }
  fwrite(&s, sizeof(struct MyStruct), 1, myoutfile);
  fclose(myoutfile);
  struct MyStruct t;
  FILE * myinfile = fopen("file.dat", "r");
  fread(&t, sizeof(struct MyStruct), 1, myinfile);
  work_with_struct(t);

  return 0;
}


来源:https://stackoverflow.com/questions/63171920/save-struct-with-pointer-members-in-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!