c++之可变参数格式化字符串(c++11可变模板参数)
本文将使用 泛型 实现可变参数。 涉及到的关见函数: std::snprintf
1、一个例子
函数声明及定义
1 // 泛型
2 template <typename... Args>
3 std::string show_str(const char *pformat, Args... args)
4 {
5 // 计算字符串长度
6 int len_str = std::snprintf(nullptr, 0, pformat, args...);
7
8 if (0 >= len_str)
9 return std::string("");
10
11 len_str++;
12 char *pstr_out = nullptr;
13 pstr_out = new(std::nothrow) char[len_str];
14 // 申请失败
15 if (NULL == pstr_out || nullptr == pstr_out)
16 return std::string("");
17
18 // 构造字符串
19 std::snprintf(pstr_out, len_str, pformat, args...);
20
21 // 保存构造结果
22 std::string str(pstr_out);
23
24 // 释放空间
25 delete pstr_out;
26 pstr_out = nullptr;
27
28 return str;
29 }
2、一个调用例子
1 std::cout << "str = " << show_str("1-%s, 2-%.2f, 3-%d", "ABC", 12.3456, 100).c_str() << "\n";
3、输出结果
演示环境为: VS2015 up3

4、完整代码
1 #include <iostream>
2
3 // 泛型
4 template <typename... Args>
5 std::string show_str(const char *pformat, Args... args)
6 {
7 // 计算字符串长度
8 int len_str = std::snprintf(nullptr, 0, pformat, args...);
9
10 if (0 >= len_str)
11 return std::string("");
12
13 len_str++;
14 char *pstr_out = nullptr;
15 pstr_out = new(std::nothrow) char[len_str];
16 // 申请失败
17 if (NULL == pstr_out || nullptr == pstr_out)
18 return std::string("");
19
20 // 构造字符串
21 std::snprintf(pstr_out, len_str, pformat, args...);
22
23 // 保存构造结果
24 std::string str(pstr_out);
25
26 // 释放空间
27 delete pstr_out;
28 pstr_out = nullptr;
29
30 return str;
31 }
32
33 // 入口函数
34 int main(int argc, char *argv[])
35 {
36 std::cout << "str = " << show_str("1-%s, 2-%.2f, 3-%d", "ABC", 12.3456, 100).c_str() << "\n";
37
38 system("pause");
39 return 0;
40 }
5、总结
A、 new 和 delete 需要配对使用
B、可自定义日志输出格式 和 构造c++格式化字符串。 更加方便输出日志.
6、扩展 (c++11)
A、可变参数模板函数
C++11的新特性--可变模版参数是C++11新增的特性之一,它对参数进行了高度泛化,能表示0到任意个数
一个例子,其定义如下
1 // 可变参数模板函数
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5 // 计算参数个数
6 int count_param = sizeof...(args);
7 std::cout << "参数个数=" << count_param << std::endl;
8 }
其中,计算参数个数的方式:
int count_param = sizeof...(args);
B、调用
1 // 入口函数
2 int main(int argc, char *argv[])
3 {
4 vp_func(1);
5 vp_func("-=+", 1.23456f);
6 vp_func(1, 2.2f, "ABC");
7
8 system("pause");
9 return 0;
10 }
C、输出结果:
演示环境: VS2015 up3

