Quote:Original post by p0is0n
Ok, I think i'm being stupid again and completely missing something.
The code I have seems to work for everything apart from strings (std::string).
char name[255] = {0};
m_file.read(name, length);
This fills the char array with the desired filename (read from a binary file using std::istream).
I was wondering what I would need to do to have say :
std::string name = "";
m_file.read(name, length);
The only way I seem to be able to get rid of the compiler errors is to use :
std::string name = "";
m_file.read(reinterpret_cast<char*>(&name), length);
Which gives "" as the output even though the bytes are read from the file. I'm sure there is a very good reason for this, but what that reason is I don't know at the moment.
I'm guessing i'm completely overlooking something obvious and simple, but would just like to know if anyone knows how to accomplish what I am trying to do.
Any help/advice would be much appreciated.
Thanks!
You're not being stupid, but you are missing a hell of a lot. :)
You can only use .read() to read into POD structs. It only accepts a char* pointer, and you read into POD structs by casting the pointer. In effect, you give the instruction "write to memory one byte at a time, starting at the beginning of this object in memory".
A std::string does not qualify as a POD. Its data layout may contain different things depending on your implementation, and you're not entitled to know exactly what's in it. It certainly does not just contain the text "directly", starting at the beginning of the structure, because in C++, objects must have a known-at-compile-time size. Thus a std::string instance will generally manage a pointer to some kind of dynamic memory allocation. When you use .read() to read over (not "into", really) the std::string, you can easily overwrite this pointer and screw everything up.
That's the practical view. The official view given by the language standard is that
absolutely anything is allowed to happen at this point. This is what we call Undefined Behaviour, and it's a very bad thing.
By the way, the .read() member function DOES NOT put a null terminator at the end of the data. In your case, this is not a problem because your buffer is initialized to all zeros. However, your buffer MUST have room for a null terminator at the end; since you declared a buffer of 255 chars, 'length' can be at most 25
4. And you should be aware that you cannot return the buffer from the function, either.
Anyway, back to std::strings.
If you want to read one word from the file, just use the operator>> overload for std::string:
m_file >> name;
If you want to read one line from the file - or in general, everything up to the first occurrance of a specific character, use the free function std::getline:
getline(m_file, name); // reads up to the first occurance of '\n'getline(m_file, name, ','); // reads up to the first comma
If you want to read a specific number of characters from the file and create a string from them, you will need a temporary buffer, which you then use to either construct or assign the string:
// With a character count that is KNOWN AT COMPILE-TIME ONLYchar buffer[NAMES_ARE_ALWAYS_EXACTLY_THIS_LENGTH];m_file.read(buffer, NAMES_ARE_ALWAYS_EXACTLY_THIS_LENGTH);// Notice that in this case you DON'T need room for a null terminator, because// you can tell the std::string how long the string is.// Construction:std::string name(buffer, buffer + NAMES_ARE_ALWAYS_EXACTLY_THIS_LENGTH);// Assignment:name.assign(buffer, buffer + NAMES_ARE_ALWAYS_EXACTLY_THIS_LENGTH);// With a character count that is determined at runtime, or a known-at-compile-time length:std::vector<char> buffer(length);m_file.read(buffer, length);// Construction:std::string name(buffer.begin(), buffer.end());// Assignment:name.assign(buffer.begin(), buffer.end());