include <iostream>
include <string>
class Staff{
private:
int StaffNumber;
string Name;
public:
void Person::createNew(){
int i;
string s,t;
cout << "Enter No: ";
getline( cin, t);
if (!(istringstream( t ) >> i))
i = 0;
cout << "Enter Name:";
getline( cin, s );
StaffNumber = i;
Name = s;
}
void Person::viewDetails() {
cout << "\nStaffNumber: " << StaffNumber;
cout << "\t| Name: " << Name;
}
};
then on the main() method i save this object to a file and then i can read the object from the file as well.. This works fine as long as i enter less than or equal to 15 characters for the string Name.
Suppose i call the createNew() method and enter a number first and then i enter a string of more than 15 characters for the name and save the object to the file. Then i read the object from the file and put it into a variable and when i use viewDetails() method to display the details i see some gibberish instead of the Name. And then i get this error
Unhandled exception at 0x65907a8b (msvcp90d.dll) in Staff Personnel System.exe: 0xC0000005: Access violation reading location 0x006f68b0.
It seems there is some kind of 15 character limit for strings.
I want to store the object with Name at any length.
Your problem is where you are saving/loading from disk. There is no limit on the length of a std::string, it sounds like you are just hastily overwriting a strings internal representation/buffer.
It doesn't give me error when i insert a record, but when i display the records it gives an error at the exact position in the while loop where the string Name exceeds 15 characters. The whole thing works fine as long as i dont enter strings longer than 15 chars.
I'm pretty sure that would only work for POD types. You can't expect to save a pointer (memory address) and then read it and the data still exist. Similar to a deep copy, you need to do a "deep save" if there is such a thing. std::string uses dynamically allocated memory, so you can't just forcefully save it in this manor. If it works in any case, I think you're just getting lucky.
I agree with you moorecm.
the sizeof(person) is always the same even though I'm using string. So I gave it a try to save the objects into the file and it worked, because all objects are of the same size. When I input more than 15 chars into the string I can still write it to the file. But I think the size of that specific object will not be the same as the others and therefore when I retrieve the data using the same size as others, it gives error. That's what I think.
I think the "string" in C++ works something like a vector which has an initial size of 15 and when more characters are assigned it's size is increased dynamically. Therefore when I read the record I must use the size of that specific record, but we don't know which record it is right.
I started C++ only 2 months ago but I'm familiar with other languages including basics of C, so I don't really know how C++ works
i believe i'm lacking some knowledge regarding reading and writing objects into files. The .size() method might give me the size of the string but the string is located inside the class 'Person' and i'm saving objects of this class.
You could write your own write/read methods and still use std::string. The methods would just have to operate member by member and in the case of the string, write it's contents or read a temporary and construct the string.
Thanks Galik,
So basically you're writing the member variables alone. I got one question, would this allow me to save more than one object into the file and read from specific positions?
You can read and write multiple objects. But each object is of variable length because you don't know how long each string is. So you can't access the file randomly (specific positions). You would have to read through from the beginning.
To do that you would have to modify the output functions to always use fixed lengths. So when you output the string you could truncate it if it is too long, or ensure the user can not enter more than a specified amount.
Then you can position were you read and write exactly to align with each record using seekg() and seekp().
Umm, yea that's the problem. I want the user to enter a string of any length not a fixed length and also be able to access the file from any random location.
Then perhaps you need an index. That is a file containing fixed length records that point to the position of the actual data. To be honest when things get this complex I generally turn to a database. They are designed for this.
the thought of creating another file for this has been in my mind for a while now, but i thought its a stupid idea so i dint do it :D
so i guess i'm gonna do that now and that will solve the entire problem...
actually i cud do this without dynamic lengths, OR sequential reading of file, but i just wanna know how to random access with dynamic lengths.
Also i am required to do this only with files not database.
You have been a great help for me. I'm now actually using the code that you posted above instead of my original code.
Thanks a lot
Okay, but the index route is not as simple as it looks. When you come to deleting files you end up leaving differently sized holes in your data file. So then you have the problem of finding a free space to store new records in. Also if you edit a record and the data grows too large for the space already allocated. You then need to re-allocate it leaving a hole where it once was. So the data becomes 'fragmented' over time. This is actually why you have a "defrag" option for your hard disk. If this is a college assignment I would be tempted to use fixed length strings and save myself from all the grief.