Topic: string with '\0' inside


Author: rogero@howzatt.demon.co.uk (Roger Orr)
Date: Thu, 16 Aug 2001 16:38:23 GMT
Raw View
Wernfried Schwenkner <wernfried.schwenkner@sesa.de> wrote in message news:<bu7dl9.uae.ln@news.bln.sesa.de>...
> I noticed a problem putting '\0' character into std::strings and now I
> don't know wether it is C++ conform or a compiler bug (seen on VC++).
>
> I've done the following:
>
> std::string test;
>
> test += 'a';
> test += '\0';
> test += 'b';
>
> Doing an output with
>
> std::cerr << test << std::endl;
>
> only an 'a' is displayed, I'd expeted somewhat unpritable for the '\0'
> character and then a 'b'.

Just curious - what version of VC++ are you using (I've tested it with
VC 5,
which I had handy, and it worked just fine)

Note too that although the C++ string class will let you read and
write the \0 character you might get into problems if you mix this
with anything using either the older C functions or 'char *' style
strings.

Roger Orr
--
MVP in C++ at brainbench.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Barry Margolin <barmar@genuity.net>
Date: Thu, 16 Aug 2001 18:23:00 GMT
Raw View
In article <remove.haberg-1608010031390001@du128-226.ppp.su-anst.tninet.se>,
Hans Aberg <remove.haberg@matematik.su.se> wrote:
>In fact, I think C++ should supply a way to pick up the length of string
>literals: I use a Flex/Bison combination which generates a parser that
>write C++ code, which is somewhat roundabout.

Doesn't 'sizeof "a\0b"' evaluate to 3?

On the other hand, if you do:

cons char *s = "a\0b";

and want some operator that takes s and returns 3, that's harder.  I
suppose the length could be stored somewhere, e.g. right before the
literal's storage.  But then what happens if you do:

t = s+1;

and pass t to this mythical operator?  Would it only be defined if you pass
a pointer to the beginning of a literal?  C and C++ allow literals to share
storage, e.g. if you do:

const char *s = "abc\0d";
const char *t =   "c\0d";

then s+2 == t is permitted.  Retaining this would necessitate a more
complicated implementation of the literal_size operator.

--
Barry Margolin, barmar@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Kevlin Henney <kevlin@curbralan.com>
Date: Thu, 16 Aug 2001 20:13:13 GMT
Raw View
In article <lZTe7.9$ku5.236@burlma1-snr2>, Barry Margolin
<barmar@genuity.net> writes
>Doesn't 'sizeof "a\0b"' evaluate to 3?

No, 4. Here is an as-if expansion of what the compiler might see:

        const char __tmp[] = {'a', '\0', 'b', '\0'};
        ... sizeof __tmp ...

The problem is one of presentation not of representation. In the
original problem, string was behaving itself, reporting the correct
length, and so on, but the print out was not what was expected. The
embedded '\0' is a control character, and the standard makes no
representation (sic) as to what happens on the console output when you
start throwing control characters into the stream.

Kevlin
____________________________________________________________

  Kevlin Henney                   phone:  +44 117 942 2990
  mailto:kevlin@curbralan.com     mobile: +44 7801 073 508
  http://www.curbralan.com        fax:    +44 870 052 2289
  Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: comeau@panix.com (Greg Comeau)
Date: Thu, 16 Aug 2001 20:28:23 GMT
Raw View
In article <lZTe7.9$ku5.236@burlma1-snr2>,
Barry Margolin  <barmar@genuity.net> wrote:
>In article <remove.haberg-1608010031390001@du128-226.ppp.su-anst.tninet.se>,
>Hans Aberg <remove.haberg@matematik.su.se> wrote:
>>In fact, I think C++ should supply a way to pick up the length of string
>>literals: I use a Flex/Bison combination which generates a parser that
>>write C++ code, which is somewhat roundabout.
>
>Doesn't 'sizeof "a\0b"' evaluate to 3?

No, 4.

>On the other hand, if you do:
>
>cons char *s = "a\0b";
>
>and want some operator that takes s and returns 3, that's harder.

