Just want to iterate through a string :(

Started by
11 comments, last by Domarius 16 years, 11 months ago
Quote:Original post by Domarius
Yeah I did make a typedef :) ... our instructor (back when I used to study) did this so I have just been following suit, everything he does, till I know better.


Consider questioning things openly. Acceptance is not learning. If something is justified, then your instructor should be able to state the justification.

The typedef here might be to allow for changing the underlying type later - I can indeed imagine that happening in at least one way (to std::wstring, for Unicode "support" - and I use the term loosely). It might be to avoid typing std:: everywhere, but there's a better way to do that (a using-declaration: 'using std::string;'). Or it might just be because your instructor thinks the uppercase name looks better. Whatever the case, it's worth finding out what the reasoning actually was.

Quote:
Oh... I am just in the habit of cleaning up everything... if I delete all variables then I want to close all files too... is it bad practice?


In C++, objects are supposed to be designed to clean up their own messes. When you dynamically allocate something, you need to 'delete' it (or 'delete[]' for an array allocation - the two are NOT interchangable), yes; but the way to do things is *not* to try to figure out everywhere the object needs to be cleaned up and insert the call, but instead arrange for it to happen *automatically*, using destructors. That's what they're in the language for.

In the case of iostreams, the destructor simply calls .close() (or has the same effect). The net result is that you don't have to worry about putting in the call at every point where the stream could go out of existence. Because of exceptions, there are actually a LOT more of these than you think. It's inconsistent to handle the "normal" ones explicitly and forget about exception situations; so it makes more sense to not handle anything explicitly at all - why do extra work that accomplishes nothing?

Done properly, we accomplish a very powerful idiom called RAII - Resource Acquisition Is Initialization - a misnomer, because the idiom is usually seen as much more about the cleanup than it is about the setup (which is "obvious"). Example. (As you can tell from my sig, I'm quite fond of this particular example ;) ) What's going on is that, because the string's destructor deallocates the memory, we don't have to and shouldn't think about that task. It's not the responsibility of our code.

Quote:
But I have a very specific format of CSV for this app I'm making (my app cannot make use of any other format - must have string, string, int, int for each row), and while it would be more reliable to use that CSV thing I downloaded, I wouldn't be learning much, except how to use someone elses class.


If it's your file format, don't feel compelled to emulate CSV in any way, shape or form. Use things that are easy to parse naturally in C++. Reading up until a specific character is easy (just specify that third argument for std::getline :) ), and reading ints that are separated by whitespace is easy. If possible, use a character to separate the strings that can't appear within them - you can choose what you like, after all.

If there is no such character, then you will need some sort of escaping system. You might want to consider how the C++ language itself does things in its syntax - that way is really robust (you can be sure that every possible string is representable), but it's hard to parse from within C++ (maddeningly enough). A simpler way is to treat a doubled-up separator as an escape code for the separator: after reading up to a separator, check if the next "item" is empty, and if it is, append the separator character and keep going. However, this way will not allow you to represent empty strings. But in general, try to avoid scanning the thing character by character; it's usually too much work. (Although it *is* pretty much required for the C++-syntax-style approach.)
Advertisement
Thanks Zahlman, this has been very informative.

Quote:Original post by Zahlman
Consider questioning things openly. Acceptance is not learning. If something is justified, then your instructor should be able to state the justification.
Oh by that I did not mean I was blindly following what I was told - all I meant that I was just doing it for now - till I get in contact with him again or find out for myself, hence the "till I know better". :) I'll email him right now.

Quote:In C++, objects are supposed to be designed to clean up their own messes. When you dynamically allocate something, you need to 'delete' it (or 'delete[]' for an array allocation - the two are NOT interchangable), yes; but the way to do things is *not* to try to figure out everywhere the object needs to be cleaned up and insert the call, but instead arrange for it to happen *automatically*, using destructors. That's what they're in the language for.

I understand now. I guess some "legacy" habits are coming into play there. I see now that we consider the open file, part of the object, and hence, will be taken care of, just like all other objects, when we call "delete" on it.

Quote:If it's your file format, don't feel compelled to emulate CSV in any way, shape or form. Use things that are easy to parse naturally in C++. Reading up until a specific character is easy (just specify that third argument for std::getline :) ), and reading ints that are separated by whitespace is easy. If possible, use a character to separate the strings that can't appear within them - you can choose what you like, after all.

If there is no such character, then you will need some sort of escaping system. You might want to consider how the C++ language itself does things in its syntax - that way is really robust (you can be sure that every possible string is representable), but it's hard to parse from within C++ (maddeningly enough). A simpler way is to treat a doubled-up separator as an escape code for the separator: after reading up to a separator, check if the next "item" is empty, and if it is, append the separator character and keep going. However, this way will not allow you to represent empty strings. But in general, try to avoid scanning the thing character by character; it's usually too much work. (Although it *is* pretty much required for the C++-syntax-style approach.)


The reason I chose CSV is because it's a format I am familiar with, and I like to use supported formats if I can - I will have the option to play with the values using Excel, for debugging purposes. It's just the principal of choosing a widely used format, really - leaves options :) No it's not extensively thought out - I just didn't see it being much trouble to use a CSV file so I thought I may as well.

But that part of your post gave me something to think about. I can see how all these string functions have been created to save us scanning character by character ourselves, it keeps code simpler.
But this is such a small app with a very finite use, and the logic seems to be working - it seemed to be finding the right amount of words and using the quotes to ignore commas - I just couldn't store the characters in the string. But I will in a moment, I expect.

[Edited by - Domarius on May 5, 2007 2:05:50 AM]

For local multiplayer retro themed games, visit Domarius Games.

Thanks everyone for their help - I went with the for loop method rather than the pointer arithmetic method, everything is fine now, and I found one of the crashes to be from sending the log function a string instead of a char array, ie. I was missing the bit in bold;

std::string text= "hello";
hge->System_Log("%s", text.c_str());

For local multiplayer retro themed games, visit Domarius Games.

This topic is closed to new replies.

Advertisement