Formating Output of std::ostream

J

Johannes Barop

Hi,

I want to format the output of a 'std::eek:stream', but i dont know how to
do it [in ansi-c++].

Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.


Any Ideas?
Thanks
 
S

Stephan Grein

Johannes said:
Hi,

I want to format the output of a 'std::eek:stream', but i dont know how to
do it [in ansi-c++].

Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.


Any Ideas?
Thanks
Look up on dinkumware.com or elsewhere for the manipulators for <iostream>.

Greets,
 
J

Jonathan Mcdougall

Johannes said:
Hi,

I want to format the output of a 'std::eek:stream', but i dont know how to
do it [in ansi-c++].

Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.

You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.

For the new lines, you'll have to parse the output and find them
yourself.

class timestamp_out
{
public:
void print(const std::string& s)
{
// tokenize s using \n as separator
// see boost::tokenizer
// output each line preceded by a timestamp
}
};

timestamp_out& operator<<(timestamp_out& out, const std::string& s)
{
out.print(s);
return out;
}

For the statements, on top of my head, you could return a proxy from
the first operator<< and have that proxy set a flag in timestamp_out
when it is destroyed. Since this temporary will exist until the end of
the statement, it will probably work.

Jonathan
 
J

Johannes Barop

Jonathan said:
Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.
You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.

Yeha. The second one is my problem :/

For the statements, on top of my head, you could return a proxy from
the first operator<< and have that proxy set a flag in timestamp_out
when it is destroyed. Since this temporary will exist until the end of
the statement, it will probably work.

Hm, can u explain it to me with more detail? I'am not that fit in C++
 
P

puzzlecracker

Johannes said:
Jonathan said:
Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.
You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.

Yeha. The second one is my problem :/

For the statements, on top of my head, you could return a proxy from
the first operator<< and have that proxy set a flag in timestamp_out
when it is destroyed. Since this temporary will exist until the end of
the statement, it will probably work.

Hm, can u explain it to me with more detail? I'am not that fit in C++

He wrote a fairly simple and intuitive enough to understand example to
illustrate the concept and solve your problem. If you're still puzzled,
you should read basics on operators and c++ in general. Start with
FAQ. Really.


Best,
 
J

Jonathan Mcdougall

Johannes said:
Jonathan said:
Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.
You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.

Yeha. The second one is my problem :/

For the statements, on top of my head, you could return a proxy from
the first operator<< and have that proxy set a flag in timestamp_out
when it is destroyed. Since this temporary will exist until the end of
the statement, it will probably work.

Hm, can u explain it to me with more detail? I'am not that fit in C++

When you do

out << "one" << "two";

you'll want the first operator to return a proxy.

timestamp_out_proxy operator<<(timestamp_out& out, const std::string&
s)
{
timestamp_out_proxy p(out);
p.print(s);
return p;
}

So

operator<<(out, "one")

will return the proxy. Next, you'll want to define an operator<< for
the
proxy.

timestamp_out_proxy& operator<<
(timestamp_out_proxy& p, const std::string& s)
{
p.print(s);
return p;
}

Your proxy is a way to do something before the first output and after
the
last output in a single statement. That is, with

timestamp_out out;
out << "one" << "two";

a proxy will get constructed for "one" and will be destroyed after
"two"
(at the end of the statement). So you can use the constructor and
destructor of the proxy.

class timestamp_out_proxy
{
public:

// This constructor is called when outputting "one". It stores the
// stream and you'll understand copy_ later.
//
timestamp_out_proxy(timestamp_out& out)
: out_(out),
copy_(false)
{
}

// This constructor is called when the proxy is returned from the
// operator<<. Note that we return it by value so a copy may be
created.
// That means the original proxy will get destroyed and you'll get
// additional timestamps printed. You want the action to take place
at
// the destruction of the last proxy on the statement so you have to
// track copy construction.
//
timestamp_out_proxy(timestamp_out_proxy& p)
: out_(p.out_),
copy_(false)
{
p.copy_ = true;
}


// You'll see newline_ and timestamp_ later.
//
~timestamp_out_proxy()
{
if (!copy_)
{
// when a proxy is destroyed (end of a statement), you want the
// next output to be on a new line with [TIMESTAMP]
//
out_.newline_ = true;
out_.timestamp_ = true;
}
}


// This only forwards to the stream.
//
void print(const std::string& s)
{
out_.print(s);
}


private:
timestamp_out& out_;
bool copy_;
};

Now, on with the actual stream.

