tags:

views:

1068

answers:

5

I'd like to save a struct in a file. I'd like to realize a function which makes this work. I tried this code but it didn't work.

struct utilisateur   // enregestrement pour sauvegarder les details de l utilisateur
{
 char nom[20];
 char prenom[20];
 int place;
 char depart[20];
 char arrive[20];
 char sexe;
 int nwagon;
};

struct utilisateur utilis;
struct utilisateur *Table[48];

void crea_fich(struct utilisateur *Tutilis)
// creation un fichier, vous introduiez le nom, et le sotcker par enreg
{
    FILE *f;
    if (f!==0)
    {
         printf("error in the name of file \n");
         exit(1);
    }
    if (f=fopen(futilis,"w")==Null){
         fprint("We can't creat file \n");
         exit(1);
    }
    else{
        f=fopen("futilis.dat","wb");
        fwrite(Tutilis ,sizeof(utilisateur),1,f);
    }
}
A: 

I'd look over the symbol names first, like Null and fprint, not to mention that weird /0. As an additional thought, you should close the file after writing to make sure it gets flushed to disk, and double check that futilis variable to be a char* that contains a valid, writeable path.

Blindy
+4  A: 

No. You need to write out your data members individually, one at a time. You should not just blindly copy the memory representation of your struct into the file output buffer (which it is clear you are trying to do). Writing files that way will cause the files to non-portable (they won't be readable except on the platform that they were written), because of the endian-ness and the platform-specific padding of the struct elements.

Michael Aaron Safyan
well, he never said that portability was required, so there is nothing explicitly wrong with the notion of writing structs directly to the filesystem. I've know one or two language front-ends, for instance, that did exactly that with their parsed-tree data.
Mike Ellery
+1  A: 

Just a simple example :)

// your struct
struct Data
{
    int first;
    double second;
    char third[10];
};

Then write the struct!

struct Data data = {22, 4.0, "Hi"};
FILE* output;

output = fopen("Data.dat", "wb");

fwrite(&data, sizeof(data), 1, output);

fclose(output);

Finally read the data from the file you created!

struct Data data;
FILE* input;

input = fopen("Data.dat", "rb");

fread(&data, sizeof(data), 1, input);

// you got the data from the file!

fclose(input);

Binary files are nightmares if not written and read wisely. You have to take care of a lot of things about the architecture where the file was created and where will it be read. Endianess and size of variables are the most important. Also, If you have pointers inside your struct, the pointer that will be written to the file not the actual data where the pointer points to. Sorry, I didn't edit your code because it is full of compilation errors :)

I deleted my first answer because it was so wrong, sorry :)

AraK
This is just a nitpick, but you opened the file in "r" mode and wrote binary data ("r" is text, "rb" is binary). While this won't make a difference in linux, it might when this code is run in windows, FYI.
James
Sorry I am not a good C man :) I use C++ regularly.
AraK
+3  A: 

Try this, and then if that's not doing what you want, try explaining how it differs from what you want.

void crea_fich(struct utilisateur *Tutilis)
{
   FILE *f;
   size_t nwritten;

   f = fopen("futilis.dat","wb");

   if (f == NULL)
   {
      fprintf(stderr, "Cannot open file for writing.\n");
      exit(1);
   }

   nwritten = fwrite(Tutilis, sizeof Tutilis[0], 1, f);
   fclose(f);

   if (nwritten < 1)
   {
      fprintf(stderr, "Writing to file failed.\n");
      exit(1);
   }
}
caf
This (and the converse function using `fread()`) will work on any one machine architecture; it is not, however, portable to other architectures. This probably doesn't matter in the context, but it is worth mentioning for completeness.
Jonathan Leffler
+2  A: 

Michael S is right; using fwrite with a struct is wildly nonportable. But let's assume you don't care about that and you want something easy to write that will work.

The problem in your code is that you've broken the Golden Rule of sizeof: never use sizeof with a type name. Instead you should use sizeof with an lvalue, and almost always with the dereference of another argument. Thus

Tutilis = malloc (sizeof (*Tutilis));
  ...
fwrite(Tutilis, sizeof (*Tutilis), 1, f);

If you follow this recipe it's much harder to get the size wrong.

Norman Ramsey
I would hardly call that a "Golden Rule." Tons of code out and about today calls sizeof on non lvalues. Microsoft's own MSDN website shows how to call it on a type-name. http://msdn.microsoft.com/en-us/library/4s7x1k91.aspx
James
@James: It's perfectly legal, it's just not a very robust programming practice. You wouldn't jump off a cliff just because MSDN showed you how, would you? :-)
Norman Ramsey