Sign in to follow this  

help with struct and i/o please

This topic is 4755 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

how can i read from a file written in binary to a struct? here is my program - it's homework so i realize the program is pretty pointless. i am having problems writing the info on the file into the struct temprec - it only reads into temprec[0].name and temprec[0].amnt but all data after that is garbage binary - the whole program is bellow. i'm a newbie so please bear with me.
 
struct record
{
	char name[15];
	float amnt;
};

struct temp
{
	char name[15];
	float amnt;
};


void main()
{
	ofstream fout;

	fout.open("master.dat", ios::binary);
	
	record master [10] = {"Helen", 10, "Julie", 20, "Lena", 30, 
		"Alan", 40, "Annie", 50, "May", 60, "Lee", 70, "Sam", 80, "June", 90, 
"Bill", 100};
	
	fout.write((char*)&master, sizeof(record));
	fout.close();

	fout.open("trans.dat", ios::binary);
	
	struct record trans [7] = {"Lena", 10, "Julie", 5.75, "Lee", 15.02,
		"Ed", 40, "Art", 5.00, "Bill", 7.32};

	fout.write((char*)&trans, sizeof(record));
	fout.close();

	temp temprec[10];
	ifstream fin;
	fin.open("master.dat", ios::binary);
		
	fin.read((char*)&temprec, sizeof(temp));
	while(fin)
	{
		
		cout << temprec[0].name << "   " << temprec[0].amnt << endl;

		fin.read((char*)&temprec, sizeof(temp));
	}

	fin.close();

	fin.open("trans.dat", ios::binary);

	
		
	fin.read((char*)&temprec, sizeof(temp));
	while(fin)
	{
		
		cout << temprec[1].name << "   " << temprec[1].amnt << endl;

		fin.read((char*)&temprec, sizeof(temp));
	}

	fin.close();


}

[Edited by - angelxe1 on December 7, 2004 7:53:46 AM]

Share this post


Link to post
Share on other sites
Since this is homework I won't solve it for you, but I will give you a pointer to where you're going wrong. Take a long hard look at this line:
 fout.write((char*)&master, sizeof(record));


Enigma

Share this post


Link to post
Share on other sites
lol
believe me when i say that i have looked at that one line for about two days but i still can't figure out what is wrong i want to write to the file master.dat and then open it and read the data into temprec -
anyway i tried to find something online about structs and i/o files - because i have no textbook since i couldn't afford it (it was either the text book which the teacher told us not to bother or the lab book which i needed) and i can not
does anyone have any links they can direct me two please?

Share this post


Link to post
Share on other sites
OK, I'll give you a bit more of a hint. You're saying that you manage to read the first record just fine, but not any of the other records. This leaves two possibilities:
  • You're not reading all the records properly

  • You're not writing all the records properly

Furthermore, if we dissect the line I highlighted earlier we can see a limited number of places that it could be going wrong:
fout.write((char*)&master, sizeof(record));
  • Is fout valid?

  • Is fout capable of writing data?

  • Is there a possibility of a bug in fout?

  • Is (char*)&master the data we want to write

  • Is the structure of master correct to allow us to write it out as an array of bytes?

  • Does sizeof(record) write out the number of items we want?


Enigma

Share this post


Link to post
Share on other sites
how do i know if i am writing the records properly? when i don't use binary i can just open it and look but this way i am not sure.

"Is fout valid?" it is writing the first record so i am assuming yes

"Is fout capable of writing data?" our teacher used fout in a similar program so i think yes

"Is there a possibility of a bug in fout?" a bug? i have no idea.

"Is (char*)&master the data we want to write?" i want to write the record called master to the file so yes (i think)

"Is the structure of master correct to allow us to write it out as an array of bytes?" home work:
------------------------- writing structures on disk --------------------------
14) This program deals with writing records (structures) on to a disk file. You will be using this file as input for the next program. Create the following structure in your program:

struct record
{
char name [15];
float amt;
};

Now set up 2 arrays of record structures, one called master and one called trans in the following manner:

struct record master [10];
struct record trans [7];

Initialize the two arrays with the folllowing data:

Master Trans

Helen 10. Lena 10.
Julie 20. Julie 5.75
Lena 30. Lee 15.02


"Does sizeof(record) write out the number of items we want?" it is supposed to, as far as i know.

i feel like i am where i started.

