用c++20的std::location_source做日志输出
一个简单的输出日志功能
参考文章:
用C++20 std::location_source做日志输出 出自:purecpp 地址: www.purecpp.org
使用std::location_source须加载头文件#include <source_location>
因为是c++20的东西所以项目也需要设置为c++20标准
下面直接上原版代码
#include <iostream>
#include <source_location>
template<typename... Args>
class Log {
public:
Log(Args...args, const std::source_location location = std::source_location::current()) {
std::cout << "file: "
<< location.file_name() << "("
<< location.line() << ":"
<< location.column() << ") "
<< location.function_name() << ": ";
((std::cout << args << " "), ...);
std::cout << "\n";
}
};
template<typename... Args>
Log(Args...)->Log<Args...>;
int main() {
Log(222, "222", true);
}
文件路径有点长只想保留文件名
参考文章:c++ std::string截取子串
std::vector<std::string> StringSplit(const std::string& s, const std::string& delim)
{
std::vector<std::string> elems;
size_t pos = 0;
size_t len = s.length();
size_t delim_len = delim.length();
if (delim_len == 0) return elems;
while (pos < len)
{
int find_pos = s.find(delim, pos);
if (find_pos < 0)
{
elems.push_back(s.substr(pos, len - pos));
break;
}
elems.push_back(s.substr(pos, find_pos - pos));
pos = find_pos + delim_len;
}
return elems;
}
StringSplit(location.file_name(), "\\").back()
再加上时间戳
std::string getTime() {
time_t now = time(NULL);
tm* tm_t = localtime(&now);
char time_c[20];
sprintf(time_c, "%d-%d-%d %02d:%02d:%02d",
tm_t->tm_year + 1900, tm_t->tm_mon + 1, tm_t->tm_mday,
tm_t->tm_hour, tm_t->tm_min, tm_t->tm_sec
);//YY-MM-DD HH:MM:SS
return time_c;
}
都是一个颜色有点单调辨识度也不高
带颜色输出1
参考文章: C++ 输出颜色字体
后来测试发现这个改色只能在VS启动的控制台有效,发行之后直接运行exe没有效果!
原本函数
void red_print(string out){
cout << "\033[31;1m" << out << "\033[0m" << endl;
}
不太好用要稍微改造一下变成上色函数
考虑通用性的话要使用模板函数
再加上标准库std::stringstream
的类型转换
使用std::stringstream
要加载头文件#include <sstream>
template<typename T>
std::string red_printT(T t) {
std::stringstream s;
s << t;
return ("\033[31;1m" + s.str() + "\033[0m");
}
/*
cout << "\033[30;1m这是黑色\033[0m" << endl;
cout << "\033[31;1m这是红色\033[0m" << endl;
cout << "\033[32;1m这是绿色\033[0m" << endl;
cout << "\033[33;1m这是黄色\033[0m" << endl;
cout << "\033[34;1m这是蓝色\033[0m" << endl;
cout << "\033[35;1m这是紫色\033[0m" << endl;
cout << "\033[36;1m这是青色\033[0m" << endl;
cout << "\033[37;1m这是白色\033[0m" << endl;
*/
带颜色输出2
上面那个上色虽然好用但是只能使用在vs中运行的程序才有效果
所以另外找了个带颜色输出的方法,这个方法需要使用#include <Windows.h>
头文件里面的东西实现的
参考文章: C++ 输出彩色的控制台
class Log {
//加入底下这些底下
WORD colorOld;
HANDLE handle;
CONSOLE_SCREEN_BUFFER_INFO csbi;
void coloring_up(int color){
handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(handle, &csbi);
colorOld = csbi.wAttributes;
SetConsoleTextAttribute(handle, color);
}
void coloring_down() {
SetConsoleTextAttribute(handle, 0x0F);//黑底白字
}
//......
}
然后再构造函数跟析构函数中稍作修改
Log(Args...args, const std::source_location location = std::source_location::current()) {
std::string msg = "[" + getTime() + "] ";//GetExePath() + "\\log\\" + getTime() + ".log";
msg.append(StringSplit(location.file_name(), "\\").back());//文件路径
msg.append("->[");
msg.append(std::to_string(location.line()));//触发行数
msg.append("]行[");
//msg.append(std::to_string(location.column()));//?
msg.append(location.function_name());//触发函数名称
msg.append("()]->").append("\n Log >>>>>>>>>: ");
coloring_up(0x0E);//上黑底黄字
std::cout << msg;
coloring_down();//恢复黑底白字
coloring_up(0x09);//上黑底蓝字
((std::cout << args << " "), ...);
coloring_down();//恢复黑底白字
std::cout << "\n";
}
~Log() {
coloring_down();//恢复黑底白字
}
//SetConsoleTextAttribute(handle,0x07);填十六进制数字,前面的数字代表背景色,后面的代表前景色。
//SetConsoleTextAttribute(handle,7);直接传入十进制数字。
变更输出方向到数据库
…