On May 30, 5:18 pm, coomberjo...@gmail.com wrote:
> On May 30, 4:47 am, James Kanze <james.ka...@gmail.com> wrote:
> > On May 29, 11:36 pm, coomberjo...@gmail.com wrote:
> > > I have a few std::strings that I am using to store raw binary
> > > data, each of which may very well include null bytes at any
> > > point or points.
> > As others have pointed out, that's probably a design error.
> > However...
> I guess I don't understand why. Strings are designed to be
> able to handle binary data, including nulls.
It gives the wrong message. For better or for worse, the name
string suggests text data of some sort; there might be reasons
for inserting '\0' characters into text data, but it is still
text data.
Of course, the actual interface of std::string doesn't really do
much to support text (as opposed to just any data), but then, it
doesn't really do much to make it preferable to std::vector---in
fact, I find in practice that I'm often drawn to using
std::vector< char > for my strings, because it corresponds
better to what I'm doing.
> > > I want to slap them together into a single string, so I
> > > tried a std:
stringstream:
> > And concatenation would be a lot more reasonable.
> I guess I don't understand why.
Because that's the way you concatenate strings, normally.
ostringstream is for formatting: converting non-text into text,
more or less (but also e.g. ensuring field widths, etc.). If
you're not actually formatting, using it passes the wrong
message to the reader.
> I understand that concatenation will achieve the result I
> want, but I don't get why it's "a lot more reasonable". They
> both (seemingly) should accomplish the same thing: slap these
> three strings together into one string.
That's not what ostringstream says. Ostringstream says format
this data to a specific textual format.
> > > std:
stringstream oss;
> > > oss << x << y << z;
> > > std::string result ( oss.str() );
> > > The result shows that feeding the ostringstream with a string
> > > just takes the string's data up to (and not including) the
> > > first null character.
> > With what implementation?
> Microsoft Visual C++ 6.0.
Don't put '\0' characters in an std::string with VC++ 6.0.
Period. It's not just ostringstream which doesn't work; it's a
lot of the functions. And it often results in program crashes,
not just incorrect results. This is a known bug, which has been
fixed.
> > And of course, no one uses such an old compiler.
> Unfortunately for me, you're wrong.
No one should. The compiler is something like 10 years old. It
was a very good compiler when it came out, but the situation has
evolved considerably since then: we have an ISO standard, and we
make far more extensive use of templates than we did back then.
And of course, Microsoft offers the newer versions free, so
there's absolutely no reason for not upgrading.
> > > Stroustrop's book is vague about what should happen (at least
> > > in the sole reference I could find); it merely says "The <<
> > > operator writes a string to an ostream".
> > What more should it say?
> If the behavior is supposed to be as VC++ 6.0 is doing (and to
> be clear, I'm not saying it's supposed to be that way), then
> it should explicitly say "writes the contents of a string, up
> to but not including the first null, to an ostream". Because
> it is NOT doing what it says - i.e. "writing a string". It's
> writing PART of a string.
Yes and no. VC++ 6.0 doesn't support null characters in
strings, period. That's an error in the library implementation.
But since they don't support null characters in strings, they're
effectively copying all of the string.
> > Note that an arbitrary ostream may not be able to handle a '\0';
> > an ofstream opened in text mode, for example, is only required
> > to handle printable characters and a small set of control
> > characters ('\n', '\t', etc.), and some of these (e.g. '\n') may
> > have special behavior. But an ostringstream can handle anything
> > a string can handle, and a string can obviously handle '\0'.
> Which is what I had in mind when I originally coded it. But
> that's not how it has worked out.
That's because you're using a pre-standard compiler. There are
a lot of things that "won't work out as expected" with VC++ 6.0,
if you expect standard C++. (Remember, the compiler is older
than the standard.)
> > I'm wondering how you actually determined that there was a
> > problem.
> I did what I said: I had three strings, one of which contained
> a null, and I fed them into an ostringstream, exactly as
> described. And the result was that, for the string that
> contained a null, the output only included up to the null.
> I'm having a hard time understanding what you're not getting
> about that.
What output? What did you do to determine that the result was
shorter than it should be? (Of course, if you're using VC++
6.0, the only thing that surprises me here is that it didn't
actually crash.)
> > Did you, per chance, use some other function which
> > does treat '\0' specially?
> I did exactly what I said: Slapped three strings together
> using an ostringstream.
But how did you determine the results? From the code you
posted, it's impossible to say what you're actually seeing.
> > Because it's clear that in this case, '\0' is just a
> > character like another, and I can't find an implementation
> > where this isn't the case.
> Well, there is one.
There was one. There were, in fact, a lot of them, many years
back. I don't know of any in the last ten years, however.
--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34