在 C++ 中重用 strftime
Reusing strftime in C++
我正在编写一个程序,需要将当前日期和时间写入日志文件,虽然代码可以运行,但有很多重复代码。密码是
#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;
}
}
}
我不得不在每一节中包含 { },以便变量仅用于一个特定的代码块。如果我不使用它们,那么我会在编译时出错。
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);
^
加上大括号,编译运行没有问题。
写入日志文件的信息会有所不同,需要和时间分开。
由于我是 C++ 的新手,我觉得我把问题复杂化了,所以任何指导将不胜感激。
我是 运行 CentOS 7,g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
问候
琥珀玛丽
更新
感谢您的帮助。完整代码如下:
#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);
}
希望对其他人有所帮助。
琥珀玛丽
问题是您正在重新声明变量 "timeNow" 并调用其构造函数以赋予其值 "timeBuffer"。这适用于括号,因为每个括号都是一个新范围。 "timeNow" 的每个重新声明对其所有其他声明都是不可见的,因此编译器方面没有混淆。要摆脱这种情况,请使用赋值而不是尝试重新声明变量。使用 timeNow = timeBuffer
而不是
string timeNow(timeBuffer);
我试过这段代码,它在我这边使用 g++ 工作:
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);
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);
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);
timeNow = timeBuffer;
cout << timeNow << " - End of log." << endl;
vLog << timeNow << " - End of log." << endl;
}
编写一个函数来包装您的代码。参数应该是 ofstream、strftime 格式参数和日志消息(“- 第一行代码”,..)
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;
}
是的,这是可能的:)
让我们首先考虑整个获取和格式化时间业务。重复代码中唯一可变的是格式字符串,所以让我们把它作为一个参数:
std::string formattedCurrentTime(char const *const format) {
std::time_t const rawTime = std::time(nullptr);
std::tm const *const timeInfo = std::localtime(&rawTime);
char buffer[80];
std::size_t const length = std::strftime(buffer, sizeof buffer, format, timeInfo);
return {buffer, buffer + length};
}
然后我们可以查看重复的日志行。由于整个 operator <<
重载和多态性业务,通用解决方案实施起来有点棘手,但您的案例看起来足够一致,可以从量身定制的解决方案中受益:
auto const logBookend = [&](std::string const &message) {
auto const timeNow = formattedCurrentTime("%A %d %b %Y %r %Z");
std::cout << timeNow << " - " << message << std::endl;
vLog << timeNow << " - " << message << std::endl;
};
auto const logLine = [&](std::string const &message) {
auto const timeNow = formattedCurrentTime("%r");
std::cout << timeNow << " - " << message << std::endl;
vLog << timeNow << " - " << message << std::endl;
};
注意:请参阅 this question 为什么 不 使用 using namespace std;
。
我正在编写一个程序,需要将当前日期和时间写入日志文件,虽然代码可以运行,但有很多重复代码。密码是
#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;
}
}
}
我不得不在每一节中包含 { },以便变量仅用于一个特定的代码块。如果我不使用它们,那么我会在编译时出错。
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);
^
加上大括号,编译运行没有问题。
写入日志文件的信息会有所不同,需要和时间分开。
由于我是 C++ 的新手,我觉得我把问题复杂化了,所以任何指导将不胜感激。 我是 运行 CentOS 7,g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
问候 琥珀玛丽
更新
感谢您的帮助。完整代码如下:
#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);
}
希望对其他人有所帮助。
琥珀玛丽
问题是您正在重新声明变量 "timeNow" 并调用其构造函数以赋予其值 "timeBuffer"。这适用于括号,因为每个括号都是一个新范围。 "timeNow" 的每个重新声明对其所有其他声明都是不可见的,因此编译器方面没有混淆。要摆脱这种情况,请使用赋值而不是尝试重新声明变量。使用 timeNow = timeBuffer
而不是
string timeNow(timeBuffer);
我试过这段代码,它在我这边使用 g++ 工作:
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);
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);
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);
timeNow = timeBuffer;
cout << timeNow << " - End of log." << endl;
vLog << timeNow << " - End of log." << endl;
}
编写一个函数来包装您的代码。参数应该是 ofstream、strftime 格式参数和日志消息(“- 第一行代码”,..)
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;
}
是的,这是可能的:)
让我们首先考虑整个获取和格式化时间业务。重复代码中唯一可变的是格式字符串,所以让我们把它作为一个参数:
std::string formattedCurrentTime(char const *const format) {
std::time_t const rawTime = std::time(nullptr);
std::tm const *const timeInfo = std::localtime(&rawTime);
char buffer[80];
std::size_t const length = std::strftime(buffer, sizeof buffer, format, timeInfo);
return {buffer, buffer + length};
}
然后我们可以查看重复的日志行。由于整个 operator <<
重载和多态性业务,通用解决方案实施起来有点棘手,但您的案例看起来足够一致,可以从量身定制的解决方案中受益:
auto const logBookend = [&](std::string const &message) {
auto const timeNow = formattedCurrentTime("%A %d %b %Y %r %Z");
std::cout << timeNow << " - " << message << std::endl;
vLog << timeNow << " - " << message << std::endl;
};
auto const logLine = [&](std::string const &message) {
auto const timeNow = formattedCurrentTime("%r");
std::cout << timeNow << " - " << message << std::endl;
vLog << timeNow << " - " << message << std::endl;
};
注意:请参阅 this question 为什么 不 使用 using namespace std;
。