So I\'m having a bit of an issue of not being able to properly read a binary file into my structure. The structure is this:
struct Student
{
char name[25];
There is more than one way to solve the problem of this thread. Here is a solution based on using union of a struct and a char buf:
#include
#include
#include
#include
/*
This is the main idea of the technique: Put the struct
inside a union. And then put a char array that is the
number of chars needed for the array.
union causes sStudent and buf to be at the exact same
place in memory. They overlap each other!
*/
union uStudent
{
struct sStudent
{
char name[25];
int quiz1;
int quiz2;
int quiz3;
} field;
char buf[ sizeof(sStudent) ]; // sizeof calcs the number of chars needed
};
void create_data_file(fstream& file, uStudent* oStudent, int idx)
{
if (idx < 0)
{
// index passed beginning of oStudent array. Return to start processing.
return;
}
// have not yet reached idx = -1. Tail recurse
create_data_file(file, oStudent, idx - 1);
// write a record
file.write(oStudent[idx].buf, sizeof(uStudent));
// return to write another record or to finish
return;
}
std::string read_in_data_file(std::fstream& file, std::stringstream& strm_buf)
{
// allocate a buffer of the correct size
uStudent temp_student;
// read in to buffer
file.read( temp_student.buf, sizeof(uStudent) );
// at end of file?
if (file.eof())
{
// finished
return strm_buf.str();
}
// not at end of file. Stuff buf for display
strm_buf << std::setw(25) << std::left << temp_student.field.name;
strm_buf << std::setw(5) << std::right << temp_student.field.quiz1;
strm_buf << std::setw(5) << std::right << temp_student.field.quiz2;
strm_buf << std::setw(5) << std::right << temp_student.field.quiz3;
strm_buf << std::endl;
// head recurse and see whether at end of file
return read_in_data_file(file, strm_buf);
}
std::string quiz(void)
{
/*
declare and initialize array of uStudent to facilitate
writing out the data file and then demonstrating
reading it back in.
*/
uStudent oStudent[] =
{
{"Bart Simpson", 75, 65, 70},
{"Ralph Wiggum", 35, 60, 44},
{"Lisa Simpson", 100, 98, 91},
{"Martin Prince", 99, 98, 99},
{"Milhouse Van Houten", 80, 87, 79}
};
fstream file;
// ios::trunc causes the file to be created if it does not already exist.
// ios::trunc also causes the file to be empty if it does already exist.
file.open("quizzes.dat", ios::in | ios::out | ios::binary | ios::trunc);
if ( ! file.is_open() )
{
ShowMessage( "File did not open" );
exit(1);
}
// create the data file
int num_elements = sizeof(oStudent) / sizeof(uStudent);
create_data_file(file, oStudent, num_elements - 1);
// Don't forget
file.flush();
/*
We wrote actual integers. So, you cannot check the file so
easily by just using a common text editor such as Windows Notepad.
You would need an editor that shows hex values or something similar.
And integrated development invironment (IDE) is likely to have such
an editor. Of course, not always so.
*/
/*
Now, read the file back in for display. Reading into a string buffer
for display all at once. Can modify code to display the string buffer
wherever you want.
*/
// make sure at beginning of file
file.seekg(0, ios::beg);
std::stringstream strm_buf;
strm_buf.str( read_in_data_file(file, strm_buf) );
file.close();
return strm_buf.str();
}
Call quiz() and receive a string formatted for display to std::cout, writing to a file, or whatever.
The main idea is that all the items inside a union start at the same address in memory. So you can have a char or wchar_t buf that is the same size as the struct you want to write to or read from a file. And notice that zero casts are needed. There is not one cast in the code.
I also did not have to worry about padding.
For those who do not like recursion, sorry. Working it out with recursion is easier and less error prone for me. Maybe not easier for others? The recursions can be converted to loops. And they would need to be converted to loops for very large files.
For those who like recursions, this is yet another instance of using recursion.
I don't claim that using union is the best solution or not. Seems that it is a solution. Maybe you like it?