std::ostream manipulator

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Boris

    std::ostream manipulator

    Is it possible to manipulate the std::ostream to prepend a string when
    performing output, e.g.

    // manipute std::cout to prepend "prefix "
    std::cout << "hallo" << std::endl;
    // results in "prefix hallo"

    I need this to overwrite the "<<" operator for MyClass in a recursive
    way, e.g.

    std::ostream&
    operator<<( std::ostream& stream, MyClass const& myClass )
    {
    // do some output
    // prepend '\t' to stream, how?
    stream << myClass.member_ << '\n'; // recursive call of << operator
    // remove prefix '\t' from stream
    return stream;
    }

    when MyClass has a pointer to another MyClass as a member
    (MyClass const* member_). I like to prepend tabs when streaming the
    members without saving the prefixes in MyClass.

    Thanks,

    Boris
  • Bob Smith

    #2
    Re: std::ostream manipulator



    Boris wrote:
    [color=blue]
    > Is it possible to manipulate the std::ostream to prepend a string when
    > performing output, e.g.
    >
    > // manipute std::cout to prepend "prefix "
    > std::cout << "hallo" << std::endl;
    > // results in "prefix hallo"
    >
    > I need this to overwrite the "<<" operator for MyClass in a recursive
    > way, e.g.
    >
    > std::ostream&
    > operator<<( std::ostream& stream, MyClass const& myClass )
    > {
    > // do some output
    > // prepend '\t' to stream, how?
    > stream << myClass.member_ << '\n'; // recursive call of << operator
    > // remove prefix '\t' from stream
    > return stream;
    > }[/color]

    do you mean simply:
    strstream s;
    s << "prepended: " << myClass.member_ ;
    stream << s;
    -..
    or maybe stream << s.str(),

    ????
    /B

    [color=blue]
    >
    > when MyClass has a pointer to another MyClass as a member
    > (MyClass const* member_). I like to prepend tabs when streaming the
    > members without saving the prefixes in MyClass.
    >
    > Thanks,
    >
    > Boris
    >[/color]

    Comment

    • tom_usenet

      #3
      Re: std::ostream manipulator

      On 15 Oct 2003 01:49:54 -0700, godot@nexgo.de (Boris) wrote:
      [color=blue]
      >Is it possible to manipulate the std::ostream to prepend a string when
      >performing output, e.g.
      >
      >// manipute std::cout to prepend "prefix "
      >std::cout << "hallo" << std::endl;
      >// results in "prefix hallo"
      >
      >I need this to overwrite the "<<" operator for MyClass in a recursive
      >way, e.g.
      >
      >std::ostream &
      >operator<<( std::ostream& stream, MyClass const& myClass )
      >{
      > // do some output
      > // prepend '\t' to stream, how?
      > stream << myClass.member_ << '\n'; // recursive call of << operator
      > // remove prefix '\t' from stream
      > return stream;
      >}
      >
      >when MyClass has a pointer to another MyClass as a member
      >(MyClass const* member_). I like to prepend tabs when streaming the
      >members without saving the prefixes in MyClass.[/color]

      It's unclear from this whether you need a prefix for each line or
      something else. For the former you need the prefix_buf. See the prefix
      stuff under IOStreams here:


      Tom

      Comment

      • Boris

        #4
        Re: std::ostream manipulator

        Bob Smith <bobsmith@jippi i.fi> wrote in message news:<3F8D1403. 2040109@jippii. fi>...[color=blue]
        >
        > do you mean simply:
        > strstream s;
        > s << "prepended: " << myClass.member_ ;
        > stream << s;
        > -..
        > or maybe stream << s.str(),
        >[/color]

        Hi,
        streaming MyClass is a multiline message, I need the prefix for each line.
        Your solution prepends only a prefix for the first line.

        Thanks,
        Boris

        Comment

        • tom_usenet

          #5
          Re: std::ostream manipulator

          On 15 Oct 2003 09:00:51 -0700, godot@nexgo.de (Boris) wrote:
          [color=blue]
          >Bob Smith <bobsmith@jippi i.fi> wrote in message news:<3F8D1403. 2040109@jippii. fi>...[color=green]
          >>
          >> do you mean simply:
          >> strstream s;
          >> s << "prepended: " << myClass.member_ ;
          >> stream << s;
          >> -..
          >> or maybe stream << s.str(),
          >>[/color]
          >
          >Hi,
          >streaming MyClass is a multiline message, I need the prefix for each line.
          >Your solution prepends only a prefix for the first line.[/color]

          In that case, the prefix stream at this site does *exactly* what you
          want. There's no other good way to do it within the iostreams
          heirarchy.


          Tom

          Comment

          • grejdanospam@pacbell.net

            #6
            Re: std::ostream manipulator

            On 15 Oct 2003 01:49:54 -0700, Boris <godot@nexgo.de > wrote:
            [color=blue]
            > Is it possible to manipulate the std::ostream to prepend a string when
            > performing output, e.g.
            >
            > // manipute std::cout to prepend "prefix "
            > std::cout << "hallo" << std::endl;
            > // results in "prefix hallo"
            >
            > I need this to overwrite the "<<" operator for MyClass in a recursive
            > way, e.g.
            >
            > std::ostream& operator<<( std::ostream& stream, MyClass const& myClass )
            > {
            > // do some output
            > // prepend '\t' to stream, how?
            > stream << myClass.member_ << '\n'; // recursive call of << operator
            > // remove prefix '\t' from stream return stream;
            > }
            >
            > when MyClass has a pointer to another MyClass as a member
            > (MyClass const* member_). I like to prepend tabs when streaming the
            > members without saving the prefixes in MyClass.
            >
            > Thanks,
            >
            > Boris
            >[/color]

            I am not sure what you are trying to do here.
            If you want a table like output ( tab may do it ) then you just have to
            set the
            width of next output field by calling,
            os.width(...) or os << setw(...)

            If you want the tabs to accumulate then you should create an object that
            would accumulate the tabs with the << operator to send it to ostream.
            Inserting such code to the ostream class seems unnecessery.

            --
            grzegorz

            Comment

            • Boris

              #7
              Re: std::ostream manipulator

              Hi,
              thanks for your answer.
              [color=blue]
              >
              > I am not sure what you are trying to do here.
              > If you want a table like output ( tab may do it ) then you just have to
              > set the
              > width of next output field by calling,
              > os.width(...) or os << setw(...)
              >[/color]

              I like to do proper indentation for multiline output of
              nested data structures.
              [color=blue]
              > If you want the tabs to accumulate then you should create an object that
              > would accumulate the tabs with the << operator to send it to ostream.[/color]

              Maybe you are right, that seams to be the simplest solution.
              [color=blue]
              > Inserting such code to the ostream class seems unnecessery.[/color]

              Do you think so? You can do nice formating of floating point numbers
              with
              std::cout << std::scientific for example. Now the formating behaviour
              of the stream changes for all succeeding floating point output. I
              would appreciate a similar mechanism for strings and prefixes.

              Regards,
              Boris

              Comment

              • Boris

                #8
                Re: std::ostream manipulator

                tom_usenet <tom_usenet@hot mail.com> wrote in message news:<m81rov0qf 1qrrfrcerjm5ndp t60l4bk5ag@4ax. com>...[color=blue]
                > On 15 Oct 2003 09:00:51 -0700, godot@nexgo.de (Boris) wrote:
                >[color=green]
                > >Bob Smith <bobsmith@jippi i.fi> wrote in message news:<3F8D1403. 2040109@jippii. fi>...[color=darkred]
                > >>
                > >> do you mean simply:
                > >> strstream s;
                > >> s << "prepended: " << myClass.member_ ;
                > >> stream << s;
                > >> -..
                > >> or maybe stream << s.str(),
                > >>[/color]
                > >
                > >Hi,
                > >streaming MyClass is a multiline message, I need the prefix for each line.
                > >Your solution prepends only a prefix for the first line.[/color]
                >
                > In that case, the prefix stream at this site does *exactly* what you
                > want. There's no other good way to do it within the iostreams
                > heirarchy.
                > http://www.informatik.uni-konstanz.de/~kuehl/
                >
                > Tom[/color]

                Hi,
                I visited the page, thanks for the hint. You are right, this is exactly
                what I need, even thought its a much more complicate solution than I hoped
                to find. Unfortunatly the cited code does not compile on my platform
                (Visual C++ .Net 2003), but I try to contact Dietmar Kuehl for a workaround.

                Regards,
                Boris

                Comment

                • tom_usenet

                  #9
                  Re: std::ostream manipulator

                  On 16 Oct 2003 07:16:23 -0700, godot@nexgo.de (Boris) wrote:
                  [color=blue]
                  >tom_usenet <tom_usenet@hot mail.com> wrote in message news:<m81rov0qf 1qrrfrcerjm5ndp t60l4bk5ag@4ax. com>...[color=green]
                  >> On 15 Oct 2003 09:00:51 -0700, godot@nexgo.de (Boris) wrote:
                  >>[color=darkred]
                  >> >Bob Smith <bobsmith@jippi i.fi> wrote in message news:<3F8D1403. 2040109@jippii. fi>...
                  >> >>
                  >> >> do you mean simply:
                  >> >> strstream s;
                  >> >> s << "prepended: " << myClass.member_ ;
                  >> >> stream << s;
                  >> >> -..
                  >> >> or maybe stream << s.str(),
                  >> >>
                  >> >
                  >> >Hi,
                  >> >streaming MyClass is a multiline message, I need the prefix for each line.
                  >> >Your solution prepends only a prefix for the first line.[/color]
                  >>
                  >> In that case, the prefix stream at this site does *exactly* what you
                  >> want. There's no other good way to do it within the iostreams
                  >> heirarchy.
                  >> http://www.informatik.uni-konstanz.de/~kuehl/
                  >>
                  >> Tom[/color]
                  >
                  >Hi,
                  >I visited the page, thanks for the hint. You are right, this is exactly
                  >what I need, even thought its a much more complicate solution than I hoped
                  >to find. Unfortunatly the cited code does not compile on my platform
                  >(Visual C++ .Net 2003), but I try to contact Dietmar Kuehl for a workaround.[/color]

                  Apologies, the code it very out of date and needs fixing for standard
                  streams. Here's the (hopefully) fixed code (sorry about the annoying
                  word wrap and tabs):


                  #ifndef _PRFXSTREAM_H_
                  #define _PRFXSTREAM_H_
                  // </PRE>
                  //----------------------------------------------------------------------------
                  #include <streambuf>
                  #include <ios>
                  #include <ostream>
                  #include <istream>
                  #include <vector>
                  // </PRE>

                  class prfxbuf: public std::streambuf
                  {
                  private:
                  std::streambuf *i_sbuf; // the actual streambuf used
                  to read and write chars
                  unsigned int i_len; // the
                  length of the prefix
                  char *i_prfx; // the
                  prefix
                  bool i_newline; //
                  remember whether we are at a new line
                  int i_cache; // may
                  cache a read character
                  std::vector<cha r> i_buf;

                  bool skip_prefix();

                  protected:
                  int overflow(int);
                  int underflow();
                  int uflow();
                  int sync();

                  public:
                  prfxbuf(std::st reambuf *sb, const char *prfx);
                  ~prfxbuf();
                  };


                  class iprfxstream: public std::istream
                  {
                  public:
                  iprfxstream(std ::streambuf *sb, const char *prfx);
                  ~iprfxstream();
                  };

                  class oprfxstream: public std::ostream
                  {
                  public:
                  oprfxstream(std ::streambuf *sb, const char *prfx);
                  ~oprfxstream();
                  };

                  #endif /* _PRFXSTREAM_H_ */

                  #include <cstring>
                  #include <vector>
                  //#include "prfxstream .h"
                  // </PRE>
                  //----------------------------------------------------------------------------
                  // The constructor of the prfxbuf initializes its pointer to the
                  streambuf
                  // with the argument sb: It is assumed that this streambuf is
                  initialized
                  // correctly. In addition no ownership is assumed for this streambuf.
                  It
                  // is not deleted in the destructor. Then the length of the prefix
                  string
                  // is cached and the prefix string is copied into a private version:
                  This
                  // is done to avoid problems when the user modifies or deletes the
                  string
                  // passed as constructor argument. The member i_newline is set to
                  indicate
                  // that the processing it at the beginning of a new line: in either
                  case
                  // (reading or writing) it starts with a new line. When reading a file
                  a
                  // prefix has to be skipped and when writing a file a prefix has to be
                  // added. EOF is used to indicate that the cache does not contain any
                  // valid character.
                  // <BR>
                  // In the body of the constructor the put area and the get area are
                  // initialized to be empty: no buffering is done by this streambuf.
                  All
                  // buffering is deferred to the actually used streambuf. This makes
                  sure
                  // that the function overflow() is called whenever a character is
                  written
                  // to this streambuf and that the function underflow() is called
                  whenever
                  // a character is read from this streambuf. The put buffer is
                  specified
                  // using streambuf::setp () and the get buffer is specified using
                  // streambuf::setg ().
                  // <PRE>
                  prfxbuf::prfxbu f(std::streambu f *sb, const char *prfx):
                  std::streambuf( ),
                  i_sbuf(sb),
                  i_len(std::strl en(prfx)),
                  i_prfx(std::str cpy(new char[i_len + 1], prfx)),
                  i_newline(true) ,
                  i_cache(EOF),
                  i_buf(i_len)
                  {
                  setp(0, 0);
                  setg(0, 0, 0);
                  }
                  // </PRE>
                  // The destructor of prfxbuf has to release the copy of the prefix.
                  // <PRE>
                  prfxbuf::~prfxb uf()
                  {
                  delete[] i_prfx;
                  }

                  bool prfxbuf::skip_p refix()
                  {
                  if (i_sbuf->sgetn(&i_buf[0], i_len) != i_len)
                  return false;
                  if (std::strncmp(& i_buf[0], i_prfx, i_len))
                  {
                  // an expection could be thrown here...
                  return false;
                  }
                  i_newline = false;
                  return true;
                  }

                  int prfxbuf::underf low()
                  {
                  if (i_cache == EOF)
                  {
                  if (i_newline)
                  if (!skip_prefix() )
                  return EOF;

                  i_cache = i_sbuf->sbumpc();
                  if (i_cache == traits_type::to _int_type('\n') )
                  i_newline = true;
                  return i_cache;
                  }
                  else
                  return i_cache;
                  }

                  int prfxbuf::uflow( )
                  {
                  if (i_cache == EOF)
                  {
                  if (i_newline)
                  if (!skip_prefix() )
                  return EOF;

                  int rc = i_sbuf->sbumpc();
                  if (rc == traits_type::to _int_type('\n') )
                  i_newline = true;
                  return rc;
                  }
                  else
                  {
                  int rc = i_cache;
                  i_cache = EOF;
                  return rc;
                  }
                  }

                  int prfxbuf::overfl ow(int c)
                  {
                  if (c != EOF)
                  {
                  if (i_newline)
                  if (i_sbuf->sputn(i_prfx , i_len) != i_len)
                  return EOF;
                  else
                  i_newline = false;

                  char cc = traits_type::to _char_type(c);
                  int rc = i_sbuf->sputc(cc);
                  if (cc == '\n')
                  i_newline = true;
                  return rc;
                  }
                  return 0;
                  }

                  int prfxbuf::sync()
                  {
                  return i_sbuf->pubsync();
                  }

                  iprfxstream::ip rfxstream(std:: streambuf *sb, const char *prfx):
                  std::istream(ne w prfxbuf(sb, prfx))
                  {
                  }

                  oprfxstream::op rfxstream(std:: streambuf *sb, const char *prfx):
                  std::ostream(ne w prfxbuf(sb, prfx))
                  {
                  }

                  iprfxstream::~i prfxstream()
                  {
                  delete rdbuf();
                  }

                  oprfxstream::~o prfxstream()
                  {
                  delete rdbuf();
                  }
                  // </PRE>
                  //----------------------------------------------------------------------------
                  // <HR>
                  // Please send comments, suggestions, problem reports, bug fixes etc.
                  to
                  // <BR>
                  // <A HREF="http://www.informatik. uni-konstanz.de/~kuehl"><I>Diet mar
                  Kühl</I></A>:
                  // <A
                  HREF="mailto:di etmar.kuehl@cla as-solutions.de">D ietmar.Kuehl@cl aas-solutions.de</A>
                  // </BODY>
                  // </HTML>

                  //test code
                  #include <iostream>
                  int main()
                  {
                  oprfxstream mystream(std::c out.rdbuf(), "Test prefix: ");
                  mystream << "This should have been prefixed.\nAlon g with this.";
                  mystream << "\n" << 10 << '\n';
                  mystream.flush( );
                  }


                  Comment

                  Working...