Certainly nothing C or C++ allows you to programmatically detect
that you've done so, so figuring it out would need to be done
in some other manner, through a compiler extension or some scheme
you've figured out.

>I
>suppose the length could be stored somewhere, e.g. right before the
>literal's storage.  But then what happens if you do:
>
>t = s+1;

Right, neither C nor C++ is conducive to this, w/o some change
to those standards.  OTOH, that's what std::string's are for.

>and pass t to this mythical operator?  Would it only be defined if you pass
>a pointer to the beginning of a literal?  C and C++ allow literals to share
>storage, e.g. if you do:
>
>const char *s = "abc\0d";
>const char *t =   "c\0d";
>
>then s+2 == t is permitted.  Retaining this would necessitate a more
>complicated implementation of the literal_size operator.

std::string std::string std::string std::string.... :)
--
Greg Comeau                 Countdown to "export": December 1, 2001
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries.  Have you tried it?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: Thu, 16 Aug 2001 20:38:20 GMT
Raw View
In article <lZTe7.9$ku5.236@burlma1-snr2>, Barry Margolin
<barmar@genuity.net> wrote:
>>In fact, I think C++ should supply a way to pick up the length of string
>>literals...
...
>Doesn't 'sizeof "a\0b"' evaluate to 3?

In fact, one has to add one; see verse 2.13.4:5, last sentence.

One can pick it up in a std::string by the macro:

#include <cstddef>
#include <string>

#define string_literal(name, s)  const std::string name(s, sizeof(s) - 1);

Then the program:

#include <iostream>

int main() {
  string_literal(str, "a\0b");

  std::cout << "size = " << str.size() << std::endl;
  std::cout << "name = " << str << "." << std::endl;

  return 0;
}

produces the output:
  size = 3
  name = ab.
with my compiler.

-- It remains only to extend C++ so that one can add a constructor say
  std::string::string(const char[]);
to the string class that only applies to string literals, and not to
character pointers.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: comeau@panix.com (Greg Comeau)
Date: Fri, 17 Aug 2001 05:39:14 GMT
Raw View
In article <remove.haberg-1608012233170001@du128-226.ppp.su-anst.tninet.se>,
Hans Aberg <remove.haberg@matematik.su.se> wrote:
>In article <lZTe7.9$ku5.236@burlma1-snr2>, Barry Margolin
><barmar@genuity.net> wrote:
>>>In fact, I think C++ should supply a way to pick up the length of string
>>>literals...
>One can pick it up in a std::string by the macro:
>
>#include <cstddef>
>#include <string>
>
>#define string_literal(name, s)  const std::string name(s, sizeof(s) - 1);
>
>Then the program:
>
>#include <iostream>
>
>int main() {
>  string_literal(str, "a\0b");
>
>  std::cout << "size = " << str.size() << std::endl;
>  std::cout << "name = " << str << "." << std::endl;
>
>  return 0;
>}

Why won't std::string get the right size anyway?

>produces the output:
>  size = 3
>  name = ab.
>with my compiler.

Comeau C++ (both with libcomo, and with Dinkumware) both emit
the same output.  But as Kevlin noted, be careful here.
In other words, if you were to look at the output in say
a hex editor the null byte is still there.

>-- It remains only to extend C++ so that one can add a constructor say
>  std::string::string(const char[]);
>to the string class that only applies to string literals, and not to
>character pointers.

Well, in the spirit of C99 allowing some keywords in []'s,
it would be: std::string::string(const char[literal]);

But one would do this because?
--
Greg Comeau                 Countdown to "export": December 1, 2001
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries.  Have you tried it?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Wernfried Schwenkner <wernfried.schwenkner@sesa.de>
Date: Fri, 17 Aug 2001 16:29:53 CST
Raw View
In article <7a474e76.0108160645.db43b05@posting.google.com>,
rogero@howzatt.demon.co.uk says...
> Just curious - what version of VC++ are you using (I've tested it with
> VC 5,
> which I had handy, and it worked just fine)

Yes, that's curious. So here is my sample code. I use VC 6.0 SP5.

