Welcome to Steve’s Webshed

Games, Screensavers, and Photo Utilities
Tips for C++ and C++Builder



Gotta website? Wanna earn some cash? Sign up to be an affiliate!

Google
Search Now:
In Association with Amazon.com

Snip #1: Streaming struct tm


One problem I seem to have struggled with in a number of projects is sticking the date and time in a file, usually to do some logging. My previous solution went something like this:

ofstream fout("logfile.txt"); // or any other stream
char tstr[SOME_MAX];
time_t now = time(0);
strcpy(tstr, ctime(now));
tstr(strlen(tstr)-1) = 0;  // chop off the trailing \n
fout << tstr;

The problem with this solution is that it "felt" like a hack. I really wanted to find a way to do this using standard ostreams, without having to screw around with the \n, in seamless way. Why shouldn't I be able to write something like this and have it work:

ofstream fout("logfile.txt"); // or any other stream
time_t now = time(0);
fout << *localtime(&now);

Ideally, I wanted my solution to not only output the date & time, but do it using the user's locale. After doing a bit of net spelunking, I came across http://www.cantrip.org, which has a great discussion on using locales. That led me to this solution:

template<class charT, class traits>
std::basic_ostream<charT, traits>&
    operator<<(std::basic_ostream<charT,traits>& os,
    const std::tm& date)
{
    typedef std::ostreambuf_iterator<charT,traits> outIter_t;
    typedef std::time_put<charT, outIter_t> Facet;

    // makes this safe in a multithreaded environment
    std::basic_ostream<charT, traits>::sentry cerberus(os);
    if ( cerberus )
    {
        // output the date & time, plus weekday and
        // AM/PM indicator, in the local format
        static const char format[] = "%a %x %X %p";
        const Facet& fac = std::use_facet<Facet>(os.getloc());
        if ( fac.put(os, os, os.fill(), &date, format, format + 11).failed() )
		{
            os.setstate(os.badbit);
		}
    }

    return os;
}

This solution works great on standard conforming compilers. On MSVC6, it chokes. A solution that works is:

template<class charT, class traits>
std::basic_ostream<charT, traits>&
    operator<<(std::basic_ostream<charT,traits>& os,
    const tm& date)
{
    typedef std::ostreambuf_iterator<charT,traits> outIter_t;
    typedef std::time_put<charT, outIter_t> Facet;

    // makes this safe in a multithreaded environment
    std::basic_ostream<charT, traits>::sentry cerberus(os);
    if ( cerberus )
    {
        // output the date & time, plus weekday and AM/PM
        // indicator, in the local format; note that the
        // simpler version of put (std version above)
        // doesn't work in MSVC
        static const char format[] = "%a %x %I:%M:%S %p";
        const Facet& fac = std::_USE(os.getloc(), Facet);
        if ( fac.put(os, os, &date, format, format + 17).failed() )
		{
            os.setstate(os.badbit);
		}
    }

    return os;
}

One bit I've omitted from the code snips above is that it's a good idea to imbue the output stream with the desired locale, or at least with the default like so:

ofstream fout("logfile.txt");
fout.imbue( locale("") );

So now, with a little help from the preprocessor, I can stream out the date and time just like any other piece of data, and using the local format, to boot.

For those who are interested, here's the complete file, streamext.h.

Latest Releases
Webifier 1.1.0 - 11/14/2007 - Show your pictures to the world with this web photo gallery creator.
PictureSaver 4.2.5 - 03/10/2006 - Turn your pictures into a slideshow screensaver; great with digital cameras!
RandomSaver 2.0.3 - 06/14/2002 - Got a lot of screen savers? Why watch just one? RandomSaver lets you watch 'em all!
GullBlaster 1.1 - 05/12/2002 - Tired of them seagulls? Now you can get even! Blast them before they blast you!
FontViewer 1.1.1 - 06/13/2002 - Preview all the installed fonts on your system.

Firefox 2
Get Thunderbird!

Monitor page
for changes

it's private
powered by
ChangeDetection

Valid HTML 4.01 Transitional


This page has been visited 548 times. View usage statistics.