问题
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