Solved

To IOStream gurus

Posted on 2001-09-13
13
512 Views
Last Modified: 2013-12-14
Hi,
I am trying to implement logging system using iostreams. My question is: how can I add date/time stamp on iostream basis? What I want to acheive is as following:

cmylog << "Test" << std::endl;

And the output shall be

10:00 Test

(I will be able to configure time stamp format but it is beyond my question, do not worry about it)

Please advise

P.S. I will increase points for working solution.
0
Comment
Question by:proskig
  • 5
  • 4
  • 4
13 Comments
 
LVL 8

Expert Comment

by:mnashadka
ID: 6479119
One way would be to store the data in a std::ostringstream, and when the stream insertion operator is called, you can see if the inserted data is the first data in the ostringstream (by checking ostringstream.str().empty()).  Then, when you see std::endl come in, dump the ostringstream.str() to the file and clear it.  This is the approach I took when I had a similar requirement.  Hope this helps.
0
 
LVL 5

Author Comment

by:proskig
ID: 6479138
mnashadka: What's the correct way to recognize std::endl? I mean flushing buffer? Another question is: which operator to overload ?
0
 
LVL 8

Expert Comment

by:mnashadka
ID: 6479203
Actually, probably an easier way would be to just have 2 stream insertion operators, like:
template<class T>
cmylog &operator<<(T &value)
{
  stream << value;
}

And then another one to dump the ostringstream to the file

cmylog &operator<<(std::ostream &(*end_of_line) (std::ostream &))
{
  file << time() << stream.str() << end_of_line;
  // Clear the ostringstream
}

Of course, the stream variable is the ostringstream and file is the ofstream.
0
 
LVL 7

Expert Comment

by:peterchen092700
ID: 6479213
I once did something similar, providing my own class with this (pseudo-)code:


class mystream
{
  ostream * os;
}

// default template to "redirect" all output to the ostream
template <class T>
mystream & operator << (mystream & s, T const & x)
{
  s->os << x;
}

// specific overload for endl:
mystream & operator << (mystream & s, std::endl const & x)
{
  s->os << x;
  s->os << ... // output time for new line
}

Peter


Note 1: I found the streams extremely slow for this purpose. Since we had to log *tons* of data, I finally rewrote the thing to use printf-style (which is less fun, but more readable and faster)

Note 2: I'm not quite sure about the const & - just tell me if there are problems.

0
 
LVL 8

Expert Comment

by:mnashadka
ID: 6479262
perterchen, what happens if you don't have a new line for a long time?  This is assuming that the next log statement will be coming within seconds.  Just curious.
0
 
LVL 5

Author Comment

by:proskig
ID: 6479604
I do have problems with specialization for std::endl

class mystream
{
  std::ostream *os;
};

// default template to "redirect" all output to the ostream
template <class T>
mystream & operator << (mystream & s, T const & x)
{
 *(s.os) << x;
}

// specific overload for endl:
mystream & operator << (mystream & s, std::endl & x)
{
 *(s.os) << x;
}


Produces error
error C2321: syntax error : unexpected 'endl'

for MSVC
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 7

Expert Comment

by:peterchen092700
ID: 6480172
mnashadka: you're right - in this case, you need to use a flag

class mystream
{
 ostream * os;
 bool needWriteTime; // init to true in CTor
}

// default template to "redirect" all output to the ostream
template <class T>
mystream & operator << (mystream & s, T const & x)
{
 if (s->needWriteTime)
   s->os << "10:00 "; // ;)
 s->os << x;
}

// specific overload for endl:
mystream & operator << (mystream & s, std::endl const & x)
{
 s->os << x;
 s->needWriteTime = true;
}

proksig: I'll look into it, I'm myself not sure with the syntax...
0
 
LVL 8

Expert Comment

by:mnashadka
ID: 6480222
cmylog &cmylog::operator<<(std::ostream &(*end_of_line) (std::ostream &))
is the syntax for endl
0
 
LVL 8

Expert Comment

by:mnashadka
ID: 6480238
I still think it's better to buffer the output, though.  If you don't and your application is (or becomes) multithreaded, your log messages will be interspersed and you won't be able to tell them apart (I know this from experience).  But that's just my 2 cents.
0
 
LVL 7

Expert Comment

by:peterchen092700
ID: 6480300
Hmmm... found a solution, but... seee below..

typedef ostream & (tEndl)(ostream & os);

mystream & operator << (mystream & s,  tEndl x)
{
   tEndl * endlfunc = endl;
   x(*s.os); // s.os << endl;
   if ( x == endlfunc)   // ***
      (*s.os) << "10:40 ";
   return s;
}


I initially thought the endl manip is declared as class - but no, its a function.

The point I find a bit awkward in an STL environment is that at ***, we actually have to compare two function pointers to see if the manipulator passed is actually "endl", or something else (like flush). Although I see no *technical* problem with this.

P.S. next comment: working sample (console app)
0
 
LVL 7

Accepted Solution

by:
peterchen092700 earned 200 total points
ID: 6480303
#include "stdafx.h"
#include <ios>
#include <iostream>

using namespace std;

class mystream
{
   public:
      ostream * os;
      bool      needtime;
      mystream() { needtime = true; }
};

static int time; // instead of time....

// default template to "redirect" all output to the ostream
template <class T>
mystream & operator << (mystream & s, T const & x)
{
   if (s.needtime) {
      ++time;
      (*s.os) << time << " ";  
      s.needtime = false;
   }
 (*s.os) << x;
 return s;
}

int f(int);
int f(int,int);


// specific overload for endl:
//typedef std::basic_ostream<char,std::char_traits<char> >  & (tEndl)(std::basic_ostream<char, std::char_traits<char> > & os);
typedef ostream & (tEndl)(ostream & os);

mystream & operator << (mystream & s,  tEndl x)
{
   x(*s.os); // s.os << x;

   tEndl * endlfunc = endl/*<char, std::char_traits<char> >*/;
   if ( x == endl)
      s.needtime = true;


   return s;
}

int main(int argc, char* argv[])
{
   mystream s;
   s.os = &cout;

   s <<  "Hello World " << endl;
   s <<  "Yeah yeah yeah " << flush << "It works " << endl;    // flush: to test another manip
     return 0;
}

// it's not a clean example... but shows the principles
0
 
LVL 5

Author Comment

by:proskig
ID: 6480420
Cool Thanks!
0
 
LVL 5

Author Comment

by:proskig
ID: 6480431
Cool thanks.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
mixing C++ & C# in Vis Studio 2013 7 141
What is Codeanywhere used for and can EE provide example of use 9 197
Compile GLUT with Visual Studio 2015 1 108
debug as  junit test 4 73
Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand columnThat will then direct you to their download page.From that page s…
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now