C++ 九阴真经之字符串格式化

佐手、 提交于 2020-08-10 12:09:31

提供支持C++字符格式的printf函数

虽然C++中提供了iostream进行字符串格式化输出,但日常开发中还是多有不便,比如log的输出,一般还是采用printf格式化输出,但printf不支持C++的std::string, 使用时需要频繁的转换,因此实现了C++字符串自动识别的format函数。

使用示例:

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("this is %s --> %s", strMsg, TestPrint()) << std::endl;
}

输出:

TestPrint 构造函数
TestPrint 析构函数
TestPrint 析构函数
this is my msg --> hello_100
TestPrint 析构函数

实现过程:

 

头文件

//获取数据
template <typename T>
T DataTraits(T val)
{
    return val;
}

//特化
const char* DataTraits(const std::string& ref);

//类型萃取,对非基础类型,按照c++的方式来处理
template <typename T>
std::string TypeTraits(void (T::*)())
{
	return std::string();
}

template <typename T>
T TypeTraits(T val)
{
	return val;
}

//类型萃取,数据转换
template <typename T>
std::string TypeTraitsValue(T val, int T::*)
{
	std::stringstream str;
	str << val;
	return str.str();
}

template <typename T>
T TypeTraitsValue(T val, ...)
{
	return val;
}

template<typename T>
decltype(TypeTraits<T>(0)) ClassTraits(T val)
{
	return TypeTraitsValue<T>(val, 0);
}

//格式化
std::string __format(const char *strFmt, ...);

template<typename...Args>
std::string __args(const char *strFmt, Args...args)
{
    return __format(strFmt, DataTraits(std::forward<Args>(args))...);
}

template<typename...Args>
std::string format(const char *strFmt, Args...args)
{
    return __args(strFmt, ClassTraits(std::forward<Args>(args))...);
}

std::string format(const char *strFmt);

实现文件:

std::string format(const char *strFmt)
{
    return strFmt;
}

std::string __format(const char *strFmt, ...)
{
#ifdef _WIN32
	va_list vl;

	va_start(vl, strFmt);
	int count = _vscprintf(strFmt, vl); //_vsctprintf(format, vl); 
	va_end(vl);

	char *pszBuf = new char[count + 1];
	va_start(vl, strFmt);
	vsprintf_s(pszBuf, count + 1, strFmt, vl);  //_vstprintf_s
	va_end(vl);
	std::string msg(pszBuf);
	delete pszBuf;
    return msg;
#else
	va_list vl;
	va_start(vl, strFmt);
	char *pszBuf = NULL;
	int count = vasprintf(&pszBuf, strFmt, vl); //_vsctprintf(format, vl); 
	va_end(vl);	

	std::string msg(pszBuf);
	free(pszBuf);
    return msg;
#endif
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!