Text formatting with streams

Discussion in 'C++' started by CSpartan, Jul 20, 2005.

  1. CSpartan

    CSpartan Guest

    I need to create a C++ function that works similar to 'cout'. I would
    like to have a function 'MyTextOut' that would accept the following
    syntax

    MyTextOut << "x = " << iX << " kg" ;

    and outputs the concatenated string on a I/O channel defined by me.
    CSpartan, Jul 20, 2005
    #1
    1. Advertising

  2. CSpartan

    Chris Dams Guest

    Dear CSpartan,

    On Wed, 2005-07-20 at 09:49 -0700, CSpartan wrote:
    > I need to create a C++ function that works similar to 'cout'. I would
    > like to have a function 'MyTextOut' that would accept the following
    > syntax
    >
    > MyTextOut << "x = " << iX << " kg" ;
    >
    > and outputs the concatenated string on a I/O channel defined by me.


    This already exists in the standard library. It is called an
    ostringstream and can be used as in

    #include<sstream>

    vector<string> v;
    ostringstream ss;
    int i=5,j=8;
    ss << "f" << i << "_" << j;
    v.push_back(ss.str());

    Best wishes,
    Chris
    Chris Dams, Jul 21, 2005
    #2
    1. Advertising

  3. CSpartan wrote:
    > I need to create a C++ function that works similar to 'cout'.


    You should probably start with learning C++ first... 'cout' is not
    a function, it is an object of a class (of 'std::eek:stream' or derived
    thereof) and you apparently want to create a similar class. Note,
    however, that this is done differently than you think: you are *not*
    going to change 'std::eek:stream' or derive thereof (well, you might
    derive from this class but only for convenient construction; see below)
    but you want to derive a class from 'std::streambuf' and use it with
    an 'std::eek:stream'.

    > I would like to have a function 'MyTextOut' that would accept the
    > following syntax
    >
    > MyTextOut << "x = " << iX << " kg" ;
    >
    > and outputs the concatenated string on a I/O channel defined by me.


    IOStreams operate on external representations abstracted using the
    class 'std::streambuf' (well, actually it is a class template called
    'std::basic_streambuf' but you should probably ignore this detail for
    noww and use the typedef 'std::streambuf' thinking of it as a normal
    class). For handling output you want to override the virtual function
    'sync()' and 'overflow()' which do similar but not identical operations.
    In addition, you want to setup a buffer to avoid sending individual
    characters. This looks something like this:

    class io_channel_buf:
    public std::streambuf
    {
    public:
    io_channel_buf() { setp(m_buffer, m_buffer + s_size - 1); }
    private:
    int overflow(int c)
    {
    if (traits_type::eq_int_type(c, traits_type::eof()))
    {
    *pptr() = traits_type::to_char_type(c);
    pbump(1);
    }
    return sync() == -1? traits_type::eof(): traits_type::not_eof(c);
    }

    int sync()
    {
    if (pbase() != pptr())
    {
    int rc = write(channel, pbase(), pptr() - pbase());
    if (rc != pptr() - pbase())
    return -1; // TODO: possibly deal with partially send buffers...
    sep(m_buffer, m_buffer + s_size - 1);
    }
    return 0;
    }

    enum { s_size = 1024 };
    char m_buffer[s_size];
    };

    The 'write()' function sends the characters to your I/O channel and
    will probably be replaced by whatever approach is suitable to access
    this I/O channel. You would then create an 'std::eek:stream' object which
    internally uses this stream buffer for your stream object:

    io_channel_buf MyTextBuf;
    std::eek:stream MyTextOut(&MyTextBuf);

    MyTextOut << whatever;

    To avoid the two step construction of the output object, you might
    derive from 'std::eek:stream' and setup the proper stream buffer in the
    constructor of the derived class. You should, however, don't try to
    temper with 'std::eek:stream's functios otherwise than this.

    For more details on anything I have written, search for past articles
    I have written in comp.lang.c++ or comp.lang.c++.moderated on similar
    subjects...
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.eai-systems.com> - Efficient Artificial Intelligence
    Dietmar Kuehl, Jul 21, 2005
    #3
  4. CSpartan

    Guest

    The 'streambuf' class seems to be able to do what I want. I tried the
    suggested code block, but couldn't make it work. What is missing to
    make the following work (writing to standard out) ?

    #include <iostream>
    #include <io.h>

    class io_channel_buf : public std::streambuf
    {
    public:
    io_channel_buf() { setp(m_buffer, m_buffer + s_size - 1); } //
    constructor
    private:
    int overflow(int c)
    {
    if (traits_type::eq_int_type(c, traits_type::eof()))
    {
    *pptr() = traits_type::to_char_type(c);
    pbump(1);
    }
    return sync() == -1? traits_type::eof(): traits_type::not_eof(c);
    }

    int sync()
    {
    if (pbase() != pptr())
    {
    int rc = write(1, pbase(), pptr() - pbase());

    if (rc != pptr() - pbase())
    return -1; // TODO: possibly deal with partially send buffers...

    setp(m_buffer, m_buffer + s_size - 1);
    }
    return 0;
    }

    enum { s_size = 1024 };
    char m_buffer[s_size];
    };

    void main(void)
    {
    io_channel_buf MyTextBuf;
    std::eek:stream MyTextOut(&MyTextBuf);
    int x = 3;

    MyTextOut << "x equals " << x ;
    }
    , Jul 21, 2005
    #4
  5. CSpartan

    Guest

    I found the problem. I forgot to include a destructor which calls the
    sync() to flush buffer.

    Thanks for your help, the function now works exactly the way I want.
    , Jul 21, 2005
    #5
  6. CSpartan

    Guest

    I entered another problem with the code. Depending on the compiler I
    use, the buffer doesn't always get flushed.

    If compiled with VC++ 6, then I need to add 'endl' to make the buffer
    get flushed (i.e. MyTextOut << whatever << endl).

    In VC++ 7 I don't need to include the 'endl' (i.e. MyText << whatever)

    Why?

    Is there a difference in implementation of streambuf between the two
    compilers? How can I make it work with both compiler versions without
    the need for 'endl'?
    , Jul 24, 2005
    #6
  7. CSpartan

    Ben Pope Guest

    wrote:
    > I entered another problem with the code. Depending on the compiler I
    > use, the buffer doesn't always get flushed.
    >
    > If compiled with VC++ 6, then I need to add 'endl' to make the buffer
    > get flushed (i.e. MyTextOut << whatever << endl).
    >
    > In VC++ 7 I don't need to include the 'endl' (i.e. MyText << whatever)
    >
    > Why?
    >
    > Is there a difference in implementation of streambuf between the two
    > compilers? How can I make it work with both compiler versions without
    > the need for 'endl'?


    What do you want to do? Flush the buffer without a newline?

    MyTextOut << whatever << std::flush;

    or

    MyTextOut << whatever;
    MyTextOut.flush();

    Ben
    --
    Questions by email will likely be ignored, please use the newsgroups.
    I'm not just a number. To many, I'm known as a String...
    Ben Pope, Jul 24, 2005
    #7
  8. CSpartan

    Guest

    I would like to know why the class behaves differently when compiled in
    VC++ 6 compared to VC++ 7.

    When compiled in VC++ 6 the following code does not print to stdout

    MyTextOut << whatever ;

    Recompiling the code using VC++ 7 will give output to the stdout. Why
    do I need to force flushing from VC++ 6?
    , Jul 24, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joe Hotchkiss
    Replies:
    1
    Views:
    1,200
  2. Koen
    Replies:
    1
    Views:
    584
    Victor Bazarov
    Oct 5, 2004
  3. Tron Thomas
    Replies:
    3
    Views:
    501
    Tron Thomas
    Nov 8, 2004
  4. Replies:
    0
    Views:
    271
  5. William Ahern

    Unicode Normalization of Text Streams

    William Ahern, Sep 14, 2006, in forum: C Programming
    Replies:
    4
    Views:
    351
    Simon Biber
    Sep 19, 2006
Loading...

Share This Page