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

帅比萌擦擦* 提交于 2020-10-24 15:59:50

上一篇介绍了支持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;
}

 

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