能力值:
( LV4,RANK:50 )
|
-
-
2 楼
#ifdef DEBUG
#define dbgPrintf dbgPrintf__
#else
#define dbgPrintf
#endif
int dbgPrintf__(const char *fmt, ...)
{
va_list args;
char buffer[1024];
int i;
va_start(args, fmt);
i=vsnprintf(buffer, sizeof(buffer)-1, fmt,args);
va_end(args);
OutputDebugString(buffer);
return i;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
# 可以用于符号拼接。 楼主先试度定字符。 然后把定字符的改成valist
|
能力值:
( LV4,RANK:50 )
|
-
-
4 楼
[QUOTE=exile;1314534]#ifdef DEBUG
#define dbgPrintf dbgPrintf__
#else
#define dbgPrintf
#endif
int dbgPrintf__(const char *fmt, ...)
{
va_list args;
char buffer[...[/QUOTE]
你没看我的内容呀
我不想要fmt这个参数,很麻烦的
我就想直接把几个变量传进去,省去自己不停的改写fmt的内容
你的无法实现成我想要的调用方法,
如:dbgPrintf(A,B,C)
而一定要写成:
dbgPrintf("%s = %d, %s = %d, %s = %d",A,B,C)
写个fmt费死劲了,要这样我直接用printf了,是吧,根本不需要宏
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
路过回复一下:
较新的编译器(现在一般都支持的)宏可以用__VA_ARGS__支持动态参数,比如
#define LogError(Format, ...) xxx( Format, __VA_ARGS__)
xxx的实现可以用vDbgPrintEx或者CString.FormatV等等快速实现,自己可以参见printf或者DbgPrint实现。
比较旧的编译器可以用()来包含动态参数,可以参见kdPrint
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
[QUOTE=exile;1314534]#ifdef DEBUG
#define dbgPrintf dbgPrintf__
#else
#define dbgPrintf
#endif
int dbgPrintf__(const char *fmt, ...)
{
va_list args;
char buffer[...[/QUOTE]
宏比函数的好处可以方便处理一些编译器信息,例如插入函数名等等:
#define LogError(Format, ...) Log(Log_Error, __FUNCTION__, __LINE__, Format, __VA_ARGS__)
|
能力值:
( LV4,RANK:50 )
|
-
-
9 楼
我就是要舍弃前面的format,而通过宏来完成自动参数拼接成format啊
你和楼上都转回原路了,对我来说没意义,我早就实现成这样了
但当要大量输出时,几千行时,不停的改写format是非常麻烦的事
|
能力值:
( LV4,RANK:50 )
|
-
-
10 楼
对,我现在就用到了__FUNCTION__,
貌似宏没有办法实现参数枚举并加#进行连接哦
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
不用format宏无法推导参数个数,除非带个参数个数进去,或者根据参数定义多个宏,Log(n,...) 或者LogN(),都影响美观,很久以前就干过这样的。
用模板可以实现这样的功能
boost里面的function有类似的功能
利用typelist和模板递归可以实现,
---
实在不行用默认参数,Log(P1 p1=NULL, .... ,Pn pn = NULL); 蛋疼
其实也许你根本不需要这样的功能,记得以前想实现一个类似function的功能,搞了很多宏和模板,太琐碎,后来直接用脚本生成了Function0,Fucntion1,...FuncionN, 简单明了快捷
我记得有人说过,我们很多时间都浪费在寻找捷径上面,而且不是经常走的捷径。
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
// testLog.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <stdarg.h>
//下面这些宏 可以求出 "..." 参数的个数
#define COUNT_PARMS2(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _, ...) _
#define REPEAT_PARAMS(...) (__VA_ARGS__)
#define COUNT_PARMS(...) COUNT_PARMS2 REPEAT_PARAMS(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
// 输出不同个数参数的宏
#define Log0()
#define Log1(_arg1_) _LogA_Helper(#_arg1_, _arg1_)
#define Log2(_arg1_, _arg2_) _LogA_Helper(#_arg1_, _arg1_, #_arg2_, _arg2_)
#define Log3(_arg1_, _arg2_, _arg3_) _LogA_Helper(#_arg1_, _arg1_, #_arg2_, _arg2_, #_arg3_, _arg3_)
#define Log4(_arg1_, _arg2_, _arg3_, _arg4_) _LogA_Helper(#_arg1_, _arg1_, #_arg2_, _arg2_, #_arg3_, _arg3_, #_arg4_, _arg4_)
//根据参数个数,拼接出调用的宏 Log1(...), Log2(...), ...
#define CONNECT(a, b) CONNECT1(a, b)
#define CONNECT1(a, b) CONNECT2(a, b)
#define CONNECT2(a, b) a##b
#define Logs(...) CONNECT(CONNECT(Log, COUNT_PARMS(__VA_ARGS__)), REPEAT_PARAMS(__VA_ARGS__))
/// ////////////////////////////////////////////////////////////////////////////////
/// 重载的输出单个参数:可以根据类型确定输出格式
#define _MyPrintf printf
void _PrintOneParam(char value)
{
_MyPrintf("'%c'", value);
}
void _PrintOneParam(const char * szLog)
{
_MyPrintf("\"%s\"", szLog);
}
void _PrintOneParam(int value)
{
_MyPrintf("%d", value);
}
void _PrintOneParam(float value)
{
_MyPrintf("%f", value);
}
void _PrintOneParam(double value)
{
_MyPrintf("%lf", value);
}
/// ...
/// ////////////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////////////
/// 输出名字和值
template<typename T1>
void _LogA_Helper(const char * szT1Name, T1& t1)
{
_MyPrintf("["); _MyPrintf("%s=", szT1Name); _PrintOneParam(t1); _MyPrintf("]");
_MyPrintf("\r\n");
}
template<typename T1,typename T2>
void _LogA_Helper(const char * szT1Name, T1& t1, const char * szT2Name, T2& t2)
{
_MyPrintf("["); _MyPrintf("%s=", szT1Name); _PrintOneParam(t1); _MyPrintf("]");
_MyPrintf("["); _MyPrintf("%s=", szT2Name); _PrintOneParam(t2); _MyPrintf("]");
_MyPrintf("\r\n");
}
template<typename T1,typename T2, typename T3>
void _LogA_Helper(const char * szT1Name, T1& t1, const char * szT2Name, T2& t2, const char * szT3Name, T3& t3)
{
_MyPrintf("["); _MyPrintf("%s=", szT1Name); _PrintOneParam(t1); _MyPrintf("]");
_MyPrintf("["); _MyPrintf("%s=", szT2Name); _PrintOneParam(t2); _MyPrintf("]");
_MyPrintf("["); _MyPrintf("%s=", szT3Name); _PrintOneParam(t3); _MyPrintf("]");
_MyPrintf("\r\n");
}
template<typename T1,typename T2, typename T3, typename T4>
void _LogA_Helper(const char * szT1Name, T1& t1, const char * szT2Name, T2& t2, const char * szT3Name, T3& t3, const char *szT4Name, T4& t4)
{
_MyPrintf("["); _MyPrintf("%s=", szT1Name); _PrintOneParam(t1); _MyPrintf("]");
_MyPrintf("["); _MyPrintf("%s=", szT2Name); _PrintOneParam(t2); _MyPrintf("]");
_MyPrintf("["); _MyPrintf("%s=", szT3Name); _PrintOneParam(t3); _MyPrintf("]");
_MyPrintf("["); _MyPrintf("%s=", szT4Name); _PrintOneParam(t4); _MyPrintf("]");
_MyPrintf("\r\n");
}
/// ...
/// ////////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
int a = 1;
int b = 2;
double c = 1.2;
Logs(a,b,c);
return 0;
}
|
能力值:
( LV4,RANK:50 )
|
-
-
18 楼
其实重点是只要在宏里取得到每个参数名字就就办法了
用#把它们全连接成format,直接__VA_ARGS__给sprintf就行了
|
能力值:
( LV2,RANK:10 )
|
-
-
19 楼
需要参数的类型信息,不然不知道输出格式. 比如 double 类型 和 string类型 %后面的内容不一样.
我上面那个内容在 vc2010上测试了一下 . 可以 输出 参数名=参数值的格式.
|
能力值:
( LV4,RANK:50 )
|
-
-
21 楼
宏的好处是不用写太多函数的实现,函数这点就麻烦,模板有空研究下
这个研究确实是费时,但做过后,对将来解决类似问题还是有一定意义的
你研究过,所以给出的结论就比较有意义,起码不会再走太多弯路
|
能力值:
( LV9,RANK:200 )
|
-
-
23 楼
歪个楼,c99虽然支持了变参宏,但还是不如c++11的变参模板好使啊
//c++ 11
#include <iostream>
template<typename T>
void debug(T t)
{
std::cout << t << std::endl;
}
template<typename T, typename... L>
void debug(T t, L... l)
{
std::cout << t << " ";
debug(l...);
}
#define log_prefix __FUNCTION__, __LINE__
void main() {
debug(log_prefix, 1);
debug(log_prefix, 1, "hello");
debug(log_prefix, 1, "hello", 3.14);
}
|