C++11:变长参数模板模拟java.lang.String.format格式化输出
2016-08-29 17:45
603 查看
java.lang.String中有一个很方便的方法format,可以将不同的类型的参数格式化输出成字符串,在C++下面并没有这么方便的函数来支持这个需求。
于是我用C++11的变长参数模板实现了
String.format的简单模拟,完整代码如下:
string_utils.h
#pragma once #include <string> #include <cstdio> #include <vector> #include <regex> #include <stdexcept> namespace std { /* * 简单模拟java.ang.String.format输出 * 除算术类型(int,long,float等)之外只支持std::string输出 * */ class string_utils { // 普通类型直接返回值 template<typename T> static T cvalue(T&& v){ return std::forward<T>(v); } // std::string类型返回c-string指针 static const char* cvalue( std::string& v){ return v.c_str(); } // 递归结束 static int snprintf (char *__stream, size_t __n, const std::string &__format){ if(__n<=0)return 0; // 正则表达式用于获取第一个格式化参数的%控制 static std::regex fmt_first("^[\\s\\S]*?%[-+ #0]?(\\d+|\\*)?(\\.(?:\\d+|\\*))?(?:hh|h|l|ll|j|z|t|L)?[diuoxXfFeEgGaAcspn]"); if(std::regex_match(__format,fmt_first)){ // 实际参数数目与格式化字符串不匹配抛出异常 throw std::logic_error("invalid format string:missing argument"); } // 调用标准snprintf输出 return std::snprintf(__stream,__n,__format.c_str()); } template<typename ARG1,typename ...Args> static int snprintf (char *__stream, size_t __n, const std::string &__format, ARG1&& first,Args&&...args){ if(__n<=0)return 0; // 正则表达式用于获取第一个格式化参数的%控制 static std::regex fmt_first("^(?:[^%]|%%)*%[-+ #0]?(\\d+|\\*)?(\\.(?:\\d+|\\*))?(?:hh|h|l|ll|j|z|t|L)?[diuoxXfFeEgGaAcspn]"); std::smatch m; if (!std::regex_search ( __format, m, fmt_first )){ // 没有找到%格式控制字符串则抛出异常 std::cerr<<"extra argument provied to printf\n__format:"<<__format<<std::endl; throw std::logic_error("extra argument provied to printf"); } // 调用标准snprintf函数输出第一个参数 int num=std::snprintf(__stream,__n,m[0].str().c_str(),cvalue(std::forward<ARG1>(first))); // 递归调用处理剩余的参数,调整缓冲指针和长度 return num+snprintf(__stream+num,size_t(__n-num),m.suffix().str(),std::forward<Args>(args)...); } public: // 类printf格式化输出字符串 template<typename ...Args> static std::string format(const std::string &__format,Args&&...args){ std::vector<char> buffer (size_t(1024)); int num = snprintf ( buffer.data(), size_t(1024), __format, std::forward<Args>(args)...); return std::string(buffer.data(),buffer.data()+num); } }; }
测试代码:
int main() { std::string md5str="b9114c860f2b4bc7698c81a467487174"; std::string fmt_str=std::string_utils::format(" md5str=%s ######size %d",md5str,md5str.size()); std::cout<<fmt_str<<std::endl; }
相关文章推荐
- java格式化输出 JAVA String.format 方法使用介绍
- C#,String.Format,数字格式化输出 ,format
- 在javascript中模拟string.Format格式化字符串组合
- C# string.Format数字格式化输出
- ASP.NET C# String.Format格式化输出
- string.Format 格式化输出
- java.lang.NumberFormatException: For input string
- .net C#:String.Format数字格式化输出 (转)
- ASP.NET C# String.Format格式化输出
- 入门:java.lang.NumberFormatException: For input string: "11"
- String.Format数字格式化输出 {0:N2} {0:D2} {0:C2}
- C#:String.Format数字格式化输出
- C#:String.Format数字格式化输出
- C#:String.Format数字格式化输出
- C#:String.Format数字格式化输出
- Java String.Format() 方法及参数说明
- C#:String.Format数字格式化输出
- MessageFormat对象实现格式化字符串输出,类似C#中的string.format方法
- c# string.Format 格式化输出
- ASP.NET C# String.Format格式化输出