C++ is starting to hurt my eyes!

Started by
5 comments, last by templewulf 18 years, 8 months ago
I've been developing C and CPP applications for a couple of years and just starting trying out game development this year, but I'm having a tough time of it! I have a ton of questions, so buckle up! Is there a way to write a std::string to a file with fstream? When I use it, the data read back is all scrambled, almost as if it's reading in the wrong size. When I use a simple char szBuffer[256], and feed fstream::write() sizeof(szBuffer) as opposed to sizeof(strName), I have no problems. Right now, though, my biggest problem is creating a Win32 Window wrapper class. I'm reading tutorials here and here, but I keep getting an access violation where you're supposed to assign the hwnd in WndProc to the hwnd member of the wrapper class. Any ideas? Thanks, templewulf
XBox 360 gamertag: templewulf feel free to add me!
Advertisement
For the std::string problem, I would just suggest using the c_str() method of the std::string class to convert it to a C-style string.
-----------------------------Play Stompy's Revenge! Now!
Quote:Original post by templewulf
Is there a way to write a std::string to a file with fstream? When I use it, the data read back is all scrambled, almost as if it's reading in the wrong size. When I use a simple char szBuffer[256], and feed fstream::write() sizeof(szBuffer) as opposed to sizeof(strName), I have no problems
templewulf


To get the char* version of an std::string, use the c_str() method of std::string.

Also, typcially the stream operators are used more precedently than the write() method:
fstream file("bla bla bla");string str = "yada yada yada";// Rather thanfile.write(str.c_str());// Usefile << str.c_str();
do not use sizeof to write a string! The string object contains a pointer to a char array. Just write the string the way that it is meant to be written, with the << operator. Now if your string contains whitespace then it complicates matters, and I am sure that there is some way to do it, but I don't remember. The simple answer is don't use sizeof unless you are dealing with legacy code or if you want to implement something in a low level way. If you want to do some low level string handling then get a buffer from the string using c_str().
The std::string is an object which wraps about a pointer to the "real string data" (as well as a count of the length of the string, possibly a count of the allocated space, possibly a small "buffer" used for small strings to avoid the pointer indirection, etc.) In general, structures shouldn't be written directly to disk.

Because a std::string may contain \0 characters, and because its data is not necessarily null-terminated (and because reading in a null-terminated string is messy anyway: when you read something length-counted, you know right away how much space to allocate as well as knowing where to stop, whereas with null-termination you just have to keep going and handle an overflow... somehow), the most general-purpose procedure for "serialization" of std::string would be something like:

Writing: write out the .size() as an int, then write the .data().
Reading: Read an int, allocate a new char[] of that size. Read in that many characters into the buffer (there will not be a \0 at the end! This is a buffer, not a "string"), then construct a string from it (using the (char*, size_t) constructor, not the (char*) one which expects a null-terminated string). Finally, delete[] the buffer.

It's a bit of work, but as a bonus you get to handle strings of any length gracefully (without having to allocate a buffer "of any length", i.e. an ungodly huge one motivated by paranoia - that will ultimately still be too small sooner or later), and null characters within your string (maybe not that useful for most text, but sometimes it's useful to be able to perform "string operations" on "binary data").

Or you could let boost::serialize handle it for you. :)
sizeof() returns the size of the actual object specified, not necessarily the data it represents. In the case of std::string, it is a class that internally contains a pointer to a character array, along with some other stuff, possibly. So when you take the sizeof() the std::string, you are merely getting the size of the class (pointer and some additional info), not the whole character array. That was a much more C-style thing. A std::string, instead, provides a length() function. So you can use strobject.length() to get how long it is.

Additionally, using fstream::write() to write out a string object is also a very C-style process. Streams in C++ are very nice, in that they overload << and >> operators to work with common data types. So to write a std::string to an fstream, all you need to write is
fstreamobject << strobject;
If you really wanted to write the string to the file using the write() function, though, you could use "strobject.c_str()" or "&strobject[0]" to get the pointer to the first character (which is effectively just the array itself in this case), and use strobject.length() to get the number of characters to write.

Also, realize that sizeof() will only work on a character array that has a fixed length at compile time. If the memory is dynamically allocated, sizeof() will return the size of the pointer that points to the array (4 bytes, typically), not the size of the actual array itself. So sizeof() wouldn't be guaranteed to work for you even for normal character arrays. Also, a character array may be longer than the string it represents. A C-string is terminated with a null-zero ('\0'). If the character is 64 bytes long, but the 25th element is a null-zero, then the string represented is only 24 characters long, and everything after that is garbage data, meant to be ignored. But if you do a write using a sizeof(), you'll write the whole thing. In this case, the C function strlen() is what you would use to find the length of the C string.

Yeah, it's probably just a lot of stuff you learn from experience, and reading enough material, whether it be online tutorials, books, forum posts, or documentation. (That last one is a big one. Just browse some reference material sometime, see what's available that you didn't even realize.)

[Now let's see how many people responded before me...]
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Thanks for the help on the string, I just changed it to string::size instead of sizeof and that seemed to fix everything.

How about that Win32 wrapper, though? Does anyone know where that access violation is coming from? (Links to the tutorials and code I'm talking about are on the first post)
XBox 360 gamertag: templewulf feel free to add me!

This topic is closed to new replies.

Advertisement