http://jingyan.baidu.com/article/1709ad80b46ff54634c4f0b8.html
项目开发过程中经常用到了打日志的函数,日志函数怎么写,日志函数主要分两步,函数的实现和宏开关的控制,附带增加返回最后一次错误信息的字符串函数,包括字符串的语言设置等;
日志函数同时写到了控制台(没有创建的程序内部自己创建),文件(名字安时间起,防止冲突,防止文件过大),错误警告弹出messagebox等,如果有想写数据库的,可以按照我的格式继续添加哦,程序是按posix标准写的(messagebox那行注释掉的话),可以横跨各大平台;
方便他人亦是方便自己,如果觉得还行就点下赞吧,这样可以帮助其他人更快的找到解决问题的方法;有疑问的也可留言哦, 谢谢!
方法/步骤
-
1、日志函数的实现的完整的代码:
void fkTrace(int nLevel, const char* pcFormat, ...)
{
static char pcFile[256];
/// 获取当前时间
time_t rawTime = { 0 };
time(&rawTime);
struct tm* t = localtime(&rawTime);
if (0 == *pcFile)
{
/// 创建日志目录
char pcFolder[256] = { 0 };
GetCurrentDirectoryA(sizeof(pcFolder), pcFolder);
strcat(pcFolder, "\\log");
CreateDirectoryA(pcFolder, NULL);
/// 获取log日志文件名称
sprintf(pcFile, "%s\\%04d-%02d-%02d %02d-%02d-%02d.log", pcFolder, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
AllocConsole();
freopen("CONOUT$", "w", stdout);
}
/// 解析字符串
char pcTrace[4096] = { 0 };
sprintf(pcTrace, "%04d-%02d-%02d %02d:%02d:%02d | ", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
va_list arglist;
va_start(arglist, pcFormat);
vsprintf(strrchr(pcTrace, '\0'), pcFormat, arglist);
va_end(arglist);
/// 打印到控制台
fputs(pcTrace, stdout);
/// 打印到文件
FILE* fp = fopen(pcFile, "a+");
if (NULL != fp)
{
fputs(pcTrace, fp);
fclose(fp);
}
/// 将警告和错误消息用 messagebox 提示
if (nLevel <= 1)
{
MessageBoxA(NULL, pcTrace, "errinfo", MB_OK);
}
}
-
日志函数的宏控制代码:
调试时的代码:
#define LOG_ERROR(...) fkTrace(0, __VA_ARGS__)
#define LOG_WARN(...) fkTrace(1, __VA_ARGS__)
#define LOG_DEBUG(...) fkTrace(2, __VA_ARGS__)
#define LOG_INFO(...) fkTrace(3, __VA_ARGS__)
发布时的代码:
#define LOG_ERROR(...) fkTrace(0, __VA_ARGS__)
#define LOG_WARN(...) /// fkTrace(1, __VA_ARGS__)
#define LOG_DEBUG(...) /// fkTrace(2, __VA_ARGS__)
#define LOG_INFO(...) /// fkTrace(3, __VA_ARGS__)
-
根据错误ID返回对应的错误信息:
char* fkGetErrorInfo(int nErrno)
{
static char szErr[4000] = { 0 };
memset(szErr, 0, sizeof(szErr));
DWORD dwLanguageId = MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED);
/// MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); /// 美国英语 (US)
/// MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK); /// 英国英语 (GB)
/// MAKELANGID(LANG_CHINESE_SIMPLIFIED, SUBLANG_CHINESE_SIMPLIFIED); /// 简体中文 (zh)
/// MAKELANGID(LANG_CHINESE_TRADITIONAL, SUBLANG_CHINESE_TRADITIONAL); /// 繁体中文 (zh)
/// LANG_USER_DEFAULT 用户默认
/// LANG_SYSTEM_DEFAULT 系统默认
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, nErrno, dwLanguageId, (LPSTR)&szErr, sizeof(szErr), NULL);
int nLen = strlen(szErr);
/// 去掉最后的换行符 "/r/n"
if (nLen > 2)
{
if (0 == memcmp(szErr + nLen - 2, "\r\n", 2))
{
szErr[nLen - 2] = 0;
}
}
return szErr;
}
效果如下:
-
返回最后一个错误信息对应的字符串:
#define ERRINFO fkGetErrorInfo(GetLastError())
-
最后的效果图如下:
-