Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Text formatting with streams

Reply
Thread Tools

Text formatting with streams

 
 
CSpartan
Guest
Posts: n/a
 
      07-20-2005
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.
 
Reply With Quote
 
 
 
 
Chris Dams
Guest
Posts: n/a
 
      07-21-2005
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

 
Reply With Quote
 
 
 
 
Dietmar Kuehl
Guest
Posts: n/a
 
      07-21-2005
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: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: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: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:stream' object which
internally uses this stream buffer for your stream object:

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

MyTextOut << whatever;

To avoid the two step construction of the output object, you might
derive from 'std:stream' and setup the proper stream buffer in the
constructor of the derived class. You should, however, don't try to
temper with 'std: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...
--
<(E-Mail Removed)> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence
 
Reply With Quote
 
ove_yue@hotmail.com
Guest
Posts: n/a
 
      07-21-2005
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:stream MyTextOut(&MyTextBuf);
int x = 3;

MyTextOut << "x equals " << x ;
}

 
Reply With Quote
 
ove_yue@hotmail.com
Guest
Posts: n/a
 
      07-21-2005
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.

 
Reply With Quote
 
ove_yue@hotmail.com
Guest
Posts: n/a
 
      07-24-2005
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'?

 
Reply With Quote
 
Ben Pope
Guest
Posts: n/a
 
      07-24-2005
http://www.velocityreviews.com/forums/(E-Mail Removed) 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...
 
Reply With Quote
 
ove_yue@hotmail.com
Guest
Posts: n/a
 
      07-24-2005
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?

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Unicode Normalization of Text Streams William Ahern C Programming 4 09-19-2006 02:19 PM
unsynchronized text streams in OGG (lyrics) matej.cepl@gmail.com Python 0 07-17-2006 04:04 AM
Detecting binary verses text file streams Tron Thomas C++ 3 11-08-2004 10:07 PM
Equivalent of fprintf's -20.15g formatting with C++ formatted streams ? Koen C++ 1 10-05-2004 01:53 PM
Re: printf-style formatting with streams. Joe Hotchkiss C++ 1 06-23-2003 10:53 PM



Advertisments