该文档参考了以下网友的文章,在此表示感谢。
1. (更新)OutputDebugString函数简单封装,实现格式化打印输出(VC++)
链接:http://blog.youkuaiyun.com/sunflover454/article/details/48718409
2. __VA_ARGS__用法(转)
链接:http://blog.chinaunix.net/uid-22878837-id-2110544.html
在VC中,有时候为了方便软件的调试,需要在软件代码中加入一些调试信息来跟踪软件的执行流程和状态,这些信息通常使用打印函数打印到调试界面上。我这边使用的调试信息查看工具是DebugView,打印信息函数使用OutputDebugStringA(对于ASCII码)或OutputDebugStringW(对于UNICODE编码)。
软件中的调试信息一般在软件的DEBUG版本中使用,在Release版本中需要将其去除。为了方便软件管理和共用代码,最好自己定义调试信息打印函数,然后通过宏定义来控制是否需要打印信息。这里参照前面的文章1,对其代码进行了一些修改,方便自己的使用。调试信息打印函数的实现代码单独放在MyOutputDebugString.cpp文件中,在MyOutputDebugString.h头文件中进行了调试信息打印函数的声明,同时通过_DEBUG宏定义来控制是否在软件中包含调试信息。实际使用时,只需将这2个文件包含到工程中,然后包含MyOutputDebugString.h头文件即可。
具体代码如下。
MyOutputDebugString.h头文件代码。
#pragma once
#if _DEBUG
#define DEBUG_INFO(...) MyOutputDebugStringW(__VA_ARGS__)
#else
#define DEBUG_INFO(...)
#endif
// ASCII码形式的打印信息函数,lpcszFilterString为DebugView的过滤字符串,lpcszOutputString为格式化输出字符
// 使用示例:MyOutputDebugStringA("DLL: ","%d,%s",123,"hello");
void MyOutputDebugStringA(const char * lpcszFilterString, const char * lpcszOutputString, ...);
// UNICODE码形式的打印信息函数,lpcszFilterString为DebugView的过滤字符串,lpcszOutputString为格式化输出字符
// 使用示例:MyOutputDebugStringW(L"DLL: ",L"%d,%s",456,L"world!");
void MyOutputDebugStringW(const wchar_t * lpcszFilterString, const wchar_t * szOutputString, ...);
MyOutputDebugString.cpp文件代码。
#include <windows.h>
#include <stdlib.h>
#include <stdarg.h>
#include <vector>
#include "MyOutputDebugString.h"
using namespace std;
void MyOutputDebugStringA(const char * lpcszFilterString, const char * lpcszOutputString, ...)
{
string strResult;
if (NULL != lpcszOutputString)
{
va_list marker = NULL;
va_start(marker, lpcszOutputString); //初始化变量参数
size_t nLength = _vscprintf(lpcszOutputString, marker) + 1; //获取格式化字符串长度
std::vector<char> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
int nWritten = _vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcszOutputString, marker);
if (nWritten>0)
{
strResult = &vBuffer[0];
}
va_end(marker); //重置变量参数
}
if (!strResult.empty())
{
string strFormated = lpcszFilterString;
strFormated.append(strResult);
OutputDebugStringA(strFormated.c_str());
}
}
void MyOutputDebugStringW(const wchar_t * lpcszFilterString, const wchar_t * lpcwszOutputString, ...)
{
wstring strResult;
if (NULL != lpcwszOutputString)
{
va_list marker = NULL;
va_start(marker, lpcwszOutputString); //初始化变量参数
size_t nLength = _vscwprintf(lpcwszOutputString, marker) + 1; //获取格式化字符串长度
std::vector<wchar_t> vBuffer(nLength, '\0'); //创建用于存储格式化字符串的字符数组
int nWritten = _vsnwprintf_s(&vBuffer[0], vBuffer.size(), nLength, lpcwszOutputString, marker);
if (nWritten>0)
{
strResult = &vBuffer[0];
}
va_end(marker); //重置变量参数
}
if (!strResult.empty())
{
wstring strFormated = lpcszFilterString;
strFormated.append(strResult);
OutputDebugStringW(strFormated.c_str());
}
}
以上代码中的MyOutputDebugStringA为ASCII码版本,MyOutputDebugStringW为UNICODE版本。示例中DEBUG_INFO(...)定义成MyOutputDebugStringW,为UNICODE版本。如果需要使用ASCII码版本,则使用MyOutputDebugStringA即可。
对于打印文件名和函数名等的相关信息,如果使用ASCII码版本,则使用__FILE__和__FUNCTION__;如果使用UNICODE码版本,则使用__FILEW__和__FUNCTIONW__。