在c和c++中,可变参数使用的最多函数有:scanf,printf,以及fprintf,fscanf,sprintf等,MFC也提供CString::Format实现可变参数。
本示例通过va_list来实现自己的可变参数函数,实现程序写日志功能。
通过可变参数实现日志打印
// ForATest.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include "Windows.h"
#include "iostream"
using namespace std;
#include "string"
#include <stdio.h>
#include <stdarg.h>
#define PL_ERROR -2
#define SERVICE_ERROR(strMod, ulErrCode, cFormat, ...) \
logRecord(__FUNCTION__, __LINE__, strMod, PL_ERROR, ulErrCode, cFormat, __VA_ARGS__);
static string TestIT_MODULE = "TestItMe";
void logRecord(string strFunc,
int iLine,
string strMod,
int iLevel,
int iErrCode,
char* cFormat,
...)
{
string strLog;
strLog.clear();
char acBuffer1[255], acBuffer2[255];
sprintf_s(acBuffer1, 254, "[%s] [%d] [%s] [%d] [%d]", strFunc.data(), iLine, strMod.data(), iLevel, iErrCode);
va_list args;
va_start (args, cFormat);
vsprintf(acBuffer2,cFormat, args);
FILE* pFile = fopen("C:\\log.txt","a+");
if (NULL == pFile)
return;
fprintf(pFile, acBuffer1);
fprintf(pFile, acBuffer2);
fprintf(pFile,"\n");
fclose(pFile);
va_end(args);
}
int _tmain(int argc, _TCHAR* argv[])
{
string strFileName = "C:\\Intel\\Logs";
SERVICE_ERROR(TestIT_MODULE, -1, "GetFile %s Attributes fail error code %d", strFileName.data(), GetLastError());
}
#include "stdafx.h"
#include "Windows.h"
#include "iostream"
using namespace std;
#include "string"
#include <stdio.h>
#include <stdarg.h>
#define PL_ERROR -2
#define SERVICE_ERROR(strMod, ulErrCode, cFormat, ...) \
logRecord(__FUNCTION__, __LINE__, strMod, PL_ERROR, ulErrCode, cFormat, __VA_ARGS__);
static string TestIT_MODULE = "TestItMe";
void logRecord(string strFunc,
int iLine,
string strMod,
int iLevel,
int iErrCode,
char* cFormat,
...)
{
string strLog;
strLog.clear();
char acBuffer1[255], acBuffer2[255];
sprintf_s(acBuffer1, 254, "[%s] [%d] [%s] [%d] [%d]", strFunc.data(), iLine, strMod.data(), iLevel, iErrCode);
va_list args;
va_start (args, cFormat);
vsprintf(acBuffer2,cFormat, args);
FILE* pFile = fopen("C:\\log.txt","a+");
if (NULL == pFile)
return;
fprintf(pFile, acBuffer1);
fprintf(pFile, acBuffer2);
fprintf(pFile,"\n");
fclose(pFile);
va_end(args);
}
int _tmain(int argc, _TCHAR* argv[])
{
string strFileName = "C:\\Intel\\Logs";
SERVICE_ERROR(TestIT_MODULE, -1, "GetFile %s Attributes fail error code %d", strFileName.data(), GetLastError());
}
sprintf_s的一个示例
#include <stdio.h>
#include "string"
#include "iostream"
using namespace std;
int main( void )
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f;
string name = "hello";
// Format and print various data:
j = sprintf_s( buffer, 200, " String: %s\n", s );
j += sprintf_s( buffer + j, 200 - j, " Character: %c\n", c );
j += sprintf_s( buffer + j, 200 - j, " Integer: %d\n", i );
j += sprintf_s( buffer + j, 200 - j, " Real: %f\n", fp );
j += sprintf_s( buffer + j, 200 - j, " Name: %s\n", name.data() );
printf_s( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
#include "string"
#include "iostream"
using namespace std;
int main( void )
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f;
string name = "hello";
// Format and print various data:
j = sprintf_s( buffer, 200, " String: %s\n", s );
j += sprintf_s( buffer + j, 200 - j, " Character: %c\n", c );
j += sprintf_s( buffer + j, 200 - j, " Integer: %d\n", i );
j += sprintf_s( buffer + j, 200 - j, " Real: %f\n", fp );
j += sprintf_s( buffer + j, 200 - j, " Name: %s\n", name.data() );
printf_s( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
C++ version
// AssistTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cstdio"
#include "iostream"
#include "string"
#include "fstream"
#include "cstdarg"
#include "windows.h"
using namespace std;
const int OP_SUCCESS = 0;
const int OP_FAILED = -1;
static string TestIT_MODULE = "TestItMe";
#define SERVICE_ERROR(strMod, ulErrCode, cFormat, ...) \
logRecord(__FUNCTION__, __LINE__, strMod, ulErrCode, cFormat, __VA_ARGS__);
//print log module
void logRecord(string strFunc,
int iLine,
string strMod,
int iErrCode,
char* cFormat,
...)
{
string strLog;
strLog.clear();
char acBuffer1[255], acBuffer2[255];
sprintf_s(acBuffer1, 254, "[%s] [%d] [%s] [%d] ", strFunc.data(), iLine, strMod.data(), iErrCode);
va_list args;
va_start (args, cFormat);
vsprintf(acBuffer2,cFormat, args);
ofstream ofLogFile;
ofLogFile.open("F:\\log.txt", ios::out | ios::app);
if (!ofLogFile)
{
return;
}
string strBuffer1, strBuffer2;
strBuffer1 = acBuffer1;
strBuffer2 = acBuffer2;
ofLogFile.write(strBuffer1.data(), strBuffer1.size());
ofLogFile.write(strBuffer2.data(), strBuffer2.size());
ofLogFile.put('\n');
ofLogFile.close();
va_end(args);
}
int main(int argc, char* argv[])
{
string strFileName = "C:\\Intel\\Logs";
SERVICE_ERROR(TestIT_MODULE, -1, "GetFile %s Attributes fail error code %d", strFileName.data(), GetLastError());
}
C++ version 2
// AssistTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cstdio"
#include "iostream"
#include "string"
#include "fstream"
#include "cstdarg"
#include "windows.h"
using namespace std;
const int OP_SUCCESS = 0;
const int OP_FAILED = -1;
static string TestIT_MODULE = "TestItMe";
class mt
{
public:
void LogRecord(string strFunc, unsigned int uiLine, string strMod, int iulErrCode, char* cFormat, ...);
//print log module
};
void mt::LogRecord(string strFunc,
unsigned int uiLine,
string strMod,
int iErrCode,
char* cFormat,
...)
{
string strLog;
strLog.clear();
char acBuffer1[255], acBuffer2[255];
sprintf_s(acBuffer1, 254, "[%s] [%d] [%s] [%d] ", strFunc.data(), uiLine, strMod.data(), iErrCode);
va_list args;
va_start (args, cFormat);
vsprintf(acBuffer2,cFormat, args);
ofstream ofLogFile;
ofLogFile.open("F:\\log.txt", ios::out | ios::app);
if (!ofLogFile)
{
return;
}
string strBuffer1, strBuffer2;
strBuffer1 = acBuffer1;
strBuffer2 = acBuffer2;
ofLogFile.write(strBuffer1.data(), strBuffer1.size());
ofLogFile.write(strBuffer2.data(), strBuffer2.size());
ofLogFile.put('\n');
ofLogFile.close();
va_end(args);
}
int main(int argc, char* argv[])
{
string strFileName = "C:\\Intel\\Logs";
mt m1;
m1.LogRecord(__FUNCTION__, __LINE__ ,TestIT_MODULE, -1, "GetFile %s Attributes fail error code %d", strFileName.data(), GetLastError());
}
参考
[1] http://www.cplusplus.com/reference/clibrary/cstdio/vsprintf/
[2] http://www.cnblogs.com/stuarts/archive/2010/08/03/1791598.html
[3] http://www.cnblogs.com/mydomain/archive/2010/07/27/1785667.html
讲述了了va_start等可变参数的基本概念及定义