std::string and iostreams

Started by
2 comments, last by Kylotan 22 years, 8 months ago
Ok, there''s one thing that bothers me about this combination. When you use a string that contains spaces, you lose the symmetry between the << and the >> operators. Example: if I use << to write "this is a string" to a stream, it will take 4 uses of the >> operator to get that string back. So, in an application where you write arbitrary strings to a stream, there is no way of being able to load them back reliably. An std::string is capable of storing the \0 character, as well as \n etc. This means you can''t assume the string will be null-terminated (you wouldn''t want it to be that way in a text file anyway), nor can you use getline with the default of \n since you might have newlines within the string itself. I suppose you have to choose an arbitrary method for yourself: either writing out the length of the string first, like Pascal stores its strings, or choosing a delimiting character. Personally, I find it very surprising that there is apparently no standard way of doing this provided by the standard library. My personal solution goes something like this: 1) Pick an arbitrary delimiter. I use a tilde (~) purely because that is what I was used to from my MUD background. 2) For each instance of the delimiter character in the string you want to save, double it up. 3) Write the string as processed by step 2, plus a delimiter character at the end. 4) To read the string, you call getline with the delimiter you specified. 5) If the next character in the stream is also the delimiter, that means it has been doubled up by step 2 above, so add the delimiter character to the string, and repeat from step 4, appending to the string. 6) Otherwise, you''ve reached the end of the string and you''re done. This works for me in all situations I have used it in, but I can see one where it would not: if there were 2 strings in a row, and the second one actually began with the delimiter character. It could be possible to get around this by ensuring there was some whitespace after the delimiter at the end of a string, but then this precludes me from being able to have whitespace at the start of a string! Do you see the complications? So, I''m very interested to know how any of you have approached (or sidestepped!) this problem. String and stream handling is very important to me in everything I do and so if there''s an ''optimal'' solution out there, I want to hear of it!
Advertisement
That''s a reason to choose binary over text mode.

If text mode is a must, you need to come up with some formatting guidelines.

What I use is
1. Every string message must start on a newline in the text file.
2. Each string is terminated with a ''\0''.
3. The next entry must begin on the next line.
4. Other type of data must begin on a newline each.

i.e.

1 2 3
This is a string\0 <-- A string message is stored like that
4 5 6

If you edit the file in notepad, it will insert additional ''\n'' chars automatically when you save. Using wordpad avoids the problem.


Taking this idea even furthur, I came up with a binary stream class that can read/write in both text and binary mode using the same piece of code if data formatted in the above manner.

It is located at http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-BinaryIO&forum=cotd&id=-1

There is a minor problem there and requires a simple fix. I can send you the updated version if you like.
Perhaps I wasn''t totally clear... the problem is writing plain text files. For example, writing .INI files, or HTML files, or whatever. If I was happy writing a binary file, I would just null-terminate it, and read with ''getline'' up to the first \0, so there would be absolutely no problem. One function to read a string, one function to write one. But adding \0 means it''s no longer a plain text file and defeats the purpose of what I''m trying to achieve. Despite all the other iostreams functionality designed to make reading and writing text files so much easier, it just seems that strings were somewhat neglected!
I see.

If you are writing ini files, then you should know how many lines in the text file each entry would take, even if they are string value.

For variable strings which may contain \n, maybe output a #of chars before outputting the string.

..

This topic is closed to new replies.

Advertisement