views:

94

answers:

5

Here is data structure w/ variables:

struct Part_record
{
    char id_no[3];
    int qoh;
    string desc;
    double price:
};
---
(Using "cin" to input data)
---
Part_record null_part = {"  ", 0,"                         ",0.0};
---
---
file.seekg( -(long)sizeof(Part_record), ios::cur);
file.write( ( char *)&part, sizeof(Part_record) );

The three variables, qoh, Id_no & price, write out correctly, but the "desc" variable is not right. Do I need to initialize Part_record some other way? It should be 20 characters in length.

If you have enough info here, pls share your advice,thanks.

+3  A: 

std::string keeps its data in dynamically allocated memory, not in structure Part_record.

Kirill V. Lyadvinsky
A: 

string data won't get written; you should use a char[20] instead, because string is a dynamic class which does not have a fixed size (technically it has a fixed size but contains a pointer to a dynamic, growable character array).

I say char[20] because you mentioned that the string should be 20 characters. However, be sure to include an extra character for the terminating null byte. Also, your example contained a string with 25 spaces, so in that case you'd want a char[26].

If you will have strings of any size and you don't know the max size, then you'll have to do something more complex than simply having all of your data in a struct.

Eli Courtwright
The poster should read and write each element individually rather than using block I/O with the entire structure. There are many holes in the block I/O, and a field with `std::string` is one of them. For faster I/O, the members of the structure can be copied *contiguously* into a buffer, then the buffer can be written as one block. Another hole in the OP's design is the fact that the compile can insert padding between fields.
Thomas Matthews
A: 

std::string contains pointers to the real character data, and you're serializing the raw structure, i.e. the pointers.

Write each variable separately, with special handling for the string (i.e. use desc.data() and desc.size() to get the ptr and length of the string's data.)

Marcus Lindblom
+1  A: 

You can't write std::string objects (or any of the STL containers) to a file in this way. They contain internal pointers to their data which is allocated dynamically; you'll wind up writing pointer addresses to your file, instead of the contents of the string.

I'd recommend using the iostream library if you need to write std::string data to a file. Failing that, you can access the character data directly with part.desc[0] to achieve something similar to what you're attempting:

fwrite(&part.desc[0], part.desc.size());
meagar
A: 

Write the individual members to your output stream, or have the structure do this, or write the individual members to a buffer:

struct Part_record
{
    char id_no[3];
    int qoh;
    string desc;
    double price:
// Block I/O methods
    size_t  Size_On_Stream(void) const
    {
      size_t size = 0;
      size = sizeof(id_no) + sizeof(goh) + sizeof(price);
      size += descr.length() + 1; // +1 for terminating null character
      return size;
    }
    void  Store_To_Buffer(unsigned char *& p_buffer) const
    {
       std::copy((unsigned char *)&id_no[0], (unsigned char *)&id_no[3], p_buffer);
       p_buffer += sizeof(id_no);
       std::copy((unsigned char *)&goh, (unsigned char *)(&goh) + sizeof(goh), p_buffer);
       p_buffer += sizeof(goh);
       std::copy((unsigned char *)&price, (unsigned char *)(&price) + sizeof(price), p_buffer);
       p_buffer += sizeof(price);
       strcpy(p_buffer, descr.str());
       p_buffer += descr.length();
       *p_buffer = 0x00;
       ++p_buffer;
       return;
     }
     void Write_To_Stream(ostream& output) const
     {
       size_t buffer_size = Size_On_Stream();
       unsigned char * buffer = new unsigned char [buffer_size];
       unsigned char * p_buffer = buffer;
       Store_To_Buffer(p_buffer);
       output.write((char *)buffer, buffer_size);
       delete [] buffer;
       return;
      }
};

Since you have floating point values, integer values and text, I highly suggest you use an ASCII or text based format such as CSV or XML. Binary versions of numbers (integral and floating point) may not be compatible across platforms, between OS versions or even compiler versions. Also, variable length text is a pain to deal with in binary formats.

Thomas Matthews