# Solved: Reading from files to structures with dynamic data in c++



## compnoom (Aug 14, 2014)

How do you read from files to a structure with dynamic array without allocating a fixed size to the arrays?


----------



## Ent (Apr 11, 2009)

I'm not sure I understand your problem. 
You have to allocate a size to your array when you create it. Dynamic means you decide what size that is at run time. 
So read your file to find out how many things you have that need to go in that array, and then assign the array to that size.


----------



## compnoom (Aug 14, 2014)

It doesn't work and if i deallocate the dynamic array the file has junk values. If i try to read the file in another program it gives junk values.


----------



## Ent (Apr 11, 2009)

Could you post your code?


----------



## compnoom (Aug 14, 2014)

i'm using tc 3.0 (school standards can't help it)(it's ancient)
this is the code

#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <conio.h>

//using namespace std;

class CStudent{
private:
char *name;
char *location;
public:
CStudent()
{
// allocate memory for name and location pointer before using
name = new char[20];
location = new char[20];
}
void Getdata()
{
// allocate memory for name and location pointer before using
name = new char[20];
location = new char[20];
cout << "Student Name : ";
cin >> name;
cout << "Student Location : ";
cin >> location;
}
void Display()
{
cout << setw(20) << name << setw(20) << location << endl;
}

int IsMatch(char *s)
{
if(strcmp(s,name) == 0)
{
return 1;
}
else
{
return -1;
}
}

void ReleaseMemory() // destructor can also used here
{
// deallocating memory of name and location pointer
delete [] name;
delete [] location;
}

};

int main()
{
int val = -1;
char s[20];
int choice;
char ch = 'n';
CStudent obj;
fstream infile,outfile;
clrscr();
do
{

cout << endl << " Select your choice" <<endl;
cout << "1 --> Add Student" << endl;
cout << "2 --> Display Students" << endl;
cin >> choice;

switch (choice)
{
case 1:// Create new and append file
infile.open("lucky.txt", ios:ut | ios::app);//writing
if(infile.fail())
{
cout << "could not open lucky.txt file for append " << endl;
}
do
{
obj.Getdata();
infile.write((char*) &obj, sizeof(obj));
cout << endl <<"Do you want add more record? (y/n) : ";
cin >> ch;
}while(ch != 'n');
infile.close();
break;

case 2://display file contents
infile.open("lucky.txt", ios::in);//reading
if(infile.fail())
{
cout << "could not open fileiotest.txt file for read";
}infile.read((char*) &obj, sizeof(obj));
while(!infile.eof())
{
obj.Display();
infile.read((char*) &obj, sizeof(obj));
}
infile.close();
break;
}
}while(choice > 0 && choice < 3);
return 0;
}

it works but it's not safe because there will be memory leak sooner or later

this is another code solely to read what was written in that file

#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <conio.h>

//using namespace std;

class CStudent{
private:
char *name;
char *location;
public:
CStudent()
{
// allocate memory for name and location pointer before using
name = new char[20];
location = new char[20];
}
void Getdata()
{
// allocate memory for name and location pointer before using
name = new char[20];
location = new char[20];
cout << "Student Name : ";
cin >> name;
cout << "Student Location : ";
cin >> location;
}
void Display()
{
cout << setw(20) << name << setw(20) << location << endl;
}

int IsMatch(char *s)
{
if(strcmp(s,name) == 0)
{
return 1;
}
else
{
return -1;
}
}

void ReleaseMemory() // destructor can also used here
{
// deallocating memory of name and location pointer
delete [] name;
delete [] location;
}

}obj;
int main()
{
clrscr();
ifstream infile("lucky.txt", ios::in);//reading
if(infile.fail())
{
cout << "could not open fileiotest.txt file for read";
}infile.read((char*) &obj, sizeof(obj));
while(!infile.eof())
{
obj.Display();
infile.read((char*) &obj, sizeof(obj));
}
infile.close();
getch();
}

They both are codes of seperate cpp files in the second code, i get junk values


----------



## Ent (Apr 11, 2009)

I'm not a c++ programmer myself so this is mostly theoretical, 
however, I'd guess the real problem lies here
infile.read((char*) &obj, sizeof(obj))

The idea behind Object Oriented Programming is that you shouldn't directly overwrite or directly read the memory controlled by an object from outside. That is, from outside the object the system should look the same even if the class the object is based on decides to store the fields the other way around, encrypt its internal data, or do something similar. 
However, messing around with the internals of your object is what that line is trying to do; read in characters from the file and write them to the location of the object. 

If the object happens to be very simple and you know exactly how it's stored, such as exactly 20 bytes for the first field, exactly 20 bytes for the second field, and nothing more, you might get away with it. 

However, what if objects of type CStudent are actually, say, an integer for the size of the first array, a pointer to the first array (which is located elsewhere), and the same again for the second array? I don't know whether that's how your compiler lays it out, so that's just one sensible configuration. 

Now you have trouble first of all because you're trying to read in a dump of the first format and writing it unchanged to the second. After all, the first object in your second format just takes the first 16 characters of name from your first format, but instead of treating them as ASCII treats them as two pointers and two integers. The next object is even more confusing, getting the last 4 characters from name and the first 12 from location! 

Even if you didn't have the confusion of two formats (i.e. if lucky.txt contained a dump of the second format), it still wouldn't work. That is because the second format doesn't actually contain any text! It would tell you sizes, and it would tell you where the data happened to have been stored last time you used it. 

What you need to do instead is decide on a format for the text file that makes sense for the data you want to store (in this case a simple csv format or line separated format might do). You'd then need a little bit of extra code to extract the relevant fields from the text file, and write methods into your class for setting up the data as it's needed. That is, you hand your object a string and tell it to put it where it wants to.
Similarly when you're writing the file you need to get the data out of the objects into a standard format using some sort of getter methods (i.e. ask the object for your string back), and then write them from that standard format to the file. Just copying down the contents of the object isn't the answer.


----------



## compnoom (Aug 14, 2014)

thanks so much


----------



## Ent (Apr 11, 2009)

You're welcome.


----------

