上一篇介绍了支持C++类型的格式化操作,但还是存在以下缺点:
- 1、非类型安全,必须提供正确的%s、%d、%f等类型符号,否则有可能造成程序崩溃。
- 2、部分参数如果存在多次重复的情况下,需要多次指定参数。
针对以上缺点,我希望提供更加简洁的格式化操作函数以供选择:
format_pos("%1 + %2 = %3", 1,2,"3")
测试代码:
class TestPrint
{
public:
TestPrint()
{
std::cout << "TestPrint 构造函数" << std::endl;
}
~TestPrint()
{
std::cout << "TestPrint 析构函数" << std::endl;
}
friend void operator << (std::iostream& out, const TestPrint& t)
{
out << t.val << "_" << t.a ;
}
private:
int a = 100;
std::string val = "hello";
};
int main()
{
std::string strMsg("my msg");
std::cout << format_pos("this is %1 --> %2, this is %1 --> %2", strMsg, TestPrint()) << std::endl;
return 0;
}
实现代码:
//参数包装,统一转化成Param类
template<typename T>
std::string Param(T& val)
{
std::stringstream str;
str << val;
return str.str();
};
//特化
template<typename T = std::string>
std::string& Param(std::string& val)
{
return val;
};
//特化
template<typename T = const char*>
std::string Param(const char* val)
{
return val;
};
//参数搜集器,负责收集参数,并将参数格式化输出
class VCollect
{
public:
VCollect(const char* pszContext) :m_pszContext(pszContext)
{
}
//递归结束,将结果返回
std::string PosFormat()
{
return GetString();
}
template<typename T, typename ...Args>
std::string PosFormat(T val, Args...args)
{
m_vecParam.emplace_back(Param(val));
return PosFormat(args...);
}
std::string GetString()
{
std::stringstream str;
const char* s = m_pszContext;
while (*s)
{
if (*s == '%')
{
char ch = atoi(++s);
if (ch == '%')
{
str << *s;
continue;
}
int nArgNum = atoi(s++);
if (nArgNum <= 0 || nArgNum > m_vecParam.size())
{
return str.str();
}
str << m_vecParam[nArgNum - 1];
while ((nArgNum = nArgNum / 10) > 0)s++;
}
else
{
str << *s++;
}
}
return std::move(str.str());
}
private:
std::vector<std::string> m_vecParam;
const char* m_pszContext;
};
//按占位符替换参数,使用方法 format_pos("%1 + %2 = %3", 1,2,"3")
template<typename...Args>
std::string format_pos(const char *strFmt, Args...args)
{
return VCollect(strFmt).PosFormat(args...);
}
//特化,实现未带参数场景
std::string format_pos(const char *strFmt)
{
return strFmt;
}
来源:oschina
链接:https://my.oschina.net/u/3312209/blog/4305222