#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
 std::string g;
 g += 'a';
 g += '\0';
 g += 'b';
 std::cerr << g << " " << g.size() << std::endl;
 for (std::string::iterator i1 = g.begin(); i1 != g.end(); ++i1)
 std::cerr << *i1 << std::endl;
 return 0;
}

The output (copied from clipboard) is:
++++++
a 3
a

b
++++++

--
Sleepless in Berlin
Wernfried

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@sensor.com>
Date: Fri, 17 Aug 2001 21:41:03 GMT
Raw View

Wernfried Schwenkner wrote:

>
> int main(int argc, char* argv[])
> {
>         std::string g;
>         g += 'a';
>         g += '\0';
>         g += 'b';
>         std::cerr << g << " " << g.size() << std::endl;
>         for (std::string::iterator i1 = g.begin(); i1 != g.end(); ++i1)
>         std::cerr << *i1 << std::endl;
>         return 0;
> }

As I suggested before.  Either the std::string ostream operator<<
is defective and gagging on the null, or the whatever system
output driver you have is.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@spamcop.net>
Date: Sat, 18 Aug 2001 12:48:53 GMT
Raw View

Greg Comeau wrote:
>
>
> Comeau C++ (both with libcomo, and with Dinkumware) both emit
> the same output.  But as Kevlin noted, be careful here.
> In other words, if you were to look at the output in say
> a hex editor the null byte is still there.

This is very telling.  I also remember using a system (an early
UNIX) where the TTY driver used to not emit anymore data on a given
line once a null was written with it.

While std::string and the iostreams handle nulls probably OK, you
have to make sure whatever you are examining the output with doesn't
treat them badly.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: Sat, 18 Aug 2001 12:47:58 GMT
Raw View
In article <9lhdr8$q1t$1@panix3.panix.com>, comeau@comeaucomputing.com wrote:
>>-- It remains only to extend C++ so that one can add a constructor say
>>  std::string::string(const char[]);
>>to the string class that only applies to string literals, and not to
>>character pointers.
>
>Well, in the spirit of C99 allowing some keywords in []'s,
>it would be: std::string::string(const char[literal]);
>
>But one would do this because?

