C++ array in header file - c++

I am doing a training exercise and am having trouble getting started on it. I have to write a program for an array data structure. There is a test harness provided and I need to implement the code for the data structure. I am not sure how to define an array in a header file
bellow is the test harness main.cpp which i can not edit
#include <fstream>
#include <iostream>
using namespace std;
// *****************************
// you need to create this class
// *****************************
#include "ArrayIntStorage.h"
int main(int argc, char **argv) {
// ***********************************
// non-sort read & then sort using std
// ***********************************
ifstream fin1("ACW2_data.txt");
ofstream out1("1-arrayUnsortedRead.txt");
//ofstream out2("2-arrayUnsortedRead-thenSTDSort.txt");
if(!fin1.is_open())
{
cout << "FAIL" << endl;
return 1;
}
ArrayIntStorage arrayStorage1;
arrayStorage1.setReadSort(false); // do not read sort
// read in int values into data structure
fin1 >> arrayStorage1;
// output int values in data structure to file
out1 << arrayStorage1;
// sort data structure using std
arrayStorage1.sortStd();
// output int values in data structure to file
out2 << arrayStorage1;
fin1.close();
out1.close();
out2.close();
any information on header files and how to use them with this main file would be much appreciated
Merci beaucoup

I'm pretty sure YOU are supposed to create the ArrayIntStorage.h header AND implement the matching ArrayIntStorage.cpp.
Based on the "// sort data structure using std" comment you are expected to use and create a wrapper over an appropriate stl container, something like std::vector.
Based on the "// do not read sort" comment, you should, by default, sort the vector after each insert (unless, of course, someone calls setReadSort(false) on your wrapper).
In addition to the interface described above, you still need to implement >> and <<.
UPDATE.
Reading you question at C++ pass variable from .cpp to header file you seem to be quite confused by all this...
First thing first, adding support for >> and << operators:
You do this by declaring these operators in your .h file:
friend std::ostream& operator<<(std::ostream &out, const ArrayIntStorage &a);
friend std::ifstream & operator>>(std::ifstream &, ArrayIntStorage &);
You then define their implementation in the .cpp file:
std::ostream& operator<<(std::ostream &out, const ArrayIntStorage &a)
{ return out; }
std::ifstream & operator>>(std::ifstream &, ArrayIntStorage &)
{ return in; }
Obviously, you need to add some proper code there, this is just to make it compile.
If it still doesn't compile, check if you have included the stream headers in your .h file:
#include <fstream>
#include <iostream>
Now for some general info:
Your array storage should be based on something like std::vector. The purpose of the >> and << function you need to implement is to add and retrieve int's from that container.
Since the ArrayIntStorage is a class, once you've established the interface you need ( the public member functions in the .h file) you should only look at the .h and .cpp to flesh out the implementation.
Once that is done, you don't need any of the "extern" madness the answers to your other question said.
Look at your main function. If creates an object of your class and the fin1 stream. It then calls the >> operator you've implemented. All of this is done with local variables.
This is how you "use the value of this variable from main.cpp". You call a member function of your class with that variable as a parameter.
And finally, if you have all these problems with understanding header files and link errors, are you sure you've started with the proper training exercise?

The header file ArrayIntStorage should be like below :-
The function signature may change according to the usage :-
// ArrayIntStorage.h - header file
class ArrayIntStorage
{
public :
ArrayIntStorage(); // this is the constructor
// You may skip this constructor, and use the default one
void setReadSort(bool bSort);
void sortStd()
// Add any public members if needed
private :
// Add any private members/ functions if needed
}

Marc,
http://www.cplusplus.com/doc/tutorial/ (which I mentioned in my comment) has let us down. They don't dicuss header-files as a topic in it's own right... however http://www.learncpp.com/cpp-tutorial/19-header-files/ does.
Basically a header file defines "the interface" of your class. It's put in a seperate file so that users of your class can include JUST this "interface definition" in there code... Like #include "ArrayIntStorage.h" for example. This allows the compiler to determine if they've got something wrong, like a miss-spelled method name, or passing a parameter of the wrong type... you know, all those compiler errors you've seen... yeah?
So you define WHAT your class does in the .h file... and then in the .cpp file you define HOW it does it.
Does that make sense?
Cheers. Keith.

Related

C++ file read error in Debug mode in Visual C++ [duplicate]

I have the following User.h that holds several attributes (strings). User.cpp has all the definitions.
//User.h
#ifndef USER_H
#define USER_H
#include<iostream>
#include <cstring>
using namespace std;
class User{
string username;
public:
User();
string getUsername() const;
void setUsername(string);
};
#endif
I'm using a another class, "File" to insert new users/view users from a randomly accessed .dat file
//File.h
#ifndef FILE_H
#define FILE_H
#include "User.h"
class File{
public:
void loadUser();
bool addUser(User&);
};
#endif
File class definitions
//File.cpp
#include<cstring>
#include<iostream>
#include<iomanip>
#include<fstream>
#include "User.h"
#include "File.h"
using namespace std;
User tempUser;
fstream usersFile;
void File::loadUser(){
usersFile.open("users.dat", ios::in | ios::binary);
usersFile.seekg(0);
// commenting the following lines prevented the issue
usersFile.read(reinterpret_cast<char *>(&tempUser), sizeof(tempUser));
cout<<tempUser.getUsername().c_str();
usersFile.close();
}
bool File::addUser(User& user){
usersFile.open("users.dat", ios::out | ios::ate | ios::binary);
// no issue when writing to file
usersFile.write( reinterpret_cast<const char *>(&user), sizeof(user));
usersFile.close();
cout<<"User added";
}
I'm getting the above mentioned issue when running. No compilation issue though.
Is there any issue when dealing with objects that has "string attributes" inside, in handling?
Please help
I think the issue is that you are mixing C++ code with a C mindset.
What you should really be doing here is use the extraction operator, opeartor>>(), along with the C++ IO streams. This, as opposed to using the C standard IO along with the read() function. For writing an object, use the insertion operator operator<<() instead of the C write() function.
For working with strings use std::string. This class provides operator<<() and operator>>(). So, you can say std::string s and then io << s and io >> s where io is some C++ IO stream object. This will do The Right Thing(tm). The philosophy here is that the std::string class knows better than you, a user, how to serialize a std::string object. So let it do it, with the << and >> operators.
Going on with the idea, you, as the author of User, know better than anyone else how to serialize a User object. So provide the << and >> operators for users of your class, as a service. "Users of your class" might well be you one week from now, when you have completely forgot how to properly serialize a User object. (Or, you think you remember but in practice you forgot a detail, causing a bug in your code). Example:
// in User.h
#include <string>
#include <iosfwd> // forward declarations of standard IO streams
namespace mine {
class User {
User(const std::string& name) : username(name) { }
friend std::ostream& operator<<(std::ostream&, const User&);
friend std::istream& operator>>(std::istream&, User&);
private:
std::string username;
};
std::ostream& operator<<(std::ostream& out, const User& u)
{
return out << u.username;
}
std::istream& operator>>(std::istream& in, User& u)
{
return in >> u.username;
}
} // namespace mine
From here on, to save a user to a file you say
std::ofstream f("filename");
User u("John");
f << u;
That's it. To read a user:
std::ifstream f2("filename");
f2 >> u;
It's a good practice to wrap your code in a namespace. IDEs give a good visualization of this issue, by showing how many symbols are visible with the auto-complete feature. You get to see how much of a mess there is in the global scope. By wrapping your code in a namespace you group it under a scope name, saving some more mess in the global name scope. It's just about being tidy. If you put your code in your own namespace then you can choose any name you want for a function, a class or a variable, so long as you haven't chosen it before. If you don't put it in a namespace then you need to share names with others. It's like a skunk declaring his own territory, only without the bed smell.
On that note I suggest you take off that using namespace std from your header. This brings all the symbols in the std namespace into scope of all files that #include the header. It's a bad practice. Only say using namespace std in implementation files, if you wish, but not in header files.
Granted, some will say even this is a bad idea. I personally think it's fine if you're aware of the fact you might have name clashes in that particular implementation file. But at least you know where that using statement is: it's in your implementation file, and it only causes clashes in that implementation file. It's sort of a gun, (a plastic water gun, but a gun nonetheless), only you can only shoot (wet) your own feet and no one else's. Which in my opinion is perfectly fine.
You can't read non-POD types like that. A string is not a POD type.
What are POD types in C++?
There are a few ways to read in strings properly, depending upon how they were stored.
For text files:
If the string is just a single word, separated on both sides by whitespace, you can use the plain old >> operator. If it's more than one word, you can store it on it's own line, and use getline.
For binary files:
Store the string in null terminated form. Read it one character at a time, checking for the null character. Or, prepend the string with an integer storing it's size. When you read it, first read in the integer, then read in that many characters.
string is an object, which means you're not writing it's contents.
Try writing an User and examine the file to see what I mean. What you're then reading are some pointers, that point to invalid memory locations.
Yes, the std::string class is not plain old data, in other words it contains pointers.
If you save/load the string class in this manner, the data pointed to won't be loaded/saved, only the value of the pointer.
Additionally sizeof(tempUser) won't include the size of the text pointed to by the strings.
Your solution is to change how you're reading/writing data.
One way is to use boost::serialization which handles datatypes like std::string.
Another way would be to write each string to a separate line in the text document yourself (not in binary mode) and then use readline to read them back in.
Rather than construct your own custom serialization code, something like Google Protocol Buffers might do what you want with less effort. It's ideal for passing around simple structured data from place to place.

How can I access obect instances created from file output?

I am having trouble using file I/O to create instances of my classes for a game I am working on. It might well be a dumb question, but I cannot fathom out why the compiler seems to successfully creates the objects from the data stored in the text file and then I can't access them. (I took out the .display() function calls to test this, and added a simple cout << "Object created"; into the constructor to check something had been created.)
But the code trying to access the individual objects gives me Error: "identifier" is undefined when trying to access the objects member functions. I am probably doing something completely wrong and I would appreciate a push in the right direction, I have tried changing the syntax in the while loop for creating the object, but I haven't cracked it yet. Thank you in advance! Code below...
main.cpp
#include <iostream>
#include <string>
#include <fstream>
#include "Attributes.h"
using std::cout;
using std::endl;
using std::cin;
using std::ofstream;
using std::ifstream;
using std::getline;
using std::cerr;
int main() {
std::string line;
ifstream attdata;
attdata.open("data.txt");
if (attdata.is_open())
{
while (attdata.good())
{
getline (attdata, line);
Attributes * line = new Attributes;
}
attdata.close();
}
else cerr << "Unable to open file.";
health.display();
fatigue.display();
attack.display();
skill.display();
defence.display();
skilldef.display();
speed.display();
luck.display();
};
data.txt
health
fatigue
attack
skill
defence
skilldef
speed
luck
Atributes.h
#pragma once
#include <string>
class Attributes
{
public:
Attributes(void);
Attributes(std::string name, std::string shortName, std::string desc, int min, int max);
~Attributes(void);
void display();
private:
std::string m_nameLong;
std::string m_nameShort;
std::string m_desc;
int m_minValue;
int m_maxValue;
};
In C++, all your variables need to be declared by name in your code. You are declaring a bunch of pointer variables all named line in your loop, and then trying to use other named variables like health, fatigue, etc that have not been created.
I don't think you can directly create variables by name from a file like this, but you could read the file and create an array or vector of objects that contain the data from the file. You could pass the string read by getline() into your Attributes constructor, and then store the created pointers in an array or map that you can access later to call methods like display(). If you really want a variable called health in your code, it has to be declared somewhere in the code.
Another minor point is that you are reusing the variable name line (which you previously declared to be a std::string) in the loop scope. This may work, but is confusing and should be avoided. Call your pointer variable something else, like attItem.
For example:
Attributes * attItem = new Attributes(line);
attList.push_back(attItem);
You arent sending any of the information that you received to create the new object. Add a constructor that takes in a string with the information and then initialize Attributes like so:
Atrributes::Attributes(String data){
//parse string and initialize data here
}
Also, I would recommend not making your Attributes object have the same name as the variable that holds the data. Even if it's harmless (and im not sure that it is), its just not very clean.
C and C++ doesn't allow new names of variables to be created at runtime. Thus health in health.display(); can not come from reading a file.
What you can do is have a collection of Attributes (e.g. attList) and a function that finds the appropriate attribute for you:
Attribute health = attList.find("health");
(Or if you prefer to use a map, you could do:
Attribute health = attList["health"];
Another approach of course is to have attributes stored in each object, e.g.
class PlayerBase
{
private:
Attribute health;
Attribute speed;
...
public:
void SetAttribute(const string& name, const Attribute& attr);
};
Then you'd find the right attribute by comparing string name:
void SetAttribute(const string& name, const Attribute& attr)
{
if (name == "health") health = attr;
if (name == "speed") speed = attr;
...
}

C++: is there a point to having a header file? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ - What should go into an .h file?
I know this is general, but I find it really annoying coding things twice, and would find it a lot easier if I didn't have to browse between two files (my .h and .cc) rather than just keep it all in one.
So, what is the point in having a header file if most of what is there must be rewritten and the rest can just be placed in the .cc.
Instead of:
class VoterData {
// raw data
Voter::States state;
bool vote;
unsigned int numBlocked;
// flags
bool _hasState, _hasVote, _hasNumBlocked;
public:
VoterData();
void reset();
// getters
Voter::States getState();
bool getVote();
unsigned int getNumBlocked();
bool hasState();
bool hasVote();
bool hasNumBlocked();
// setters
void setState(Voter::States state);
void setVote(bool vote);
void setNumBlocked(unsigned int numBlocked);
};
AND:
/* VoterData */
VoterData::VoterData() {
reset();
}
void VoterData::reset() {
_hasState = _hasVote = _hasNumBlocked = false;
}
// getters
Voter::States VoterData::getState() { return state; }
bool VoterData::getVote() { return vote; }
unsigned int VoterData::getNumBlocked() { return numBlocked; }
bool VoterData::hasState() { return _hasState; }
bool VoterData::hasVote() { return _hasVote; }
bool VoterData::hasNumBlocked() { return _hasNumBlocked; }
// setters
void VoterData::setState(Voter::States state) {
this->state = state;
_hasState = true;
}
void VoterData::setVote(bool vote) {
this->vote = vote;
_hasVote = true;
}
void VoterData::setNumBlocked(unsigned int numBlocked) {
this->numBlocked = numBlocked;
_hasNumBlocked = true;
}
Why shouldn't I just put it all in the .cc file and declare the class there?
C++ doesn't tell you where to put your code. Actually, in your case it might be better to use one file:
struct VoterData {
// raw data
Voter::States state;
bool vote;
unsigned int numBlocked;
// flags
bool _hasState, _hasVote, _hasNumBlocked;
// No getters, setters and other cruft needed
};
If your class is more complicated than my or your example, you will notice that having a header file gives an advantage in understanding your program.
In that case, the header file (x.h) will be small (e.g. 20 lines of code) and the implementation file (x.cc) will be large (e.g. 200 lines of code - much more than in your example class). Anyone (who wants to understand what the class does, or how to use it) has to look at the 20 lines in the header file and doesn't have to look at the 200 other lines of code - that's great (speaking from experience)!
So, your example doesn't require separation into header and implementation files.
I believe there are a lot of reasons, which the most noticeable ones are:
If you put a class in a source file and then include that source file in other source files that use that it will work, but it won't work if anything is outside of the class.
There is a huge speedup if other source files that use the class include only header files and don't have to parse the whole class source file.
Circular references, if class A uses class B and class B uses class A, you have to use header files, its not possible with only source files (there is a possible workaround with templates but its just complicated and will get you into trouble).
Of course you can put EVERYTHING in a single .cc file and make it compiled & run, no matter how many classes there are.
Whether to use header files depends on your purpose and habits.
For example, if you want to write a shared library and release it to others, you have to use header files. The users can then include your header files and call the functions you wrote.
For most any one-off code—which will never be shared with any other programs or persons—then I agree: skip creating a header file and put all the code in a .C, .cc, .c++, etc. file
However, if a class will/should/might be reused—often the goal of much development intent—somewhere along the way it is a great idea to identify the declaration portion and put that in a header file, and the implementation part and put that in a source mode: eventually it may become a shareable library.
If everything is in the .cc file and your compiler treats that file as a compilation unit, then you will not be able to use the classes defined in that file in other files (you will get a multiply defined symbol error). Also defining everything in a single file will significantly increase your compilation times, especially in a large project.
All of the answers so far seem to answer with respect to how the language works according to the specification and current compilers, but I think the question is about why it is designed that way.
When you add a method to a class, you have to put the declaration in two places, wasting programming time. It should be entirely possible to add a compiler pass that generates header files based on their code files, shouldn't it? Slightly longer compile times seems like an okay trade-off nowadays, but it wasn't always so.
One thing the current system does is give you finer control over what is where. There may be some defines for example that you want to have for your code that you don't want to be put into the header for anyone that calls your class.

C++ How to dynamically select a file handle according to the type of data that should be written?

I've got a class outputInterface; that should handle the output (to files) of some data. The data is contained in objects of some custom classes, say dataClassA and dataClassB, that all derive from a common base class dataClassBase.
Now I want the data to be written to different files according to its type. So data of type dataClassA should go to fileA, data of type dataClassB should go to fileB and so on. As this output happens very often I would like the file handles (fileA and fileB) to stay open, i.e. I don't want to open and close the files for the output of each piece of data. One outputInterface object can be expected to exist all the time.
So what I would like to achieve is something like this:
Dynamically associate data of type dataClassA with the file handle fileA etc.
When receiving data of type dataClassA check whether fileA is already connected to a file, if not, open the file.
How can I get this behavior (or least something similar / better)?
I've been thinking of making the file handles static members of dataClassA and dataClassB (or the base class dataClassBase?). But then, how do I take care of closing the files? I would have to somehow keep track of the data types that have actually been used (the files that have actually been opened).
Try something like this:
#ifndef OUTPUTINTERFACE?H
#define OUTPUTINTERFACE?H
#include <string>
#include <fstream>
#include <map>
class DataClass
{
public:
virtual bool WriteData(std::ofstream& FStream) = 0;
};
class DataClass1 :
public DataClass
{
virtual bool WriteData(std::ofstream& FStream)
{
FStream << "teletubbies";
}
};
class DataClass2 :
public DataClass
{
virtual bool WriteData(std::ofstream& FStream)
{
FStream << "garbage";
}
};
class OutputInterface
{
public:
OutputInterface()
{
}
~OutputInterface()
{
//Release stream pointers
}
template<typename T>
bool WriteData(T& Data)
{
std::string dClassUID = std::string(typeid(T).name);
tFStreamMap::iterator it this->streamMap.find(dClassUID);
std::ofstream* stream = NULL;
if(it != streamMap.end())
{
stream = it->second;
}
else
{
stream = new std::ofstream();
stream->open(dClassUID + ".txt");
streamMap.insert(std::make_pair(dClassUID, stream));
}
Data.WriteData(stream);
}
private:
typedef std::map<std::string, std::ofstream*> tFStreamMap;
tFStreamMap streamMap;
};
#endif
This is just a prove of concept and can be optimized in many ways.
I would rather stick with overloaded functions than with runtime type checks.
This is fairly easy to implement in C++11, using an
std::map<std::type_index, std::ostring*> outputMap. (In C++03, you'll have to
implement the equivalent of std::type_index yourself.) You get the
output stream using outputMap[typeid(*data)]. The only problem is
getting the streams into the map to begin with: you can do something
like:
std::ostream*& destPtr = outputMap[typeid(*data)];
if ( destPtr == NULL ) {
destPtr = new std::ofstream("...");
}
std::ostream& dest = *destPtr;
But from where do you get the filename?
There's also the question of when you close the streams: you can't
normally close an output stream in a destructor, since closing an output
stream is an operation which can fail, and you need to detect and react
to that failure. Probably with an exception, which is why you don't
want to do it in a destructor.
Since the "data" part comes from dataClassBase, you can make a virtual/pure-virtual function 'WriteData` in this class, and let derive class implement it.
The class outputInterface may take objects of type dataClassBase and would directly call WriteData. Other than WriteData you may also add other virtual functions in dataClassBase
You did not mention relationship between outputInterface and dataClassBase

C++ Program crashes when reading object from random access file

I have the following User.h that holds several attributes (strings). User.cpp has all the definitions.
//User.h
#ifndef USER_H
#define USER_H
#include<iostream>
#include <cstring>
using namespace std;
class User{
string username;
public:
User();
string getUsername() const;
void setUsername(string);
};
#endif
I'm using a another class, "File" to insert new users/view users from a randomly accessed .dat file
//File.h
#ifndef FILE_H
#define FILE_H
#include "User.h"
class File{
public:
void loadUser();
bool addUser(User&);
};
#endif
File class definitions
//File.cpp
#include<cstring>
#include<iostream>
#include<iomanip>
#include<fstream>
#include "User.h"
#include "File.h"
using namespace std;
User tempUser;
fstream usersFile;
void File::loadUser(){
usersFile.open("users.dat", ios::in | ios::binary);
usersFile.seekg(0);
// commenting the following lines prevented the issue
usersFile.read(reinterpret_cast<char *>(&tempUser), sizeof(tempUser));
cout<<tempUser.getUsername().c_str();
usersFile.close();
}
bool File::addUser(User& user){
usersFile.open("users.dat", ios::out | ios::ate | ios::binary);
// no issue when writing to file
usersFile.write( reinterpret_cast<const char *>(&user), sizeof(user));
usersFile.close();
cout<<"User added";
}
I'm getting the above mentioned issue when running. No compilation issue though.
Is there any issue when dealing with objects that has "string attributes" inside, in handling?
Please help
I think the issue is that you are mixing C++ code with a C mindset.
What you should really be doing here is use the extraction operator, opeartor>>(), along with the C++ IO streams. This, as opposed to using the C standard IO along with the read() function. For writing an object, use the insertion operator operator<<() instead of the C write() function.
For working with strings use std::string. This class provides operator<<() and operator>>(). So, you can say std::string s and then io << s and io >> s where io is some C++ IO stream object. This will do The Right Thing(tm). The philosophy here is that the std::string class knows better than you, a user, how to serialize a std::string object. So let it do it, with the << and >> operators.
Going on with the idea, you, as the author of User, know better than anyone else how to serialize a User object. So provide the << and >> operators for users of your class, as a service. "Users of your class" might well be you one week from now, when you have completely forgot how to properly serialize a User object. (Or, you think you remember but in practice you forgot a detail, causing a bug in your code). Example:
// in User.h
#include <string>
#include <iosfwd> // forward declarations of standard IO streams
namespace mine {
class User {
User(const std::string& name) : username(name) { }
friend std::ostream& operator<<(std::ostream&, const User&);
friend std::istream& operator>>(std::istream&, User&);
private:
std::string username;
};
std::ostream& operator<<(std::ostream& out, const User& u)
{
return out << u.username;
}
std::istream& operator>>(std::istream& in, User& u)
{
return in >> u.username;
}
} // namespace mine
From here on, to save a user to a file you say
std::ofstream f("filename");
User u("John");
f << u;
That's it. To read a user:
std::ifstream f2("filename");
f2 >> u;
It's a good practice to wrap your code in a namespace. IDEs give a good visualization of this issue, by showing how many symbols are visible with the auto-complete feature. You get to see how much of a mess there is in the global scope. By wrapping your code in a namespace you group it under a scope name, saving some more mess in the global name scope. It's just about being tidy. If you put your code in your own namespace then you can choose any name you want for a function, a class or a variable, so long as you haven't chosen it before. If you don't put it in a namespace then you need to share names with others. It's like a skunk declaring his own territory, only without the bed smell.
On that note I suggest you take off that using namespace std from your header. This brings all the symbols in the std namespace into scope of all files that #include the header. It's a bad practice. Only say using namespace std in implementation files, if you wish, but not in header files.
Granted, some will say even this is a bad idea. I personally think it's fine if you're aware of the fact you might have name clashes in that particular implementation file. But at least you know where that using statement is: it's in your implementation file, and it only causes clashes in that implementation file. It's sort of a gun, (a plastic water gun, but a gun nonetheless), only you can only shoot (wet) your own feet and no one else's. Which in my opinion is perfectly fine.
You can't read non-POD types like that. A string is not a POD type.
What are POD types in C++?
There are a few ways to read in strings properly, depending upon how they were stored.
For text files:
If the string is just a single word, separated on both sides by whitespace, you can use the plain old >> operator. If it's more than one word, you can store it on it's own line, and use getline.
For binary files:
Store the string in null terminated form. Read it one character at a time, checking for the null character. Or, prepend the string with an integer storing it's size. When you read it, first read in the integer, then read in that many characters.
string is an object, which means you're not writing it's contents.
Try writing an User and examine the file to see what I mean. What you're then reading are some pointers, that point to invalid memory locations.
Yes, the std::string class is not plain old data, in other words it contains pointers.
If you save/load the string class in this manner, the data pointed to won't be loaded/saved, only the value of the pointer.
Additionally sizeof(tempUser) won't include the size of the text pointed to by the strings.
Your solution is to change how you're reading/writing data.
One way is to use boost::serialization which handles datatypes like std::string.
Another way would be to write each string to a separate line in the text document yourself (not in binary mode) and then use readline to read them back in.
Rather than construct your own custom serialization code, something like Google Protocol Buffers might do what you want with less effort. It's ideal for passing around simple structured data from place to place.