class timestamp_out
{
friend timestamp_out_proxy;
public:

// A trick here. At the very first output, you want to print a
timestamp
// but no new line.
//
timestamp_out()
: newline_(false),
timestamp_(true)
{
}

// Prints the string with timestamps and newlines
//
void print(const std::string& s)
{
// A newline will be printed iif a proxy object was destroyed.
if (newline_)
std::cout << "\n";

// A timestamp will be printed if
// 1) the stream was just created (very first output)
// 2) a proxy object was destroyed
if (timestamp_)
std::cout << "[TIMESTAMP] ";

// All subsequent strings will be printed as is (unless they have
// newlines in them).
newline_ = false;
timestamp_ = false;

// This will replace
// "Hi.\nI'm a"
// with
// "Hi.\n[TIMESTAMP} I'm a"
std::cout << boost::replace_all_copy(s, "\n", "\n[TIMESTAMP] ");
}

private:
// these control the *next* output
bool newline_;
bool timestamp_;
};

And finally:

int main()
{
timestamp_out out;

out << "Hi.\nI'am a" << " Computer.";
out << "Nice.";
}


Jonathan
 
J

Jonathan Mcdougall

puzzlecracker said:
He wrote a fairly simple and intuitive enough to understand example to
illustrate the concept and solve your problem. If you're still puzzled,
you should read basics on operators and c++ in general. Start with
FAQ. Really.

Hey, I'll decide if I want to answer or not. If *you* don't, just stay
quiet.


Jonathan
 
Z

Zara

Hi,

I want to format the output of a 'std::eek:stream', but i dont know how to
do it [in ansi-c++].

Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.


Any Ideas?
Thanks


If you derive a class form std::stringbuf, and override sync(), and
create a std::eek:stream with it, you may do anything whenever you put an
std::endl on the stream.

I have done exactly for this: writng a timestamp on every line, and it
works perfectly, but you should change your code to:

my_out << "Hi.<<std::endl<<I'am a" << " Computer."<<std::endl;
my_out << "Nice."<<std::endl;
 
D

Dietmar Kuehl

Jonathan said:
Johannes said:
Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.

You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.

Both are extremely easy to do although I would do them in two separate
classes, both filtering stream buffers:
- one breaks the lines after whatever amount of characters, possibly
taking whitespaces into account to detect where to break a line
- one injects whatever prefix is desired at the beginning of a line

Fiddling with 'std::eek:stream' derivates and/or classes overloading
'operator<<()' does not yield the desired results and is troublesome
at best.
 
J

Jonathan Mcdougall

Dietmar said:
Jonathan said:
Johannes said:
Example:
int main()
{
my_out << "Hi.\nI'am a" << " Computer.";
my_out << "Nice.";
}

Now i want to get this as output:
[TIMESTAMP] Hi.
[TIMESTAMP] I'am a Computer.
[TIMESTAMP] Nice.

You seem to want two things here: print timestamps on each line AND at
the end of each statement. The former is easy and the latter is not.

Both are extremely easy to do although I would do them in two separate
classes, both filtering stream buffers:
- one breaks the lines after whatever amount of characters, possibly
taking whitespaces into account to detect where to break a line

The OP wanted a new line to be added at the end of a statement:

my_out << "First" << "line\nSecond" << "line";
my_out << "Third" << "line";

I don't think this is easy because there is no way for my_out to now
whether two operations are in the same statement.
- one injects whatever prefix is desired at the beginning of a line
Yes.

Fiddling with 'std::eek:stream' derivates and/or classes overloading
'operator<<()' does not yield the desired results and is troublesome
at best.

Would you care to give an example using stream buffers?


Jonathan
 
D

Dietmar Kuehl

Jonathan said:
The OP wanted a new line to be added at the end of a statement:

my_out << "First" << "line\nSecond" << "line";
my_out << "Third" << "line";

OK, I missed this - probably because I hadn't even considered that
someone what to do something that - er - unusual. Had I noticed
that, I would have argued against doing something like this. BTW,
one reason why I may have missed the fact that he [to me suddenly]
wants to break the line at the end of the statement is that in a
German newsgroup he posted the same question asking for a break
after a certain number of characters.

I would argue against inserting newlines at the end of a statement
anyway: it is far too error prone! It is pretty common to split
existing lines into multiple statements in which case suddenly
newlines would be conjured up.
I don't think this is easy because there is no way for my_out to now
whether two operations are in the same statement.

Yes. The only way to do something like this using an appropriate
temporary which inserts a newline when it gets destructed. However,
as stated before, I would not combine statements with newlines or
I would make the situations at least pretty obvious, e.g. by using
a corresponding temporary. I think it is doable silently with a
class using appropriate conversions but it would be a kludge.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top