I arrived it because I wanted in my own OOPL that identifiers are allowed
to be arbitrary strings. These names are then mangled into C++
identifiers, but I also wanted a runtime lookup system for methods, which
retains the original name. An example of an identifier with a '\0' in it
might be written as `a\0b' in this language, will be treated as the string
of the characters 'a', '\0', 'b' and may be used as any other identifier.

But I figure that the feature might be useful in other situations where
one wants to generate sequence of bytes.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: Sat, 18 Aug 2001 12:49:32 GMT
Raw View
Hans Aberg <remove.haberg@matematik.su.se> wrote:

> -- It remains only to extend C++ so that one can add a constructor say
>   std::string::string(const char[]);
> to the string class that only applies to string literals, and not to
> character pointers.

But you (almost) can do that now. You can't restrict arguments to
literals, but you can restrict them to a type that allows string
literals, but not character pointers - and you can allow the function
call to pick up the length at compile time.

Thus your macro (which compiles but misbehaves, if passed a character
pointer) is better replaced by something like:

template<typename CharT, std::size_t N>
std::basic_string<CharT>=20
   literal_string(CharT const (&array)[N])
   {
      return std::basic_string<CharT>(array, N);
   }

Regards, Joerg

--=20
J=F6rg Barfurth                         joerg.barfurth@attglobal.net
<<<<<<<<<<<<< using std::disclaimer;  <<<<<<<<<<<<<<<<<<<<<<<<<<<<
Software Developer                    http://www.OpenOffice.org
StarOffice Configuration              http://www.sun.com/staroffice

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Bill Wade <wrwade@swbell.net>
Date: Sat, 18 Aug 2001 12:50:18 GMT
Raw View
"Greg Comeau" <comeau@panix.com> wrote

> Well, in the spirit of C99 allowing some keywords in []'s,
> it would be: std::string::string(const char[literal]);
>
> But one would do this because?

One might COW literals.  No need for reference counting.  No MT issues.

Of course when the writer of the core compiler is the writer of the library,
he can already do this for std::string.  No need for a language extension.
But the language extension would be convenient for library writers who want
to do this but don't want to write the core compiler also.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Christopher Eltschka <celtschk@web.de>
Date: Sat, 18 Aug 2001 17:04:49 GMT
Raw View
remove.haberg@matematik.su.se (Hans Aberg) writes:

> In article <lZTe7.9$ku5.236@burlma1-snr2>, Barry Margolin
> <barmar@genuity.net> wrote:
> >>In fact, I think C++ should supply a way to pick up the length of string
> >>literals...
> ...
> >Doesn't 'sizeof "a\0b"' evaluate to 3?
>
> In fact, one has to add one; see verse 2.13.4:5, last sentence.
>
> One can pick it up in a std::string by the macro:
>
> #include <cstddef>
> #include <string>
>
> #define string_literal(name, s)  const std::string name(s, sizeof(s) - 1);
>
> Then the program:
>
> #include <iostream>
>
> int main() {
>   string_literal(str, "a\0b");
>
>   std::cout << "size = " << str.size() << std::endl;
>   std::cout << "name = " << str << "." << std::endl;
>
>   return 0;
> }
>
> produces the output:
>   size = 3
>   name = ab.
> with my compiler.

You know, macros are evil :-)

What about:

template<std::size_t Size>
 std::string string_literal(char(&str)[Size])
{
  return std::string(str, size);
}

Indeed, this could have been an additional constructor of std::string:

namespace std
{
  template<class _Char, class _Traits> class string
  {
    template<size_t _Size> string(_Char(&)[_Size]);
    // ...
  }
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: comeau@panix.com (Greg Comeau)
Date: Sun, 19 Aug 2001 12:01:51 GMT
Raw View
In article <3B7D3402.F30F82AA@spamcop.net>,
Ron Natalie  <ron@spamcop.net> wrote:
>Greg Comeau wrote:
>> Comeau C++ (both with libcomo, and with Dinkumware) both emit
>> the same output.  But as Kevlin noted, be careful here.
>> In other words, if you were to look at the output in say
>> a hex editor the null byte is still there.
>
>This is very telling.  I also remember using a system (an early
>UNIX) where the TTY driver used to not emit anymore data on a given
>line once a null was written with it.
>
>While std::string and the iostreams handle nulls probably OK, you
>have to make sure whatever you are examining the output with doesn't
>treat them badly.

Indeed.  Furthermore, on the opposite side of things,
I've seen some I/O systems bug out over nulls in the _input_
with stdio and others.
--
Greg Comeau                 Countdown to "export": December 1, 2001
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Kevlin Henney <kevlin@curbralan.com>
Date: Mon, 20 Aug 2001 00:19:59 GMT
Raw View
In article <t33d6ppch9.fsf@watts.itp.tuwien.ac.at>, Christopher Eltschka
<celtschk@web.de> writes
>What about:
>
>template<std::size_t Size>
> std::string string_literal(char(&str)[Size])
>{
>  return std::string(str, size);
>}

You will need to add a 'const' to this, because string literals are
const char arrays. Although they have a deprecated conversion to non-
const, this works only where they are used as values not as references,
ie you cannot bind a char *& or char (&)[] to a string literal.

Kevlin
____________________________________________________________

  Kevlin Henney                   phone:  +44 117 942 2990
  mailto:kevlin@curbralan.com     mobile: +44 7801 073 508
  http://www.curbralan.com        fax:    +44 870 052 2289
  Curbralan: Consultancy + Training + Development + Review
____________________________________________________________

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "THOMAS GULBRANDSEN" <thomas.gulbrandsen@c2i.net>
Date: Mon, 20 Aug 2001 00:33:45 GMT
Raw View
When you write std::cerr << test << std::endl, your compiler will call a
function called
operator<< that has a body _O << _X.cstr();where _O is a basic_ostream, like
cerr or cout,
and _X is a basic_string, like std::string(which is realt defined like this:
typedef basic_string<char*> string)
If you examine this you will se that cerr << test is somewhat similar to
cerr << test.c_str().c_str() returns a pointer to a char, who points at a
null terminated string. When cerr see a 0 then it ends the printing
operation and the program goes on.
"Wernfried Schwenkner" <wernfried.schwenkner@sesa.de> wrote in message
news:bu7dl9.uae.ln@news.bln.sesa.de...
> I noticed a problem putting '\0' character into std::strings and now I
> don't know wether it is C++ conform or a compiler bug (seen on VC++).
>
> I've done the following:
>
> std::string test;
>
> test += 'a';
> test += '\0';
> test += 'b';
>
> Doing an output with
>
> std::cerr << test << std::endl;
>
> only an 'a' is displayed, I'd expeted somewhat unpritable for the '\0'
> character and then a 'b'.
>
> test.size() is correct (3) and with the iterator all characters are
> accessable.
>
> So, is this a bad implementation of std::cerr?
>
> --
> Sleepless in Berlin
> Wernfried
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Mon, 20 Aug 2001 00:54:44 GMT
Raw View
THOMAS GULBRANDSEN wrote:
>
> When you write std::cerr << test << std::endl, your compiler will call a
> function called
> operator<< that has a body _O << _X.cstr();where _O is a basic_ostream, like
> cerr or cout,
> and _X is a basic_string, like std::string(which is realt defined like this:
> typedef basic_string<char*> string)
> If you examine this you will se that cerr << test is somewhat similar to
> cerr << test.c_str().c_str() returns a pointer to a char, who points at a
> null terminated string. When cerr see a 0 then it ends the printing
> operation and the program goes on.

That doesn't quite work that way, because there's an

 operator<<(basic_ostream<charT,traits>&,
  const basic_string<charT,traits,Allocator&)

That function works directly in this case, with no type conversions
needed. There's no call to cstr(). The effects of calling
operator<<(_os_,_str_) are described in 21.3.7.9p4: "... inserts
characters as if by calling _os_.rdbuf()->sputn(_str_.data(), _n_), ...
where _n_ is the smaller of _os_.width() and _str_.size() ..."

Therefore, the number of bytes written doesn't depend on the presence of
a null character in the string; it depends exclusively on the value
returned by size(), and that value is required to include the null
character in this case.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Paul Pedriana <paulp@removethis.ccnet.com>
Date: Mon, 20 Aug 2001 12:01:07 GMT
Raw View
The bug appears to be in Microsoft's header file "STRING", courtesy of
P.J. Plauger.
Here is the code:

   template<class _E, class _Tr, class _A>
   inline
   basic_ostream<_E, _Tr>& __cdecl operator<<(
           basic_ostream<_E, _Tr>& _O,
           const basic_string<_E, _Tr, _A>& _X)
   {
       _O << _X.c_str();
       return (_O);
   }




>int main(int argc, char* argv[])
>{
>        std::string g;
>        g += 'a';
>        g += '\0';
>        g += 'b';
>        std::cerr << g << " " << g.size() << std::endl;
>        for (std::string::iterator i1 = g.begin(); i1 != g.end(); ++i1)
>        std::cerr << *i1 << std::endl;
>        return 0;
>}
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@sensor.com>
Date: Mon, 20 Aug 2001 17:12:25 GMT
Raw View

THOMAS GULBRANDSEN wrote:
>
> When you write std::cerr << test << std::endl, your compiler will call a
> function called
> operator<< that has a body _O << _X.cstr();where _O is a basic_ostream, like
> cerr or cout,

This is clearly what is happening, but it's bogus.  The standard doesn't
imply this behavior.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "THOMAS GULBRANDSEN" <thomas.gulbrandsen@c2i.net>
Date: Mon, 20 Aug 2001 17:31:45 GMT
Raw View
I've just lookt at the template code that came with my VC++, and here is the
template:
template<class _E, class _Tr, class _A> inline

basic_ostream<_E, _Tr>& __cdecl operator<<(

basic_ostream<_E, _Tr>& _O,

const basic_string<_E, _Tr, _A>& _X)

{

_O << _X.c_str();

return (_O); }

I changed the code in the body to:    _O << "Laban";

And everytime i wrote cerr << test << endl, or tryed to write a std::string,
the computer wrote Laban.

So I do not  where i am wrong.

This template code was written in 1994, and i know that the standard was not
complete back then.

You refer to the 21.3.7.9p4. What does this "number" refer to?

If I am still wrong about this, pleas let me know.

Thomas Gulbrandsen

"James Russell Kuyper Jr." <kuyper@wizard.net> wrote in message
news:3B80621B.E20CF5D7@wizard.net...
> THOMAS GULBRANDSEN wrote:
> >
> > When you write std::cerr << test << std::endl, your compiler will call a
> > function called
> > operator<< that has a body _O << _X.cstr();where _O is a basic_ostream,
like
> > cerr or cout,
> > and _X is a basic_string, like std::string(which is realt defined like
this:
> > typedef basic_string<char*> string)
> > If you examine this you will se that cerr << test is somewhat similar to
> > cerr << test.c_str().c_str() returns a pointer to a char, who points at
a
> > null terminated string. When cerr see a 0 then it ends the printing
> > operation and the program goes on.
>
> That doesn't quite work that way, because there's an
>
> operator<<(basic_ostream<charT,traits>&,
> const basic_string<charT,traits,Allocator&)
>
> That function works directly in this case, with no type conversions
> needed. There's no call to cstr(). The effects of calling
> operator<<(_os_,_str_) are described in 21.3.7.9p4: "... inserts
> characters as if by calling _os_.rdbuf()->sputn(_str_.data(), _n_), ...
> where _n_ is the smaller of _os_.width() and _str_.size() ..."
>
> Therefore, the number of bytes written doesn't depend on the presence of
> a null character in the string; it depends exclusively on the value
> returned by size(), and that value is required to include the null
> character in this case.
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "P.J. Plauger" <pjp@dinkumware.com>
Date: Mon, 20 Aug 2001 17:49:38 GMT
Raw View
"Paul Pedriana" <paulp@removethis.ccnet.com> wrote in message news:3B807300.6020301@removethis.ccnet.com...

> The bug appears to be in Microsoft's header file "STRING", courtesy of
> P.J. Plauger.
> Here is the code:
>
>    template<class _E, class _Tr, class _A>
>    inline
>    basic_ostream<_E, _Tr>& __cdecl operator<<(
>            basic_ostream<_E, _Tr>& _O,
>            const basic_string<_E, _Tr, _A>& _X)
>    {
>        _O << _X.c_str();
>        return (_O);
>    }

I'm having real trouble finding code that reads like this. The very
first code I sent Microsoft, over five years ago, has a for loop that
puts _X.size() characters, each by calling sputc. That's the way the
V5.0 and V6.0 headers read on my laptop. The major change to our baseline
is to add padding with spaces, as requred by a later draft of the C++
Standard.

I'm not saying the above form never existed -- aside from the funny
placement of inline and the braces, it looks vaguely familiar. But
I can't find any code that reads like this in any of our archives.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Wernfried Schwenkner <wernfried.schwenkner@sesa.de>
Date: Wed, 15 Aug 2001 12:20:24 GMT
Raw View
I noticed a problem putting '\0' character into std::strings and now I
don't know wether it is C++ conform or a compiler bug (seen on VC++).

I've done the following:

std::string test;

test += 'a';
test += '\0';
test += 'b';

Doing an output with

std::cerr << test << std::endl;

only an 'a' is displayed, I'd expeted somewhat unpritable for the '\0'
character and then a 'b'.

test.size() is correct (3) and with the iterator all characters are
accessable.

So, is this a bad implementation of std::cerr?

--
Sleepless in Berlin
Wernfried

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Michele Bariani <michele@ferrara.linux.it>
Date: Wed, 15 Aug 2001 17:06:11 GMT
Raw View
Wernfried Schwenkner wrote:

> I noticed a problem putting '\0' character into std::strings and now I
> don't know wether it is C++ conform or a compiler bug (seen on VC++).

The null character '\0' is the string terminator (both in C and C++),
so I think the behaviour is correct.

Michele

--
Michele Bariani
michele@ferrara.linux.it
http://members.ferrara.linux.it/michele

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@sensor.com>
Date: Wed, 15 Aug 2001 18:31:20 GMT
Raw View

Michele Bariani wrote:
>
> Wernfried Schwenkner wrote:
>
> > I noticed a problem putting '\0' character into std::strings and now I
> > don't know wether it is C++ conform or a compiler bug (seen on VC++).
>
> The null character '\0' is the string terminator (both in C and C++),
> so I think the behaviour is correct.
>
>
Std::string cares nothing about null terminators.  The only place it
is a problem is when you try to set the string from a char* (which
std::string assumes points to a null terminated string).

I suspect that it's not std::string that's messed up in Sleepless's
implemenation but his iostreams are tripping over the null (since
string itself does seem to realize it has 3 characters in it).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Matthew Austern <austern@research.att.com>
Date: Wed, 15 Aug 2001 18:43:33 GMT
Raw View
Michele Bariani <michele@ferrara.linux.it> writes:

> Wernfried Schwenkner wrote:
>
> > I noticed a problem putting '\0' character into std::strings and now I
> > don't know wether it is C++ conform or a compiler bug (seen on VC++).
>
> The null character '\0' is the string terminator (both in C and C++),
> so I think the behaviour is correct.

Not quite.  The character char(0) is the string *literal* terminator
in C and C++, and by convention it is used as the string terminator by
the standard C library.

The character char(0) is not used as the string terminator by the
standard C++ library.  (Except for the parts of the standard C++
library that are designed to interface with legacy software.)  The
std::basic_string<> class does not use any special character for
string terminators.  It is required to keep track of the length
some other way.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: comeau@panix.com (Greg Comeau)
Date: Wed, 15 Aug 2001 21:44:29 CST
Raw View
In article <RFve7.3666$f52.162935@news.infostrada.it>,
Michele Bariani  <michele@ferrara.linux.it> wrote:
>Wernfried Schwenkner wrote:
>> I noticed a problem putting '\0' character into std::strings and now I
>> don't know wether it is C++ conform or a compiler bug (seen on VC++).
>
>The null character '\0' is the string terminator (both in C and C++),
>so I think the behaviour is correct.

You're talking about char[?]'s, but he's talking about
std::string, where the null charcter should not matter
unless you .c_str() the std::string or something like that.
--
Greg Comeau                 Countdown to "export": December 1, 2001
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries.  Have you tried it?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: remove.haberg@matematik.su.se (Hans Aberg)
Date: Thu, 16 Aug 2001 16:27:44 GMT
Raw View
In article <dily9oltboj.fsf@isolde.research.att.com>, Matthew Austern
<austern@research.att.com> wrote:
>Not quite.  The character char(0) is the string *literal* terminator
>in C and C++, and by convention it is used as the string terminator by
>the standard C library.

Note that it is perfectly legal to have '\0' in string literals, for example
  const char* s = "a\0b";
which will be implemented as an array of the characters 'a', '\0', 'b',
and '\0', where the last '\0' is and additional "string terminator". This
is useful if one also implements the length, say
  const size_t n = 3;

Then this can be used to create a C++ string:
  std::string str(s, n);

In fact, I think C++ should supply a way to pick up the length of string
literals: I use a Flex/Bison combination which generates a parser that
write C++ code, which is somewhat roundabout.

  Hans Aberg      * Anti-spam: remove "remove." from email address.
                  * Email: Hans Aberg <remove.haberg@member.ams.org>
                  * Home Page: <http://www.matematik.su.se/~haberg/>
                  * AMS member listing: <http://www.ams.org/cml/>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Roger Orr" <rogero@howzatt.demon.co.uk>
Date: Mon, 20 Aug 2001 20:47:08 GMT
Raw View
>I'm not saying the above form never existed -- aside from the funny
>placement of inline and the braces, it looks vaguely familiar. But
>I can't find any code that reads like this in any of our archives.
>
>P.J. Plauger
>Dinkumware, Ltd.

The VC 5.0 code from the header file STRING looks like:-

template<class _E, class _Tr, class _A> inline
 basic_ostream<_E, _Tr>& __cdecl operator<<(
  basic_ostream<_E, _Tr>& _O,
  const basic_string<_E, _Tr, _A>& _X)
 {
 for (_A::size_type _N = 0; _N < _X.size(); ++_N)
  if (_Tr::eq_int_type(_Tr::eof(),
   _O.rdbuf()->sputc(_X[_N])))
   break;
 return (_O); }

Which does work.  It looks like Microsoft must have 'fixed' the code for
VC6....but not updated the copyright notice.
I've always heard they shipped the same STL for VC 5 and VC6 - perhaps not
quite :-)

Roger Orr
--
MVP in C++ at www.brainbench.com


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "P.J. Plauger" <pjp@dinkumware.com>
Date: Mon, 20 Aug 2001 16:24:10 CST
Raw View
"THOMAS GULBRANDSEN" <thomas.gulbrandsen@c2i.net> wrote in message news:Vd5g7.9345$em.277700@juliett.dax.net...

> I've just lookt at the template code that came with my VC++, and here is the
> template:
> template<class _E, class _Tr, class _A> inline
>
> basic_ostream<_E, _Tr>& __cdecl operator<<(
>
> basic_ostream<_E, _Tr>& _O,
>
> const basic_string<_E, _Tr, _A>& _X)
>
> {
>
> _O << _X.c_str();

So Pete Becker just reported to me too. But my copy has a loop on
size() elements. I wonder if this is some SP change...

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: emarkp@CSUA.Berkeley.EDU (E. Mark Ping)
Date: Mon, 20 Aug 2001 21:29:45 GMT
Raw View
In article <3b81084e$0$16701@wodc7nh0.news.uu.net>,
P.J. Plauger <pjp@dinkumware.com> wrote:
>"Paul Pedriana" <paulp@removethis.ccnet.com> wrote in message
>news:3B807300.6020301@removethis.ccnet.com...
>
>> The bug appears to be in Microsoft's header file "STRING", courtesy of
>> P.J. Plauger.
>> Here is the code:
>>
>>    template<class _E, class _Tr, class _A>
>>    inline
>>    basic_ostream<_E, _Tr>& __cdecl operator<<(
>>            basic_ostream<_E, _Tr>& _O,
>>            const basic_string<_E, _Tr, _A>& _X)
>>    {
>>        _O << _X.c_str();
>>        return (_O);
>>    }
>
>I'm having real trouble finding code that reads like this.

I found the same code beginning on line 177 of <string>:

template<class _E, class _Tr, class _A> inline
    basic_ostream<_E, _Tr>& __cdecl operator<<(
        basic_ostream<_E, _Tr>& _O,
        const basic_string<_E, _Tr, _A>& _X)
    {
    _O << _X.c_str();
    return (_O); }

I don't know why the formatting is different.

Note this is VS6sp4
--
Mark Ping
emarkp@soda.CSUA.Berkeley.EDU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: comeau@panix.com (Greg Comeau)
Date: Mon, 20 Aug 2001 21:31:10 GMT
Raw View
In article <Vd5g7.9345$em.277700@juliett.dax.net>,
THOMAS GULBRANDSEN <thomas.gulbrandsen@c2i.net> wrote:
>I've just lookt at the template code that came with my VC++, and here is the
>template:.....  _O << _X.c_str(); ......
>...This template code was written in 1994, and i know that the standard
>was not complete back then.

Well, the latest Dinkum version does not seem to have this problem
(as I posted the other day, and furthermore just looked).
In fact, 1994 seem to really be pushing it, and I wonder if you even
have a recent version no less the latest....
--
Greg Comeau                 Countdown to "export": December 1, 2001
Comeau C/C++ ONLINE ==>     http://www.comeaucomputing.com/tryitout
World Class Compilers:  Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Ron Natalie <ron@sensor.com>
Date: Mon, 20 Aug 2001 21:34:09 GMT
Raw View

Roger Orr wrote:

> The VC 5.0 code from the header file STRING looks like:-
>
> template<class _E, class _Tr, class _A> inline
>  basic_ostream<_E, _Tr>& __cdecl operator<<(

That's not the one that is included with my 5.0 version of
the compiler (and I think I'm up todate with service packs)
has the c_str version.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]