简体   繁体   中英

Can I retrieve a struct from a file if so how?

So, I have this array of structs and a file in which I need to copy all information to the struct, can I do something like this? If not how could I do this?

#include <stdio.h>
#include <iostream>

using namespace std;

typedef struct{
      int x;
      int y;
      int z;
}coordinates;

int main(){
     coordinates coordinate[100];
     int i = 0;
     FILE *f;
     f = fopen("file.file","rb");

     if(!f){
        cout << "Error";
        return 0;
     }

     while(!feof(f)){
        fread(coordinate[i],sizeof(coordinates),1,f);
        i++;
     }
     return 0;
}

Well if you are using C++ (a completely different language to C by the way). You would simply define the input operator for the class.

struct coordinates{
      int x;
      int y;
      int z;

      // Personally I prefer serialization to a straight binary format.
      // It is easy to read and validate by a human
      // and not as brittle as a binary format when anything non
      // trivial happens.
      friend std::istream& operator>>(std::istream& str, coordinates& c)
      {
           return str >> c.x >> c.y >> c.z;
      }
      friend std::ostream& operator<<(std::ostream& str, coordinates const& c)
      {
           return str << c.x << " " << c.y << " " << c.z << " ";
      }
};

Now you can simply read structures from the file:

int main()
{
    std::ifstream data("file.file");

    coordinates  value;
    while(data >> value) {
       std::cout << "I have a set of cordinates\n";
    }

    // To read them into an array (a vector is a resizable array available in C++)
    std::vector<coordinates>   vec;
    std::copy(std::istream_iterator<coordinates>(file),
              std::istream_iterator<coordinates>(),
              std::back_inserter(vec));
}

How to write and read struct to binary file

    typedef struct{
      int x;
      int y;
      int z;
}coordinates;

Write to file

 FILE *f;
 f = fopen("test.dat","wb");

 for(int i = 0; i < 3; i++)
 {
    coordinates c;
    c.x = 0;
    c.y = 1;
    c.z= 2;
    fwrite(&c,sizeof(coordinates),1,f);
 }

read back to struct

 FILE *f;
 f = fopen("test.dat","rb");

 if(!f){
    cout << "Error";
    return 0;
 }

 coordinates c;
 while(fread(&c,sizeof(coordinates),1,f))
 {
    cout << c.x << " " << c.y << " "<< c.z << endl;
 }

Can I retrieve a struct from a file if so how?

Yes, you can. And you can do so using the read and write method. Open file and write the struct in binary mode. Then you can read from the file in binary mode using the read method.

You can use the write method to write a structure directly into a file in binary mode:

#include <iostream>
#include <fstream>
using namespace std;

struct Player {
    int age;
    int score;
};

int main()
{
    // You can write a structure directly into a file.
    // Create an instance of 'Player':
    Player rec;
    rec.age = 10;
    rec.score = 900;

    // Create out file
    fstream out_file("rec.bin",
                     ios::trunc | ios::binary | ios::in | ios::out
                     );

    // write the whole structure into the file
    out_file.write(reinterpret_cast<char*>( &rec ),
                   sizeof( rec )
                   );
}

We typecast to char* in the write and read method because the write method writes each character, each byte, one by one in order. Therefore we cast to char* to refer directly to this set of bytes.


And to read the file use the read method.
Below is an example reading the struct we just wrote into file rec.bin :

#include <iostream>
#include <fstream>
using namespace std;

struct Player {
    int age;
    int score;
};

int main()
{
    fstream in_file("rec.bin", ios::binary | ios::in | ios::out);

    Player in_rec;

    // read in age
    if ( !in_file.read(
          reinterpret_cast<char*>( &in_rec.age ),
          sizeof( in_rec.age )
    ))
    {
        // handle error
    }

    // read in score
    if ( !in_file.read(
          reinterpret_cast<char*>( &in_rec.score ),
          sizeof( in_rec.score )
    ))
    {
        // handle error
    }

    cout << in_rec.age << endl;
    cout << in_rec.score << endl;
}

Output:

10
900

Use delimiter in cord.txt file , so it will be easy to retrieve coordinates. My code will work good if you have text file in this format

cord.txt
4,5,6,
3,4,5,
7,8,9,   

Code according to above text file format is

typedef struct 
{
 int x;
 int y;
 int z;
}cord;

int main(int argc, char *argv[])
{
  cord cr[100];
  int i,j,k,l;
  j=0;k=0;l=0;
  char numbr[80];char numx[3];char numy[3];char numz[3];
  FILE *p;
  p = fopen("cord.txt","r");
  if(!p) { cout<<"File is missing\n"; }
  while(!feof(p))
  {
    for(i=0;i<80;i++)
    numbr[i]=NULL;
    for(i=0;i<3;i++)
    {
      numx[i]=NULL;
      numy[i]=NULL;
      numz[i]=NULL;
    }

   fgets(numbr,80,p);
   for(i=0;i<strlen(numbr);i++)
   {
      if(numbr[i]!=',')
      {
          if(k==0) {numx[l]=numbr[i];}
          else if(k==1) {numy[l]=numbr[i];}
          else if(k==2) {numz[l]=numbr[i];}
          l=l+1;    
      }
      else
      {
          l=0;
          if(k==0)
          {cr[j].x=atoi(numx);k=k+1;}
          else if(k==1)
          {cr[j].y=atoi(numy);k=k+1;}
          else if(k==2)
          {cr[j].z=atoi(numz);k=0;break;}
      }
   } 
   j=j+1;    
}
fclose(p);

for(i=0;i<j;i++)
 {   
   cout<<cr[i].x<<" "<<cr[i].y<<" "<<cr[i].z<<endl;
 }
cout<<"\n";
return EXIT_SUCCESS;
}

Output will be 4,5,6, 3,4,5, 7,8,9

This process of writing a struct to a FILE (or more generally, a stream) is called serialization . You can either do it in binary (this is pretty difficult) or in text. The following code performs text serialization on a similar data structure.

int read_coords (FILE * f, coord_t * result);
void write_coords (FILE * f, coord_t const * write_me);

/**
 * Reads a coordinate in the form x,y,z from f into result.
 * Returns non-zero on success
 */
int read_coords (FILE * f, coord_t * result)
{
  // Leading spaces in scanf cause us to elegantly handle weird whitespace
  int read = fscanf (f, " %d , %d , %d", &result->x, &result->y, &result->z);

  return read == 3;
}

void write_coords (FILE * f, coord_t const * result)
{
  fprintf (f, "%d, %d, %d\n", result->x, result->y, result->z);
}

int main (void)
{
  coord_t coord;

  printf ("Gimme Coords: ");
  if (read_coords (stdin, &coord))
  {
    printf ("I got: ");
    write_coords(stdout, &coord);
  }
  else
  {
    printf ("I had an error reading those coords.");
  }

  return 0;
}

PS, it looks like you're in a C class. I suggest avoiding for now. You can mix and match the different I/O methods in the same program, but it makes things confusing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM