Topic: basic_string output formatting


Author: James.Kanze@dresdner-bank.de
Date: 1998/11/26
Raw View
In article <199811231632.RAA03516@su5bpc.labogeo>,
  Philippe.Couton@sercel.fr (Philippe COUTON) wrote:
> The CD2 Draft describes in section 21.3.7.9 the basic_string's operator<<()
as
> follows:
>
>     ... inserts characters as if by calling os.rdbuf()->sputn(str.data(), n),
>     padding as described in stage 3 of lib.facet.num.put.virtuals, where n is
>     the smaller of os.width() and str.size(); then calls os.width(0).
>
> So, if I write the following code:
>
>     cout << setfill('.') << setw(8) << string("Hello")
>       << ' ' << os.width() << endl;
>
> I expect to obtain something like "...Hello 0" and have the width of cout
reset
> to 0.
>
> However, I've compiled and ran this code on Microsoft Visual C++ V5.0 and GNU
> g++ 2.7.2. They both produced the same result: "Hello 8", without field
> padding. Note also that the width of cout hasn't be reset to 0: it has his
> initial value of 8.
>
> Is it my standard interpretation which is bad, or the compilers missed
> something?

They're probably conforming to an earlier version.  I seem to remember
that there was an error in most of the earlier versions, and either
char* or string (I forget which) just output the string, without any
formatting.  I don't think that this was ever the intent, but apparently,
a number of implementors followed it blindly.

> There is also a point which shocks me:
>
> If I write 'cout << setw(2) << "Hello" ', this will produce "Hello". But,
with
> strings, the section 21.3.7.9 says than the parameter n passed to sputn is
> min(os.width(), str.size()). So, the call 'cout << setw(2) <<
string("Hello")'
> must produce "He" !

This is also an obvious error -- it should be max(os.width(),str.size()).
Otherwise, the default value of width is 0, which doesn't give you very
much.

> Why the behavior is different between char* and string?

Because earlier versions of the draft had typographical errors
(or oversights).  I'd be very surprised if there aren't still a
few in the final standard.

--
James Kanze                                           GABI Software, S   rl
Conseils en informatique orient    objet  --
                          --  Beratung in industrieller Datenverarbeitung
mailto: kanze@gabi-soft.fr           mailto: James.Kanze@dresdner-bank.de

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/11/24
Raw View
Philippe COUTON wrote:

> The CD2 Draft describes in section 21.3.7.9 the basic_string's operator<<() as
> follows:
>
>     ... inserts characters as if by calling os.rdbuf()->sputn(str.data(), n),
>     padding as described in stage 3 of lib.facet.num.put.virtuals, where n is
>     the smaller of os.width() and str.size(); then calls os.width(0).
          ^^^^^^^
    read larger here

> So, if I write the following code:
>
>     cout << setfill('.') << setw(8) << string("Hello")
>          << ' ' << os.width() << endl;

This should be

(cout << setfill('.') << setw(8) << string("Hello")
          << ' ').width();

> I expect to obtain something like "...Hello 0" and have the width of cout reset
> to 0.

Correct

> However, I've compiled and ran this code on Microsoft Visual C++ V5.0 and GNU
> g++ 2.7.2. They both produced the same result: "Hello 8", without field
> padding. Note also that the width of cout hasn't be reset to 0: it has his
> initial value of 8.
>
> Is it my standard interpretation which is bad, or the compilers missed
> something?

It's the standard which is bad

> There is also a point which shocks me:
>
> If I write 'cout << setw(2) << "Hello" ', this will produce "Hello". But, with
> strings, the section 21.3.7.9 says than the parameter n passed to sputn is
> min(os.width(), str.size()). So, the call 'cout << setw(2) << string("Hello")'
> must produce "He" !

No it's (should be) max(os.width(), str.size())

> Why the behavior is different between char* and string?

It isn't (shouldn't)

the 'width' can add 'fill' characters, it shouldn't ever truncate
output

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/


