Search code examples
c++strftime

Reusing strftime in C++


I am writing a program, that requires writing of the current date and time to a log file, although the code is working, there are a lot of repeating code. The code is

#include<iostream>
#include<fstream>
#include<unistd.h>

using namespace std;

string logFile="/home/shared/c++/time.log";
char timeBuffer[80];

int main()
{
     struct tm * timeInfo;
     time_t rawtime;

     ofstream vLog(logFile.c_str(), ios_base::app | ios_base::out);
          {
               {
                    time (&rawtime);
                    timeInfo = localtime(&rawtime);
                    strftime(timeBuffer,sizeof(timeBuffer),"%A %d %b %Y %r %Z",timeInfo);
                    string timeNow(timeBuffer);
                    cout << timeNow << " - Start of log." << endl;
                    vLog << timeNow << " - Start of log." << endl;
               }
               // Do a part of the code
               {
                    time (&rawtime);
                    timeInfo = localtime(&rawtime);
                    strftime(timeBuffer,sizeof(timeBuffer),"%r",timeInfo);
                    string timeNow(timeBuffer);
                    cout << " " << timeNow << " - 1st Line of log." << endl;
                    vLog << " " << timeNow << " - 1st Line of log." << endl;
               }
               // Do more code
               {
                    time (&rawtime);
                    timeInfo = localtime(&rawtime);
                    strftime(timeBuffer,sizeof(timeBuffer),"%r",timeInfo);
                    string timeNow(timeBuffer);
                    cout << " " << timeNow << " - 2nd Line of log." << endl;
                    vLog << " " << timeNow << " - 2nd Line of log." << endl;
                }
                // Do the last part of the code
                {
                    time (&rawtime);
                    timeInfo = localtime(&rawtime);
                    strftime(timeBuffer,sizeof(timeBuffer),"%A %d %b %Y %r %Z",timeInfo);
                    string timeNow(timeBuffer);
                    cout << timeNow << " - End of log." << endl;
                    vLog << timeNow << " - End of log." << endl;
                }
        }
}

I have had to include the { } on each section so that the variables are only used for the one particular code block. If I do not use them, then I get errors on compilation.

time.cpp: In function "int main()":
time.cpp:54:29: error: redeclaration of "std::string timeNow"
    string timeNow(timeBuffer);
                             ^
time.cpp:45:11: error: "std::string timeNow" previously declared here
    string timeNow(timeBuffer);
           ^

With the braces included, then it compiles and runs with no issue.

The information that will be written to the log file will be varied, so it needs to stand separate from the time.

As I am new to C++, I feel like I am over complicating the issue, so any guidance would be appreciated. I am running CentOS 7, and g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)

Regards Amber-Marie

Update

Thank you for the help. The full code now reads:

#include<iostream>
#include<fstream>
#include<unistd.h>

std::string logFile="/home/shared/c++/time.log";
char timeBuffer[80];
void getTime(std::ofstream &vLog, const std::string &format_args, const std::string &message)
{
    struct tm * timeInfo;
    time_t rawtime;
    time (&rawtime);
    timeInfo = localtime(&rawtime);
    strftime(timeBuffer,sizeof(timeBuffer),format_args.c_str(),timeInfo);
    std::string timeNow(timeBuffer);
    std::cout << timeNow << message << std::endl;
    vLog<< timeNow << message << std::endl;
}

int main()
{
    std::ofstream vLog(logFile.c_str(), std::ios_base::app | std::ios_base::out);
    getTime(vLog, "%A %d %b %Y %r %Z", " - Start of logging");
    // Do part of the code
    getTime(vLog, " %r", " - 1st line of log");
    // Do more code
    getTime(vLog, " %r", " - 2nd line of log");
    // Do the last part of the code
    getTime(vLog, "%A %d %b %Y %r %Z", " - End of logging");
    vLog << std::endl;
    return (0);
}

Hopefully others will find this helpful.

Amber-Marie


Solution

  • Write a function to wrap your code. The parameters should be ofstream, strftime format argument and the log message ( "- 1st line of code", ..)

    void foo(ofstream &vLog, const string &format_args, const string &message)
    {
        struct tm * timeInfo;
        time_t rawtime;
    
        time (&rawtime);
        timeInfo = localtime(&rawtime);
        strftime(timeBuffer,sizeof(timeBuffer),format_args.c_str(),timeInfo);
        string timeNow(timeBuffer);
        cout << timeNow << message << endl;
        vLog<< timeNow << message << endl;
    }
    
    int main()
    {
        ofstream vLog(logFile.c_str(), ios_base::app | ios_base::out);
    
        foo(vLog, "%A %d %b %Y %r %Z", " - 1st Line of log.");
        // Do a part of the code
        foo(/* second call */);
        // Other stuff
        foo(/* 3rd call */);
        // ...
    
        return 0;
    }