=(

Share this post


Link to post
Share on other sites
Keep going at it. I'm trying to help you learn how to debug, rather than just giving you the answer (the old "give a man a fish/teach a man how to fish" adage).

Quote:
how do i know if i am writing the records properly? when i don't use binary i can just open it and look but this way i am not sure.

You can still open the file using notepad or something similar, but any numbers in the file will show up as junk values. It can still be useful to try it though, as text will show up as normal.

Quote:
"Is fout valid?" it is writing the first record so i am assuming yes

To some extent this is a good assumption, however you can be more robust by checking the state of fout. Whenever you catch yourself making an assumption try to test that assumption as much as possible. In this case you might want to do a google search for "ofstream valid". The top few results there should give you some idea of how to check the state of fout.

Quote:
"Is fout capable of writing data?" our teacher used fout in a similar program so i think yes

fout is an instance of std::ofstream, which is the standard class for file output, so the answer to this question is indeed yes. Again, a quick google search for "ofstream" should be enough to confirm that std::ofstream is a class designed for writing to files.

Quote:
"Is there a possibility of a bug in fout?" a bug? i have no idea.

There are generally two possibilities when it comes to debugging - there is a problem in the code that is being called (in this case fout) or there is a bug in the code that is making the call (in this case your code). Since fout is a std::ofstream object from the standard library you can be 99.99999999% certain it does not contain any bugs. Therefore it must be your code that contains the bug.

Quote:
"Is (char*)&master the data we want to write?" i want to write the record called master to the file so yes (i think)

Indeed, although be careful of your terminology. master is an array of records, not a record. This is something you have to check yourself. Google can't help you. One step you can take to try and test this is to write the data to the screen just before you write it to the file to confirm its validity (I assume you've covered cout before ofstreams).

Quote:
"Is the structure of master correct to allow us to write it out as an array of bytes?" home work:
------------------------- writing structures on disk --------------------------
14) This program deals with writing records (structures) on to a disk file. You will be using this file as input for the next program. Create the following structure in your program:

struct record
{
char name [15];
float amt;
};

Now set up 2 arrays of record structures, one called master and one called trans in the following manner:

struct record master [10];
struct record trans [7];

Initialize the two arrays with the folllowing data:

Master Trans

Helen 10. Lena 10.
Julie 20. Julie 5.75
Lena 30. Lee 15.02

OK, this was a bit of a tougher one and depending on your level of experience you may not be able to answer it. Since it doesn't seem to be crucial to the homework I'll tell you that the structure of master is indeed correct to allow it to be written out as an array of bytes. I won't go into the details, since this has the potential to confuse more than it would probably help.

Quote:
"Does sizeof(record) write out the number of items we want?" it is supposed to, as far as i know.

Again, you've made an assumption. Try to verify it. Go through the maths explicitly. What is master? How big is it? What is a record? How big is it?

Enigma

Share this post


Link to post
Share on other sites
i went and retested some of the stuff before i read your last reply - and here is what i got so far -

the structs are being initialized properly (i used cout to confirm this)

fout is linked to ofstream which i did have in my original code sorry it was not included in this message.

sizeof(record) is returning the number 20. which according to me is supposed to be enough to at least write to lines. but all i see when i open the file is a bunch of binary then lena then more binary. (why is lena not in binary?)

i have been working on this for days. i'm just not getting this one thing and i can't move on from it.

Share this post


Link to post
Share on other sites
Consider the following:
#include <iostream>

struct SomeStruct
{
int memberVariable;
};

SomeStruct someStructs[10];

int main()
{
std::cout << "SomeStruct is " << sizeof(SomeStruct) << " bytes long\n";
std::cout << "someStructs is " << sizeof(someStructs) << " bytes long\n";
}





