- 目标
设计一个函数库,封装五个函数,实现日志输出与断言判断等功能
- 函数原型及其实现
2.1 格式化日志输出函数:PrintLog PrintTraceLog
原型:int PrintLog(FILE *pfile, const char *pformat, …);
功能说明:按照字符串pformat的内容,控制后继参数的数量和格式,并在文件流中输出。
原型:int PrintTraceLog(char *pformat, …);
功能说明:调用PrintLog将信息写入日志文件
2.2 源码
int PrintLog(FILE *pfile, const char *pformat, ...)
{
va_list _va_list;//声明变长参数列表
TIMESTRU timestru;
char szBuf[1024];
int nLen;
if(pformat == NULL || pfile == NULL)/*参数合法性检查*/
return -1;
timestru = GetTime();//定义在后面专题
nLen = sprintf(szBuf, "INFO: %04d.%02d.%02d.%02d:%02d:%02d [%d]: ",
timestru.nYear, timestru.nMon, timestru.nDay,
timestru.nHour, timestru.nMin, timestru.nSec, getpid());
va_start(_va_list, pformat);//初始化变长参数列表
nLen += vsprintf(szBuf + nLen, pformat, _va_list);//传递变长参数列表
va_end(_va_list);//结束使用变长参数列表
nLen += sprintf(szBuf + nLen, "/n");//添加换行符
if(fputs(szBuf, pfile) != EOF && fflush(pfile) != EOF)//输出并刷新文件流
return 0;
return -2;
}
int PrintTraceLog(const char *pformat, ...)
{
FILE *fp = NULL;
int ret = -1;
if((fp = fopen(TRACE_FILE, "a")) != NULL)
{
ret = PrintLog(fp, pformat);//写日志文件
fclose(fp);
return ret;
}
return ret;
}
2.3 内存打印函数
原型:int PrintHexLog(FILE *pfile, void *pData, int nSize)
功能:将一段内存内容写入输出流
原型:int PrintTraceHexLog(void *pData, int nSize)
功能: 调用PrintHexLog将一段内存内容写入日志文件中
2.4 源码
/**
**打印一段内存
*/
int PrintHexLog(FILE *pfile, void *pData, int nSize)
{
char szBuf[1024];
char cLine[1024];
int nLen=0;
int nPos;
int nLineSize;/*每行的字节数,小于或等于16*/
int n;
int nLine; /*行号*/
PrintLog(pfile, "address[%d] size[%d]", cLine, nSize);
for(nPos = 0; nPos < nSize; nLine++)
{
nLineSize = min(nSize - nPos, 16);
memcpy(cLine, (char*)pData + nPos, nLineSize);
nPos += nLineSize;
nLen += sprintf(szBuf + nLen, "[%02d]: ", nLine);
for(n = 0; n < nLineSize; n++)
{
if(n == 8)
{
nLen += sprintf(szBuf + nLen, " ");
}
nLen += sprintf(szBuf + nLen, "%02x ", cLine[n] & 0x00FF);
}
for(n = nLineSize; n < 16; n++)
{
if(n == 8)
nLen += sprintf(szBuf + nLen, " ");
nLen += sprintf(szBuf + nLen, " ");/*三个空格*/
}
nLen += sprintf(szBuf + nLen, " :");
for(n = 0; n < nLineSize; n++)
{
if(!isprint(cLine[n]))
cLine[n] = '.';
nLen += sprintf(szBuf + nLen, "%c", cLine[n]);
}
nLen += sprintf(szBuf + nLen, "/n");
}
if(fputs(szBuf, pfile) != EOF && fflush(pfile) != EOF)
return 0;
return -1;
}
int PrintTraceHexLog(void *pData, int nSize)
{
FILE *fp = NULL;
if((fp = fopen(TRACE_FILE, "a")) != NULL)
{
PrintHexLog(fp, pData, nSize);
fclose(fp);
}
return 0;
}
2.5 信息判断函数
原型:int Verify(int bStatus, const char *szBuf, const char *szFile, int nLine)
功能:当标志bStatus为真时,函数不执行任何操作,否则Verify将向日志文件输出错误信息。字符串szBuf描述了错误信息,字符串szFile描述了发生了错误的源文件名称,参数nLine代表发生错误所在的行号。
2.6 源码
int Verify(int bStatus, const char *szBuf, const char *szFile, int nLine)
{
FILE *fp;
char szFileLine[128], szError[128];
if(!bStatus)
{
memset(szFileLine, 0, sizeof(szFileLine));
memset(szError, 0, sizeof(szError));
if(errno != 0)
sprintf(szError, "/t> %0.64s/n", strerror(errno));
if(szFile == NULL)
strcpy(szFileLine, "/t> Invalid file name");
else
sprintf(szFileLine, "/t> In line %d file %0.32s", nLine, szFile);
if(szBuf == NULL)
szBuf = "";
fp = fopen(TRACE_FILE, "a");
if(fp != NULL)
{
PrintLog(fp, "%s[%d]/n%s%s", szBuf, getpid(), szError, szFileLine);
fclose(fp);
}
errno = 0;
}
return bStatus;
}
- 测试
3.1 源码
#include "comlib.h"
int main()
{
char buf[1024];
char buf2[1024];
int i = 1000;
PrintLog(stderr, "This is a test[%d]", i);
PrintTraceLog("This is test[%d]", i);
PrintHexLog(stderr, &i, sizeof(i));
PrintTraceHexLog(&i, sizeof(int));
PrintTraceLog("----------------------");
Verify(0, NULL, __FILE__, __LINE__);
PrintTraceLog("-----------------------");
VERIFY(0);
PrintTraceLog("-----------------------");
VERIFY(1);
return 0;
}
3.2 编译
gcc –Wall –O2 –o test test.c –I../include –L../lib -lcom
3.3 查看结果
控制台输出:
INFO: 2009.12.16.22:29:26 [3712]: This is a test[1000]
INFO: 2009.12.16.22:29:26 [3712]: address[2276496] size[4]
[00]: e8 03 00 00 :....
日志文件中的输出:
INFO: 2009.12.16.22:29:26 [3712]: This is test[2278552]
INFO: 2009.12.16.22:29:26 [3712]: address[2276464] size[4]
[4200138]: e8 03 00 00 :....
INFO: 2009.12.16.22:29:26 [3712]: ----------------------
INFO: 2009.12.16.22:29:26 [3712]: [3712]
> Illegal seek
> In line 13 file src/td1.c
INFO: 2009.12.16.22:29:26 [3712]: -----------------------
INFO: 2009.12.16.22:29:26 [3712]: [3712]
> In line 15 file src/td1.c
INFO: 2009.12.16.22:29:26 [3712]: -----------------------