一、C 风格变长参数函数
最具代表性:int printf(const char *format, …);
可能的实现:
int printf(const char *fmt, ...)
{
int _cnt = 0;
char* _sv = 0;
double _dv = 0.0;
int _iv = 0;
va_list _args;
va_start(_args, fmt);
for (const char* p=fmt; *p; ++p)
{
++_cnt;
// 对 *p 进行条件判断
if (*p != '%')
{
// do something
}
else
{
switch (*(++p))
{
case 'd':
_iv = va_arg(_args, int);
// do something
break;
case 'f':
_dv = va_arg(_args, double);
// do something
break;
case 's':
for (_sv=va_arg(_args, char*); *_sv; ++_sv)
{
// do something
}
break;
default:
// do something
break;
}
}
}
va_end(_args);
return _cnt;
}
内部主要是利用 va_list、va_start、va_arg、va_end 这 4 个宏将参数展开,并根据 fmt 指定的内容进行格式化。
二、C++ 风格模板递归(c++11 标准支持)
template <typename T>
void FormatHelper(std::stringstream& ss, const T& t)
{
ss << t;
}
template <typename T1, typename ...Tn>
void FormatHelper(std::stringstream& ss, const T1& t1, const Tn& ...tn)
{
ss << t1;
FormatHelper(ss, tn...);
}
template <typename ...Args>
std::string Format(const Args& ...args)
{
std::stringstream ss;
ss.setf(std::ios::fixed); // 格式化浮点数时可能需要此行
FormatHelper(ss, args...);
return ss.str();
}
主要是利用C++的多态和模板泛型编程,自动构建各匹配函数,将参数展开。
三、C++ 折叠表达式(C++17 标准支持)
template <typename ...Args>
std::string Format(const Args& ...args)
{
std::stringstream ss;
ss.setf(std::ios::fixed); // 格式化浮点数时可能需要此行
(ss << ... << args); // 折叠表达式精髓
return ss.str();
}
更简洁的代码。
四、调用示例
C:
printf("format to a string: %d, %.5f, %s\n", 100, 12345.123456789, "abcd");
C++:
std::cout << Format("format to a string: ", 100, ", ", std::setprecision(5), 12345.123456789, ", ", "abcd") << std::endl;
输出:
format to a string: 100, 12345.12346, abcd