Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flattening and dumping nested struct in C

How would one take a struct that contained multiple other structs, amongst bools, ints etc, and flatten it into say text form?

struct Person {
      struct eye_data eyes;
      struct nose_data nose;
      struct ear_data ear;
      int height;
      int weight;
      bool alive;
}

The scenario under which I am operating is: Say Person A wants to send over the struct that they created and used, over to Person B, but the individual configurations of the struct are too many to send over via email or something.

How would I write a dump function in order to be able to say, write all the struct information to a text file, which can later be parsed by another program to be read back in, to create a struct.

Also, how would this change if the struct Person contained pointers to structs, ie:

struct Person {
      struct eye_data *eyes;
      struct nose_data *nose;
      struct ear_data *ear;
      int *height;
      int *weight;
      bool alive;
}
like image 436
Surya Ram Avatar asked Dec 10 '25 17:12

Surya Ram


1 Answers

If the struct in question contains no pointers, and all of the structs contained within it contain no pointers (fixed size arrays are fine, including fixed size strings), you can write it to disk as is:

struct Person person;

// not shown: populate fields of person

int f = open("/tmp/personfile", O_WRONLY | O_CREAT);
if (f == -1) {
    perror("open failed");
    exit(1);
}
int written = write(f, &person, sizeof(person));
if (written == -1) {
    perror("write failed");
    close(f);
    exit(1);
} else if (written != sizeof(person)) {
    fprintf(stderr, "wrote %d bytes, expected %d\n", written, sizeof(person));
}
close(f);

Then to read it back in:

struct Person person;

int f = open("/tmp/personfile", O_RDONLY);
if (f == -1) {
    perror("open failed");
    exit(1);
}
int read = write(f, &person, sizeof(person));
if (read == -1) {
    perror("read failed");
    close(f);
    exit(1);
} else if (read != sizeof(person)) {
    fprintf(stderr, "read %d bytes, expected %d\n", written, sizeof(person));
}
close(f);

This is assuming you read it back in on the same machine it was written on. If it gets moved to another machine, you need to worry about the endian-ness of the numerical fields and differences in padding depending on the architecture of the source and destination machines.

Keep in mind, this is writing the struct in a binary format. If you want to write it in a readable text format, or if you have pointers to worry about, you need to use fprintf to write each field to the file and use fscanf to read them back in an order and manner you would define.

An abbreviated example:

// writing
fprintf(f,"%d\n%d\n%d\n",person.height,person.weight,(int)person.alive);

// reading
fscanf(f,"%d\n%d\n%d\n",&person.height,&person.weight,(int *)&person.alive);
like image 176
dbush Avatar answered Dec 12 '25 11:12

dbush



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!