Help: OOP file I/O with C-strings

  • Thread starter Andreas Palsgård
  • Start date
A

Andreas Palsgård

Hey there...
I hope someone can help me with my problem.
I want to write a class object with both strings and integers, to a file,
and be able to read it properly again. I thought that the code below worked
(because it appears as so in a c++ book), but it does not. Can you make it
work? =)

thanx

Code:
--------
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

class person
{
protected:
string name,colour;
int age;
public:
void getdata()
{
cout << "Enter name:" ; cin >> name;
cout << "Enter Age:"; cin >> age;
cout << "Enter colour:"; cin >> colour;
}
void showdata()
{
cout << "Name: " << name << endl;
cout << "Age:" << age << endl;
cout << "Colour:" << colour << endl;
}
string get_name(){ return name;}
int get_age(){ return age;}
string get_colour(){ return colour;}
};

person tim;

void file_in(){
person temp_pers;
ifstream infile("person.dat", ios::in | ios::binary);
infile.read(reinterpret_cast<char*>(&temp_pers),sizeof(temp_pers));
infile.close();
tim = temp_pers;
cout << temp_pers.get_name() << endl;
cout << temp_pers.get_age() << endl;
cout << temp_pers.get_colour() << endl;
}
void file_out(){
tim.getdata();
person temp_pers;
temp_pers = tim;
ofstream outfile("person.dat", ios::binary | ios::eek:ut | ios::trunc);
outfile.write(reinterpret_cast<char*>(&temp_pers),sizeof(temp_pers));
outfile.close();
cout << temp_pers.get_name() << endl;
cout << temp_pers.get_age() << endl;
cout << temp_pers.get_colour() << endl;
}
/////////////////////////////
int main()
{
file_out();
//file_in();
return 0;
}
 
R

Ron Natalie

Andreas Palsgård said:
I thought that the code below worked
(because it appears as so in a c++ book), but it does not.

You need to burn that C++ book . What you wrote will not work.
The most likely place you are running afoul is you just can't write
out a class containing a std::string (or just about any other non-trivial
object) by casting it to char* and calling write on it. The string
class frequently doesn't contain the data, just a pointer to it.

You're going to have to format the output yourself.
 
K

Karl Heinz Buchegger

void file_in(){
person temp_pers;
ifstream infile("person.dat", ios::in | ios::binary);
infile.read(reinterpret_cast<char*>(&temp_pers),sizeof(temp_pers));

That's a bad idea. A really bad idea.
If your book relly suggest doing this: throw it away, the
author doesn't know what he is talking about.

Disclaimer: The above may work. But for making it work the class
must fullfill certain properties. Your's doesn't.

Well: The solution is not to try to read and write a class as a whole
as the above attempts. Instead you give the class some read/write
functions which do the file reading/writing on a member base. Note
this may also mean to call read/write functions of the members, if there
are any or to create a way to safely read/write by this member function
itself:


class person
{
....


void writeTo( ofstream& out_file )
{
int len;

// age can be written directly
out_file.write( &age, sizeof( age ) );

// but not so string. since std::string has no
// binary write facility, we have to invent our own
// first write the length of the string, followed by
// the characters.

len = name.length();
out_file.write( len, sizeof( len ) );
out_file.write( name.c_str(), len );

len = colour.length();
out_file.write( len, sizeof( len ) );
out_file.write( colour.c_str(), len );
}

void ReadFrom( ifstream& in_file )
{
// age can be read directly
in_file.read( &age, sizeof( age ) );

// but not so the strings. But we know
// how they are stored. So start with
// reading the length
int len;
char* tmp;

in_file.read( &len, sizeof( len ) );

// then allocate enough storage to store what
// needs to be read
tmp = new char[ len + 1 ];
in_file.read( tmp, len );
tmp[len] = '\0'; // make sure it is a valid C-style string

name = tmp;

delete [] tmp;

// same for the other string

in_file.read( &len, sizeof( len ) );
tmp = new char[ len + 1 ];
in_file.read( tmp, len );
tmp[len] = '\0';
colour = tmp;
delete [] tmp;
}


Of course some helper functions would be great, which eg
do the mechanics of writing a string in binary to a stream.
But thats left as an exercise for the reader.
 
T

tom_usenet

Hey there...
I hope someone can help me with my problem.
I want to write a class object with both strings and integers, to a file,
and be able to read it properly again. I thought that the code below worked
(because it appears as so in a c++ book), but it does not. Can you make it
work? =)

You have to write each field out explicitly, and don't use
reinterpret_cast on class types.

See http://www.parashift.com/c++-faq-lite/serialization.html

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top