I tried my best on an informative title there, sorry if it's too long.
I'm working on an assignment for a CIS class on OOP using C++. For this class, we are usually required to implement a header that's provided without modifying it or #include
ing any additional libraries. This current assignment is to add a void Read(std::ifstream&)
and void Write(std::ofstream&)
function to a Vector class that we implemented for the previous assignment.
The requirements are:
- All files must be opened in binary mode.
- The write function must write the internal array of type T to a file
- The read function must read the file into an array of type T.
It's not specified what's to be done with the array that's read from the input file. My assumption would be that a reference would be returned, but the return type of read()
is specified in the assignment as void
. My best guess is that my professor is just interested in having us demonstrate the ability to read into an array, so that's what I'm shooting for. I've also considered concatenating the input file's array to the end of whichever vector object calls read(), but I don't think that's important so I digress.
I believe I've got write() in a solid place. This is what I'm working with at the moment: Write() is busted, I'll explain after code:
306 template <class T> void Vector<T>::Write (std::ofstream& ofile) const
307 {
308 if (!ofile.is_open()) ofile.open("vector.bin", std::ios::trunc | std::ios::binary);
309
310 if (ofile.is_open())
311 {
312 ofile.write((char*)&m_array, sizeof(m_array));
313 } else throw -6;
314
315 ofile.close();
316 }
When write() runs, it does so without error but it writes something pretty far from correct into the output file. Say m_array contains {2, 8, 16, 4}. The output file will contain:
01000000 00010000 00001000 00100000
when it should contain (assuming sizeof(int) is 4, which I know I shouldn't assume, but you get the idea):
01000000 00000000 00000000 00000000
00010000 00000000 00000000 00000000
00001000 00000000 00000000 00000000
00100000 00000000 00000000 00000000
It seems like when I cast m_array to a char*, my computer is being a smarty-pants and realizing that the char represented by the number 4 doesn't take 4 bytes to store.
I've got something that's sort of on the way to working that involves something like:
void* temp = m_array;
char* buffer = (char*)temp;
which seems to help the compiler forget that 4 bytes in m_array actually represent one element. It just feels so ugly, I feel like there has to be a logical way to do this or it wouldn't be an assignment in an introductory C++ class.
Anyway, the issue that I'm having is with the read function. If I'm correct, a vector object as they're implemented according to this assignement will only be able to read from a file that that particular object wrote to. If an algorithm written to read ints tries to read from a file that a Vector wrote to, it's just going to get garbage, right? That's one of the big challenges that I'm having, writing an algorithm that will be able to read from a file into an array of type T, regardless of the actual number of bytes required to express T.
The track I'm on right now is to do something like the following:
T temp;
char* buffer = new char[sizeof(T)];
// Loop the following for the entire file
ifile.read(buffer, sizeof(T));
temp = T(*buffer); // I know this won't work, this is what I'm trying to get at
If I'm understanding correctly, this will allow me to read the right amount of bytes into a char array. For example, if an arrray of int
s were written to a file, it would read two bytes and store it in an array of char
s two long. My buffer variable would then contain exactly the data I want.
How the heck do I get that data into temp!?!?
I'm going crazy here, especially because I know that atoi would work nicely, or at least merit some investigation. I don't think that would solve my problem of working for any of the primitive data types, but it'd at least be a start. I'm pulling my hair out because I've got an array of two bytes, if I put them together I'd have the int I want, but I just can't figure out how the heck to put them together. Am I going about this all the wrong way? Is this a ridiculous way to try to read from a binary file?
Can I just do something like temp = *(int*(buffer))
? That seems pretty ugly to me, and I'd much rather understand the right way to do things than try every crazy idea until something compiles.
Thanks a lot for reading my word salad.