3

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;
}
Surya Ram
  • 81
  • 1
  • 5
  • what you want is generic serialization, so look here: [Serialize Data Structures in C](http://stackoverflow.com/questions/371371/serialize-data-structures-in-c) –  Jul 23 '15 at 17:09

1 Answers1

1

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);
dbush
  • 205,898
  • 23
  • 218
  • 273
  • 1
    don't forget mentioning padding (as well as the sizes of some numerical types), which would already be different between `x86` and `x86_64` –  Jul 23 '15 at 17:26
  • @FelixPalmen Thanks. Edited. – dbush Jul 23 '15 at 17:33
  • for the case with pointers, how would you write the fields that are structs? i.e person->eyes, person->nose, and person->ears? – Surya Ram Jul 24 '15 at 16:18
  • @SuryaRam You'd have to dig into those structures and use `fprintf` and `fscanf` to read/write their individual components. – dbush Jul 24 '15 at 17:15