[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Philippe.Couton@sercel.fr (Philippe COUTON)
Date: 1998/11/24
Raw View
The CD2 Draft describes in section 21.3.7.9 the basic_string's operator<<() as
follows:

    ... inserts characters as if by calling os.rdbuf()->sputn(str.data(), n),
    padding as described in stage 3 of lib.facet.num.put.virtuals, where n is
    the smaller of os.width() and str.size(); then calls os.width(0).

So, if I write the following code:

    cout << setfill('.') << setw(8) << string("Hello")
      << ' ' << os.width() << endl;

I expect to obtain something like "...Hello 0" and have the width of cout reset
to 0.

However, I've compiled and ran this code on Microsoft Visual C++ V5.0 and GNU
g++ 2.7.2. They both produced the same result: "Hello 8", without field
padding. Note also that the width of cout hasn't be reset to 0: it has his
initial value of 8.

Is it my standard interpretation which is bad, or the compilers missed
something?


There is also a point which shocks me:

If I write 'cout << setw(2) << "Hello" ', this will produce "Hello". But, with
strings, the section 21.3.7.9 says than the parameter n passed to sputn is
min(os.width(), str.size()). So, the call 'cout << setw(2) << string("Hello")'
must produce "He" !

Why the behavior is different between char* and string?


Regards,
Philippe Couton
---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1998/11/24
Raw View
On 24 Nov 98 01:02:43 GMT, Philippe COUTON <Philippe.Couton@sercel.fr> wrote:

>The CD2 Draft describes in section 21.3.7.9 the basic_string's operator<<() as
>follows:
>
>    ... inserts characters as if by calling os.rdbuf()->sputn(str.data(), n),
>    padding as described in stage 3 of lib.facet.num.put.virtuals, where n is
>    the smaller of os.width() and str.size(); then calls os.width(0).
>
>So, if I write the following code:
>
>    cout << setfill('.') << setw(8) << string("Hello")
>      << ' ' << os.width() << endl;
>
>I expect to obtain something like "...Hello 0" and have the width of cout reset
>to 0.

#Here is the output using egcs:
[sbnaran@localhost] [~] >> a.out
...Hello 0

#BTW, egcs is basically the new g++.
#Get it from www.cygnus.com.

Moreover, your program above is ill-defined.  It may print

...Hello 7


Eg,

int main()
{
     cout << setw(7);
     cout << setfill('.') << setw(2) << "Hello"
          << ' ' << cout.width() << endl;
}

This is because the evaluation order of subexpressions is not defined.
So it is possible that cout.width() is evaluated first to give '7'
which is stored in a temporary int.  Specifically, the parse tree
looks like this:

                                    op<<
                                   -    -
                                  -      -
                              op<<        endl
                             -    -
                            -      -
                        op<<       width
                       -    -       -
                      -      -      -
                  op<<      ' '    cout
                 -    -
                -      -
            op<<      "Hello"
           -    -
          -      -
        op<<    setw
       -         -
      -          -
    op<<         2
   -
  -
 setfill
  -
  -
 '.'


You can see that the evaluation order of
   setfill('.')
   setw(2)
   "Hello" // BTW, this needs no evaluation
   width(cout) // or more correctly, cout.width()
   endl // BTW, this needs no evaluation
is undefined.  They can occur left to right, right to left, something
else, or even at the same time!  The evaluation of op<<(cout,stuff)
occurs left to right, of course.



>There is also a point which shocks me:
>
>If I write 'cout << setw(2) << "Hello" ', this will produce "Hello". But, with
>strings, the section 21.3.7.9 says than the parameter n passed to sputn is
>min(os.width(), str.size()). So, the call 'cout << setw(2) << string("Hello")'
>must produce "He" !

Egcs prints
Hello 7

So egcs appears to be wrong as it should be printing "He".  By contrast,
the SGI implementation of op<<(...,string) has

  size_t __n = __s.size();
  size_t __pad_len = 0;
  ...
  const size_t __w = __os.width();

  if (__w > 0) {
    __n = min(__w, __n);
    __pad_len = __w - __n;
  }

  ...


And this seems to be in accord with the standard.


>Why the behavior is different between char* and string?

I guess because char* is just a dumb array of chars whereas a string
is a smart array of chars.  So op<<(...,string) respects
iostream::width more closely.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.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://reality.sgi.com/austern_mti/std-c++/faq.html              ]