Topic: Stream width and operator<<(ostream &,


Author: clamage@taumet.Eng.Sun.COM (Steve Clamage)
Date: 1996/10/03
Raw View
In article pb1@jake.esu.edu, jpotter@falcon.lhup.edu (John E. Potter) writes:
>Brian Michael Freyburger (freyburg@gamut.stanford.edu) wrote:
>: In the latest draft version I have access to, a legal definition of
>: operator << on strings is:
>
>: template <class charT, class osTraits, class strTraits>
>: basic_ostream<charT, osTraits>&
>: operator<< (basic_ostream<charT, osTraits>& os,
>:             const basic_string<charT, strTtraits>& str)
>: {
>:     os.write (str.data (), str.size ());
>:     return os;
>: }
>
>: However, this definition ignores the width format of the output
>: stream.

The latest draft (Sept 1996) still ignores the width on output,
and I believe that is a mistake. I'll forward these comments
to the C++ Committee members working on strings and streams.

>:  For orthogonality to operator<<(ostream &, const char *), I
>: think operator<< on strings should be defined as:
>
>: template <class charT, class osTraits, class strTraits>
>: basic_ostream<charT, osTraits>&
>: operator<< (basic_ostream<charT, osTraits>& os,
>:             const basic_string<charT, strTtraits>& str)
>: {
>:     return os << str.c_str();
>: }

Actually not. For a C++ string class object, all "size" characters
should be written, even if some of them are null. The expression
(os<<str.c_str()) would stop at the first null byte.

>My first encounter with this had the same results.  What is this crazy
>string that is to be better than char* yet does not adjust itself
>properly?
>
>So off to the DWP to find that it is required not a compiler bug.
>
>Now consider:
> cin >> setw(10) >> someString;
>which makes no sense.

Why do you say it makes no sense? The extraction width for cin is
set to 10, and then characters are extracted into someString. (The
definition of the string extractor says the width is taken into
account.) The effect is comparable to
 cin >> setw(10) >> charArray;

As I said above, I believe ignoring the width for string output was an
oversight.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1996/10/06
Raw View
Steve Clamage (clamage@taumet.Eng.Sun.COM) wrote:
:In article pb1@jake.esu.edu, jpotter@falcon.lhup.edu (John E. Potter) writes:
:>Brian Michael Freyburger (freyburg@gamut.stanford.edu) wrote:
:>: In the latest draft version I have access to, a legal definition of
:>: operator << on strings is:
:>
:>: template <class charT, class osTraits, class strTraits>
:>: basic_ostream<charT, osTraits>&
:>: operator<< (basic_ostream<charT, osTraits>& os,
:>:             const basic_string<charT, strTtraits>& str)
:>: {
:>:     os.write (str.data (), str.size ());
:>:     return os;
:>: }
:>
:>: However, this definition ignores the width format of the output
:>: stream.
:
:The latest draft (Sept 1996) still ignores the width on output,
:and I believe that is a mistake. I'll forward these comments
:to the C++ Committee members working on strings and streams.
:
:>:  For orthogonality to operator<<(ostream &, const char *), I
:>: think operator<< on strings should be defined as:
:>
:>: template <class charT, class osTraits, class strTraits>
:>: basic_ostream<charT, osTraits>&
:>: operator<< (basic_ostream<charT, osTraits>& os,
:>:             const basic_string<charT, strTtraits>& str)
:>: {
:>:     return os << str.c_str();
:>: }
:
:Actually not. For a C++ string class object, all "size" characters
:should be written, even if some of them are null. The expression
:(os<<str.c_str()) would stop at the first null byte.
:
:>My first encounter with this had the same results.  What is this crazy
:>string that is to be better than char* yet does not adjust itself
:>properly?
:>
:>So off to the DWP to find that it is required not a compiler bug.
:>
:>Now consider:
:>       cin >> setw(10) >> someString;
:>which makes no sense.
:
:Why do you say it makes no sense?

A combination of ignorance, misinterpretation, faith, and habbit.

:The extraction width for cin is
:set to 10, and then characters are extracted into someString. (The
:definition of the string extractor says the width is taken into
:account.) The effect is comparable to
:        cin >> setw(10) >> charArray;
:
:As I said above, I believe ignoring the width for string output was an
:oversight.

Around 1996/02 I noticed that string output ignores width.  I went
to my CD1 (ignorance, outdated) to see what it said.  I noticed that
it did not mention width for either input or output and seemed to
say that string purposely ignored width (misinterpretation, it does
not say anything).  Since the CD1 had been out for nearly a year,
someone else must have noticed this, complained, and the reasons
were given (faith).  So, I tried to rationalize reasons.  On input,
the reason for width is to protect against reading a string which
is larger than the charArray (habbit).  Since the string is able
to grow to accomidate the input, this use makes no sense.  So to
be consistent, width is also ignored on output.

Since making that post, I remembered the other use of width on
input for extracting a specific number of characters from a fixed
format record.  I doubt that I would ever use that feature with
string.  That kind of thing is quite safe with charArray and the
things I am likely to do with the results do not require the
powers of string.  Example: format(f3.1)
 char strNum[4];
 inStream >> setw(4) >> strNum;
 double number(double(atoi(strNum)) / 10);
So it still (habbit) makes no sense to me.

Your post and a look at my headers shows that width on input is
just like charArray where I must ask for one more character than
I want.  This makes no sense for string; however, it is as close
to C as possible.  A reasonable compromise.

You have also pointed out that the obvious tactic of using c_str()
in operator<< to implement width for string is not consistent with
what a string is.  However, the obvious way to print the entire
string including null characters does not preserve width.  Example:

 string s("Hello- world");
 cout << setw(40) << "|" << '\n';
 cout << setw(40) << s.c_str() << '\n';
 cout << setw(s.length() < 40 ? 40 - s.length() : 0)
   << "" << s << '\n';
 s[5] = 0;
 cout << setw(40) << s.c_str() << '\n';
 cout << setw(s.length() < 40 ? 40 - s.length() : 0)
   << "" << s << '\n';
                                       |
                            Hello- world
                            Hello- world
                                   Hello
                            Hello world

Getting them both right is not a pretty proposition.  Perhaps, the
committee members considered this (faith) and the absence of width
for string output is intentional not a mistake or an oversight.

I have no vested interest in any particular rules.  I can live
with any rules; however, life without known rules is not nice.

Best wishes for a productive meeting in Hawaii,
John


[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]