D、解包(包展开)
有两种方式
1)、递归
2)、非递归
递归,好用,但是要考虑爆栈的情况,不推荐。这里就不介绍了。
下面介绍非递归的方式展开
2.1)、定义展开函数
1 // 参数包展开
2 template<typename T>
3 void expand(const T t)
4 {
5 std::cout << t << std::endl;
6 }
再调用展开函数
1 // 可变参数模板函数
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5 // 计算参数个数
6 // int count_param = sizeof...(args);
7 // std::cout << "参数个数=" << count_param << std::endl;
8
9 std::initializer_list<int>{(expand(args), 0)...};
10 // std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
11 }
2.2)、使用lambda 展开
1 // 可变参数模板函数
2 template <typename ... Args>
3 void vp_func(Args ... args)
4 {
5 // 计算参数个数
6 // int count_param = sizeof...(args);
7 // std::cout << "参数个数=" << count_param << std::endl;
8
9 // std::initializer_list<int>{(expand(args), 0)...};
10 std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
11 }
非lambda 完整展开代码:
1 // 参数包展开
2 template<typename T>
3 void expand(const T t)
4 {
5 std::cout << t << std::endl;
6 }
7
8
9 // 可变参数模板函数
10 template <typename ... Args>
11 void vp_func(Args ... args)
12 {
13 // 计算参数个数
14 // int count_param = sizeof...(args);
15 // std::cout << "参数个数=" << count_param << std::endl;
16
17 std::initializer_list<int>{(expand(args), 0)...};
18 // std::initializer_list<int>{([&] {std::cout << args << std::endl; }(), 0)...};
19 }
c++之可变参数格式化字符串(c++11可变模板参数)的更多相关文章
- 零值初始化&字符串常数作为函数模板参数
1.在定义一个局部变量时,并希望该局部变量的初始化一个值,可以显示调用其默认构造函数,使其值为0(bool类型默认值为false). template <typename T> void ...
- Tostring(); 括号中的参数 格式化字符串
最近在逛 msdn 发现 查到 getTypeCode 方法 看到里边居然有 tostring("D")这样的写法 运行了一遍 感觉可以显示值 然后就 ...
- C语言之可变长参数格式化
概述 本文演示环境: win10 + Vs2015 可变长参数格式化 两个概念: 1. 参数长度不定, 2. 参数格式化. 使用函数 vsnprintf 结合 va_list. 源码 写好了函数, 照 ...
- C++ 11可变参数接口设计在模板编程中应用的一点点总结
概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量 ...
- [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇
目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...
- Linux下的格式化字符串漏洞利用姿势
linux最早的漏洞防护机制nx-stack刚刚出现后就有人想出了突破方法.那就是只有栈是不可执行,而除了栈以外的其他地方还是可以执行的,只要把返回地址执行别的地方就可以. 一.格式化字符串漏洞 格式 ...
- C++ Templates(1.3 多模板参数 Multiple Template Parameters)
返回完整目录 目录 1.3 多模板参数 Multiple Template Parameters 1.3.1 为返回类型设置模板参数参数 Template Parameters for Return ...
- 《深入实践C++模板编程》之三——模板参数类型详解
非类型模板参数 和 模板型模板参数 整数以及枚举类型:指向对象或者函数的指针:对对象或函数的引用:指向对象成员的指针.统称为非类型模板参数. 模板型模板参数,是指模板参数还可以是一个模板. 1.整 ...
- c(++)可变参数之格式化字符串
0.序言 使用printf函数,其参数就是可变参数.下面将使用 C语言 的库函数实现可变参数的函数 . 用途(欢迎补充): A.记录日志,可能需要将变量格式化输出到日志文件. B.格式化字符串,显示 ...
随机推荐
- 【机器学习与R语言】1-机器学习简介
目录 1.基本概念 2.选择机器学习算法 3.使用R进行机器学习 1.基本概念 机器学习:发明算法将数据转化为智能行为 数据挖掘 VS 机器学习:前者侧重寻找有价值的信息,后者侧重执行已知的任务.后者 ...
- PAML 选择压力的计算
简介 PAML(Phylogenetic Analysis by Maximum Likelihood)是伦敦大学的杨子恒(Yang Ziheng)教 授开发的一套基于最大似然估计来对蛋白质和核酸序列 ...
- R语言与医学统计图形-【23】ggplot2坐标系转换函数
ggplot2绘图系统--坐标系转换函数 包括饼图.环状条图.玫瑰图.戒指图.坐标翻转. 笛卡尔坐标系(最常见). ArcGIS地理坐标系(地图). Cartesian坐标系. polar极坐标系. ...
- C语言计算fastq文件GC含量2
改进了一下,利用zlib可以读取gz格式的压缩文件,也可以直接计算非压缩格式 #include <stdio.h> #include <stdlib.h> #include & ...
- 给lua_close实现回调函数
先讲下为什么会需要lua_close回调吧. 我用C++给lua写过不少库,其中有一些,是C++依赖堆内存,并且是每一个lua对象使用一块单独的内存来使用的. 在之前,我一直都是魔改lua源代码,给l ...
- 再聊我们自研的那些Devops工具
两年前我写了篇文章『我们自研的那些Devops工具』介绍了我们自研的一些DevOps工具系统,两年过去了这些工具究竟还有没有在发光发热,又有哪些新的变化呢,我将通过这篇文章来回顾一下这两年的发展与变化 ...
- 微信小程序扫描普通二维码打开小程序的方法
很久没有写博客了,之前换了一份工作,很久没有做Android开发了,现在转做前端开发了,记录一下遇到的问题及解决的方法. 最近做微信小程序开发,遇到一个需求,后台管理系统生成的问卷和投票会有一个二维码 ...
- SimpleNVR如何把安防监控画面推流到微信公众号直播
背景需求 进入移动互联网时代以来,微信已成为许多企业除官网以外必备的宣传渠道,当3.2亿直播用户与九亿微信用户的势能增加,在微信上开启直播已成为越来越多企业的不二选择. 需求分析 微信公众号作为平台来 ...
- Hbase(6)【Java Api Phoenix操作Hbase】
目录 两种方式操作Phoenix 1.Thick Driver 2.Thin Driver 3.注意事项 两种方式操作Phoenix 官网:http://phoenix.apache.org/faq. ...
- flink-----实时项目---day04-------1. 案例:统计点击、参与某个活动的人数和次数 2. 活动指标多维度统计(自定义redisSink)
1. 案例 用户ID,活动ID,时间,事件类型,省份 u001,A1,2019-09-02 10:10:11,1,北京市 u001,A1,2019-09-02 14:10:11,1,北京市 u001, ...