实验题目:使用C/C++编写log打印函数
实验要求:1.将log打印函数定义在 plfapi.h 文件中
2.使用枚举定义trace、debug、error等lever的打印级别,并可在main.cpp里实现切换
3.函数的进来和出去使用trace等级打印;函数返回值、函数入参、switch、if的条件、子函数内参数使用debug等级打印;错误使用error等级打印;主函数内的运行结果使用msg等级打印。
实验环境与工具:1.Linux、ubuntu20、gcc7.4.0、secureCRT4.0、notepad++
2.vs2019 x86
说明:1.本实验共编写两类打印函数。
2.一类是基于printf的log打印函数,该函数使用起来比较麻烦,需要%d、%c、%s、\n等参数,但清晰明了,知道需要打印的参数是什么类型的,能够加深新手对C语言基础的理解。
3.一类是基于C++类的log打印函数,该函数使用起来简单,无需第一类的操作。
4.这两类log打印函数可使用在linux环境下,亦可使用与vs2019(低版本兼容)中。
5.码字不易,希望各位看官点个赞,十分感谢!!!!!
目录
一、基于printf的log打印函数
1.plfapi.h 程序:
/*!
*************************************************************************************************
* @file plfapi.h
* @brief
* @author
* date
*************************************************************************************************
*/
#ifndef _PLFAPI_DEBUG_H_
#define _PLFAPI_DEBUG_H_
#include <stdio.h>
#include <string.h>
//#include "unistd.h"
#include <io.h>
#include <process.h>
class SourceFile_PLFAPI
{
public:
template <int N>
inline explicit SourceFile_PLFAPI(const char (&arr)[N])
:data_(arr)
, size_(N - 1)
{
const char* slash = strrchr(data_, '/');
if (slash)
{
data_ = slash + 1;
size_ = static_cast<int>(data_ - arr);
}
}
explicit SourceFile_PLFAPI(const char* filename)
:data_(filename)
{
const char* slash = strrchr(filename, '/');
if (slash)
{
data_ = slash + 1;
}
size_ = static_cast<int>(strlen(data_));
}
const char* data_;
int size_;
};
enum enPlfapiMessage
{
g_plfapi_none,
g_plfapi_err,
g_plfapi_msg,
g_plfapi_dbg,
g_plfapi_trace,
g_plfapi_all,
};
extern enPlfapiMessage g_Plfapi_layer;
//notice: FILE LINE func VA_ARGS has four '_'
#define PLFAPI_TRACE(...) \
if (g_plfapi_trace <= g_Plfapi_layer) \
{ \
printf("[PLFAPI_TRACE] %s#%d@%s", SourceFile_PLFAPI(__FILE__).data_, __LINE__, __func__); \
printf(__VA_ARGS__); \
} \
#define PLFAPI_DBG(...) \
if (g_plfapi_dbg <= g_Plfapi_layer) \
{ \
printf("[PLFAPI_DBG] %s#%d@%s", SourceFile_PLFAPI(__FILE__).data_, __LINE__, __func__); \
printf(__VA_ARGS__); \
} \
#define PLFAPI_MSG(...) \
if (g_plfapi_msg <= g_Plfapi_layer) \
{ \
printf("[PLFAPI_MSGE] %s#%d@%s", SourceFile_PLFAPI(__FILE__).data_, __LINE__, __func__); \
printf(__VA_ARGS__); \
} \
#define PLFAPI_ERR(...) \
if (g_plfapi_err <= g_Plfapi_layer) \
{ \
printf("[PLFAPI_ERR] %s#%d@%s", SourceFile_PLFAPI(__FILE__).data_, __LINE__, __func__); \
printf(__VA_ARGS__); \
}
2. main.cpp程序
/*!
*************************************************************************************************
* @file main.cpp
* @brief
* @author
* date
*************************************************************************************************
*/
#include <stdlib.h>
#include <string>
#include <fstream>
#include <iostream>
#include "plfapi_debug.h"
/* by changing ERR parameters to DBG, ALL, MSG, and trace,
different printing levels can be switched*/
enPlfapiMessage g_Plfapi_layer = g_plfapi_err;
//enPlfapiMessage g_Plfapi_layer = g_plfapi_all;
//enPlfapiMessage g_Plfapi_layer = g_plfapi_msg;
/*!
* @brief
*/
int main()
{
PLFAPI_TRACE("in\n");
int iRet = -1;
char s[3] = "ab";
char *pKeyWord = NULL;
pKeyWord = (char *)malloc(sizeof(char) * 3);
if (pKeyWord == NULL)
{
PLFAPI_ERR("pKeyWord is null\n");
PLFAPI_DBG("ret: %d\n", iRet);
PLFAPI_TRACE("out\n");
return iRet;
}
memset(pKeyWord, 0, (sizeof(char) * 2));
strncpy(pKeyWord, s, 3);
PLFAPI_MSG("pKeyWord :%s\n", pKeyWord);
if (pKeyWord != NULL)
{
free(pKeyWord);
pKeyWord = NULL;
}
PLFAPI_DBG("ret: %d\n", iRet);
PLFAPI_TRACE("out\n");
return iRet;
}
3.实验结果
二、基于C++类的log打印函数
1.logbase.h 程序
/*!
*************************************************************************************************
* @file logbase.h
* @brief
* @author
* date
*************************************************************************************************
*/
#ifndef _LOGBASE_H
#define _LOGBASE_H
#include <cstddef>
#include <vector>
#include <string>
#include <string.h>
#define MGR_UNUSED(Argument) static_cast<void>(Argument);
#define MGR_DISABLE_COPY(Typename) \
Typename(const Typename&); \
Typename& operator = (const Typename&); \
#include <cstdio>
#define MGR_DEBUG(...) printf("[MGR]: "__VA_ARGS__);
#include <cassert>
#define MGR_ASSERT(expression) assert(expression);
#define MGR_ENABLE_LOG
enum enAPMessageLayer
{
EN_LAYER_NONE = 0,
EN_LAYER_ERR = 1,
EN_LAYER_INFO = 2,
EN_LAYER_DBG = 3,
EN_LAYER_TRACE = 4,
EN_LAYER_ALL = 5,
};
class SourceFile
{
public:
template <int N>
inline explicit SourceFile(const char(&arr)[N])
:data_(arr)
, size_(N - 1)
{
const char* slash = strrchr(data_, '/');
if (slash)
{
data_ = slash + 1;
size_ = static_cast<int>(data_ - arr);
}
}
explicit SourceFile(const char* filename)
:data_(filename)
{
const char* slash = strrchr(filename, '/');
if (slash)
{
data_ = slash + 1;
}
size_ = static_cast<int>(strlen(data_));
}
const char* data_;
int size_;
};
#ifdef MGR_ENABLE_LOG
#define MGR_LOGD \
LogHelper::LogD(MGR_LOG_TAG)
#define MGR_LOGI \
LogHelper::LogI(MGR_LOG_TAG)
#define MGR_LOGE \
LogHelper::LogE(MGR_LOG_TAG) << SourceFile(__FILE__).data_ << "#" << __LINE__ << "@" << __FUNCTION__ << ": "
#define MGR_LOGT \
LogHelper::LogT(MGR_LOG_TAG) << SourceFile(__FILE__).data_ << "#" << __LINE__ << "@" << __FUNCTION__ << ": "
#else
#define MGR_LOGD
#define MGR_LOGI
#define MGR_LOGE
#define MGR_LOGT
#endif
/*!
*.@brief for debug code
*
*/
extern enAPMessageLayer g_APMessageLayer;
class LogHelper
{
private:
enAPMessageLayer m_level;
public:
LogHelper(const char* type, const char* tag)
{
printf("<< MGR >> - @%s(%s): ", tag, type);
switch (*type)
{
case 'D':
m_level = EN_LAYER_DBG;
break;
case 'E':
m_level = EN_LAYER_ERR;
break;
case 'I':
m_level = EN_LAYER_INFO;
break;
case 'T':
m_level = EN_LAYER_TRACE;
break;
default:
m_level = EN_LAYER_NONE;
break;
}
}
explicit LogHelper(const char* type)
{
switch (*type)
{
case 'D':
m_level = EN_LAYER_DBG;
break;
case 'E':
m_level = EN_LAYER_ERR;
break;
case 'I':
m_level = EN_LAYER_INFO;
break;
case 'T':
m_level = EN_LAYER_TRACE;
break;
default:
m_level = EN_LAYER_NONE;
break;
}
}
~LogHelper()
{
if (g_APMessageLayer != EN_LAYER_NONE)
{
if (m_level <= g_APMessageLayer)
{
printf("\n");
}
}
}
static void setLogLayer(enAPMessageLayer layer)
{
g_APMessageLayer = layer;
}
static LogHelper LogD(const char* tag)
{
if ((g_APMessageLayer == EN_LAYER_DBG) || (g_APMessageLayer == EN_LAYER_ALL))
{
return LogHelper("D", tag);
}
else
{
return LogHelper("D");
}
}
static LogHelper LogE(const char* tag)
{
if ((g_APMessageLayer == EN_LAYER_ERR) || (g_APMessageLayer == EN_LAYER_ALL))
{
return LogHelper("E", tag);
}
else
{
return LogHelper("E");
}
}
static LogHelper LogI(const char* tag)
{
if ((g_APMessageLayer == EN_LAYER_INFO) || (g_APMessageLayer == EN_LAYER_ALL))
{
return LogHelper("I", tag);
}
else
{
return LogHelper("I");
}
}
static LogHelper LogT(const char* tag)
{
if ((g_APMessageLayer == EN_LAYER_TRACE) || (g_APMessageLayer == EN_LAYER_ALL))
{
return LogHelper("T", tag);
}
else
{
return LogHelper("T");
}
}
LogHelper& operator << (const std::string& str)
{
if (g_APMessageLayer != EN_LAYER_NONE)
{
if (m_level <= g_APMessageLayer)
{
printf("%s", str.c_str());
}
}
return *this;
}
LogHelper& operator << (const char* cstr)
{
if (g_APMessageLayer != EN_LAYER_NONE)
{
if (cstr)
{
printf("%s", cstr);
}
}
return *this;
}
LogHelper& operator << (int value)
{
if (g_APMessageLayer != EN_LAYER_NONE)
{
printf("%d", value);
}
return *this;
}
};
#endif
2. main.cpp程序
/*!
*************************************************************************************************
* @file logbase.h
* @brief
* @author
* date
*************************************************************************************************
*/
#include <fstream>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include "logbase.h"
enAPMessageLayer g_APMessageLayer = EN_LAYER_ALL;
//enAPMessageLayer g_APMessageLayer = EN_LAYER_ERR;
//enAPMessageLayer g_APMessageLayer = EN_LAYER_INFO;
#define MGR_LOG_TAG "Main"
int main()
{
MGR_LOGT << "in";
int iRet = -1;
char s[3] = "ab";
char* pKeyWord = NULL;
pKeyWord = (char*)malloc(sizeof(char) * 3);
if (NULL == pKeyWord)
{
MGR_LOGE << "pKeyWord is null";
MGR_LOGD << "ret: " << iRet;
MGR_LOGT << "out";
return iRet;
}
memset(pKeyWord, 0, (sizeof(char) * 2));
memcpy(pKeyWord, s, 3);
MGR_LOGI << "s: " << s;
MGR_LOGI << "pKeyWord: " << pKeyWord;
if (pKeyWord != NULL)
{
free(pKeyWord);
pKeyWord = NULL;
}
MGR_LOGD << "ret: " << iRet;
MGR_LOGT << "out";
return iRet;
}