By the way, when I open master.dat in notepad I see: "Helen A", which is exactly what I would expect to see (although most of those spaces could be anything instead of just spaces - they're actually undefined).

Also, you have one insidious bug in your program which I will tell you about, because the likelihood of you finding it on your own is slim to none. When you close fin the status flags stay set, which means it still thinks it's at the end of the file, even after you open a new file. Insert a call to fin.clear() between fin.close() and fin.open("trans.dat", ios::binary);, or use two seperate ifstream objects.

Enigma

[Edited by - Enigma on December 1, 2004 10:31:41 AM]

Share this post


Link to post
Share on other sites
these are all things i kinda had a feeling about but just didn't know how to explain or where to go to from even in my own head. (the sizeof and the opening of files one after the other)

okay so i am not giving it enough space to write to. which is confusing because the teacher had this


struct student
{
char name[25];
int grade;
};

int main()
{
student s;
ofstream fout;
fout.open("test.dat", ios::binary);
// code to enter names and grades accordingly;

fout.write((char*)&s, sizeof(student));

// more code
}

why is it student in the sizeof? according to what i just saw from your message shouldn't be long enough to write to?

sorry to ask so much...

i made some changes and everything seems to fine now.
thank you so much for your help.

#include <iostream>
using namespace std;

#include <fstream>
using std::ofstream;
using std::ifstream;

struct record
{
char name[15];
float amnt;
};

struct temp
{
char name[15];
float amnt;
};


void main()
{
ofstream fout;

fout.open("master.dat", ios::binary);

record master [10] = {"Helen", 10, "Julie", 20, "Lena", 30,
"Alan", 40, "Annie", 50, "May", 60, "Lee", 70, "Sam", 80, "June", 90, "Bill", 100};

fout.write((char*)&master, sizeof(master));
fout.close();

fout.clear();

fout.open("trans.dat", ios::binary);

struct record trans [7] = {"Lena", 10, "Julie", 5.75, "Lee", 15.02,
"Ed", 40, "Art", 5.00, "Bill", 7.32};

fout.write((char*)&trans, sizeof(trans));
fout.close();

fout.clear();

temp temprec[10];
ifstream fin;
fin.open("master.dat", ios::binary);

fin.read((char*)&temprec, sizeof(temp));
while(fin)
{

cout << temprec[0].name << " " << temprec[0].amnt << endl;

fin.read((char*)&temprec, sizeof(temp));
}

fin.close();

fin.clear();

fin.open("trans.dat", ios::binary);



fin.read((char*)&temprec, sizeof(temp));
while(fin)
{

cout << temprec[0].name << " " << temprec[0].amnt << endl;

fin.read((char*)&temprec, sizeof(temp));
}

fin.close();


}



[Edited by - angelxe1 on December 7, 2004 7:45:19 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by angelxe1

record master [10] = {"Helen", 10, "Julie", 20, "Lena", 30,
"Alan", 40, "Annie", 50, "May", 60, "Lee", 70, "Sam", 80, "June", 90, "Bill", 100};

fout.write((char*)&master, sizeof(master));


That is one way of doing it, however consider this: master is an array of records. Now, we know that sizeof(record) is correct, and we know that master contains 10 records... think of the sizeof in another manner. For instance: "If you have 10 $50 bills, how much money do you have? How did you calculate that amount?" now lets rephrase that to match our question: "If you have 10 records, and each record is 20 bytes big, how big is it total?" The math for both is the same, and you might want to consider rewriting that fout to use sizeof(record) and account for that small bit of math.

Share this post


Link to post
Share on other sites
Don't apologise about asking. You don't learn if you don't ask. As long as people show that they're willing to have a go at solving their problems and not just sponge answers then I'm more than willing to help.

I suspect you're getting to "can't see the wood for the trees" mode. This often happens when you stare at a bug for too long. So for now, completely forget about your code and I'll quickly go through some basics which you probably know but are beginning to get confused about because you've been bashing your head against them so long.
struct SomeStruct
{
int memberVariable1;
char memberVariable2[15];
};

This is the definition for a struct. All it does is tell the compiler what that structure looks like. In this case you're telling the compiler: "I have a structure called SomeStruct which I'll be using later. SomeStruct objects consist of an integer and an array of 15 characters".
The size of SomeStruct is the amount of space (in bytes) the compiler would allocate for a single instance of SomeStruct. In this case the size of SomeStruct is 20 bytes. That's 4 for the int, 15 for the character array and an extra 1 to pad it to a multiple of 4 because that's how computers work best.
SomeStruct aStruct;

This is the definition for an instance of SomeStruct. Here the compiler actually allocates memory for a SomeStruct. In this case you're telling the compiler: "You know that SomeStruct structure I told you about earlier? Well, I want one of them now called aStruct".
Since the size of SomeStruct is the amount of space (in bytes) the compiler would allocate for a single instance of SomeStruct it follows that the sizeof aStruct (an instance of SomeStruct) is exactly the same.
SomeStruct someStructs[10];

This is the definition for an array of SomeStructs. Here the compiler must allocate memory for 10 SomeStructs. In this case you're telling the compiler: "You know that SomeStruct structure I told you about earlier? Well, I want ten of them now in a row".
This is roughtly equivalent to doing:
SomeStruct aStruct1;
SomeStruct aStruct2;
SomeStruct aStruct3;
...
SomeStruct aStruct10;

Since someStructs contains 10 SomeStruct objects is follows that the size of someStructs is 10 times the size of SomeStruct, so the size of someStructs in this case is 200 bytes.
Now lets apply this to your teachers example:
struct student
{
char name[25];
int grade;
}; // definition of the class - takes up no memory, just tells the compiler what a student object will look like

int main()
{
student s; // definition for a student object. Here the compiler allocates memory for the object - probably 32 bytes with padding
ofstream fout;
fout.open("test.dat", ios::binary);
// code to enter names and grades accordingly;

fout.write((char*)&s, sizeof(student)); // write the student object to the file. We have only one student object, which is 32 bytes in size, so we want to write 32 bytes to the file. sizeof(student) gives that 32 bytes. It is exactly the size of the object we are writing. sizeof(s) would also work here since the size of a class is the same as the size of a single instance of that class

// more code
}


Enigma

Share this post


Link to post
Share on other sites
Quote:
Original post by angelxe1
but all i see when i open the file is a bunch of binary then lena then more binary. (why is lena not in binary?)


It is. "Lena" 'in binary' still looks like "Lena".

Share this post


Link to post
Share on other sites
ohhhh...i get it now.

Washu - Zahlman - thank you for your help. i will consider writing the code again.

Enigma - thanks a million times for helping me through this. by no means did i ever expect you to just tell me the answer. i do want to learn how to do it myself, and i'm glad you think the same way.

wish i had found this board earlier in the school year.

= )

Share this post


Link to post
Share on other sites
i'm working on another program with struct i/o files...and stuck once again. this time with updating one file with another file. so i was wondering are there any tutorials that you guys recomend on this topic? (The ones i have found so far are just not that much help)

Share this post


Link to post
Share on other sites

This topic is 4755 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this