类型安全且自动管理内存的返回 std::string 的 sprintf 实现
在这篇博文里,我提到了一个例子,说的是使用C++实现类型安全的printf。这个例子很惊艳,但是在我写程序的时候,并非那么“迫切”地需要它出现在我的工具箱中,因为它并不比普通的printf方便,而且它没有出现的标准库中。所以自己也懒得整。相反,这个函数的兄弟,sprintf,倒是一个非常需要的函数。不仅仅是因为需要它类型安全,而是 sprintf 有比 printf 更多的麻烦:
- 首先它确实也不是类型安全的
- 使用sprintf之前,必须要先准备一段buffer,但这个buffer的大小难以确定,还要防溢出
- C++程序中多数时候我还是需要使用 string,于是还是要再用buffer中的字符串再生成一个string对象来使用。
这非常的麻烦,但是,sprintf 紧凑的表达是它最大的优点~我才不会用流去格式化一个字符串呢,实在是让人精神分裂啊。
想到用 variadic template 实现的 printf 之后,觉得应该是完全可以模仿这个做一个 sprintf 函数的啊,除了得到类型安全的好外之外,还能直接从函数返回字符串,又不会有溢出的问题,string和流自动地把内存管理好。一举多得。
std::string sprintf(const char *s)
{
std::stringstream ss;
_sprintf(ss, s);
return ss.str();
} void _sprintf(std::stringstream & ss, const char *s)
{
while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
throw std::runtime_error("invalid format string: missing arguments");
}
}
ss << *s++;
}
} template<typename T,typename... Args>
std::string sprintf(const char *s, T value, Args... args) {
std::stringstream ss;
_sprintf(ss, s, value, args...);
return ss.str();
} template<typename T, typename... Args>
void _sprintf(std::stringstream & ss, const char *s, T value, Args... args)
{ while (*s) {
if (*s == '%') {
if (*(s + 1) == '%') {
++s;
}
else {
ss << value;
_sprintf(ss, s + 1, args...); // call even when *s == 0 to detect extra arguments
return;
}
}
ss << *s++;
}
throw std::logic_error("extra arguments provided to lyw::sprintf");
}
使用起来也很方便,直接像原来的sprintf一样用就好了。而且如果自定义的对象实现的流操作符重载,就可以自动地与这个函数配合。非常精巧。
string str = sprintf("I tried % times in % ", 10, "Monday");
只需要加一点点代码(使用C++的流控制符),就可以实现各加精细的格式,这个版本我就不再贴了。
PS: 代码在VS2013上跑,很High,
VS2013在C++的开发环境(我是指编辑器)上做了很大的改进,而且速度也快了。算是难得
类型安全且自动管理内存的返回 std::string 的 sprintf 实现的更多相关文章
- iOS 非ARC基本内存管理系列 2-多对象内存管理(3) 利用@property来自动管理内存
iOS 基本内存管理-多对象内存管理(2)中可以看到涉及到对象的引用都要手动管理内存:每个对象都需要写如下代码 // 1.对要传入的"新车"对象car和目前Person类对象所拥有 ...
- Mysql: Connect/C++ 使用过程中发现返回 std::string 造成的内存泄露
在使用 Connect/C++ ,测试时发现在调用 getString 出现了内存增长的情况. ConstructOutput(); //打印出当前内存 ;i<;++i) { prepareSt ...
- Objective C----手动管理内存和自动管理内存
对象的引用计数(Reference Counting) 正常情况下,当一段代码需要访问某个对象时,该对象的引用的计数加1:当这段代码不再访问该对象时,该对象的引用计数减1,表示这段代码不再访问该对象: ...
- iOS手动管理内存
虽然iOS已经有了ARC帮你自动管理内存,但在有些项目中必须采用手动的方式,而且在懂得手动管理内存的情况下会是自己的代码更加完善 众所周知,基于手动管理内存的情况下必然涉及到 relese reta ...
- Oracle DB 自动管理共享内存
• 启用Oracle Enterprise Manager (EM) 内存参数 • 设置自动优化的内存参数 • 使用手动优化的SGA 参数覆盖最小大小 • 使用SGA Advisor 设置SGA_TA ...
- 【超值分享】为何写服务器程序需要自己管理内存,从改造std::string字符串操作说起。。。
服务器程序为何要进行内存管理,管中窥豹,让我们从string字符串的操作说起...... new/delete是用于c++中的动态内存管理函数,而malloc/free在c++和c中都可以使用,本质上 ...
- 根据Facebook内存的管理使用,浅谈在iOS上自动检测内存泄漏问题
分装库下载:https://github.com/facebook/FBMemoryProfiler FBMemoryProfiler类库使用教程:http://ifujun.com/fbmemory ...
- 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.3.垃圾收集器与内存分配策略
1.学习目的 当需要排查各种内存溢出. 内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. Java内存运行时区域的各个部分,其中程序计数 ...
- OpenCV 2.4.9 学习笔记(2)—— OpenCV内存自动管理
OpenCV自动内存管理 目前版本的OpenCV是自动处理所有自己的内存的,虽然这么说也不是很严谨.OpenCV在2.0版本中引入了一个新的C++接口,利用自动内存管理给出了解决问题的新方法.使用这个 ...
随机推荐
- Activiti系列:如何把Activiti工程转换为maven工程以解决依赖项找不到的问题
在eclipse中安装了Activiti插件之后,就可以新建Activiti工程,但是在实际使用时发现,在该工程中间新建Activiti Diagram,绘制好该图形之后,右键,新建单元测试,选择ju ...
- java从0开始学——数组,一维和多维
#,在java中,允许数组的长度为0:也就是允许 int[] zeroLenthArray = new int[0]; #,匿名的数组初始化是合法的: int[] smallPrim ...
- LeetCode:Binary Tree Level Order Traversal I II
LeetCode:Binary Tree Level Order Traversal Given a binary tree, return the level order traversal of ...
- Linux第三次实验报告
北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级:201352 姓名:池彬宁 贺邦 学号:20135212 2013520 ...
- Promise 学习笔记 - 时间支配者
本文同步自我的个人博客:http://www.52cik.com/2015/11/08/promise.html JavaScript 的 promises 事实标准称为 Promises/A+.ES ...
- 类似IOS的滑动返回上一级,SwipeBackLayout-android的滑动返回类库
最近,公司在开发App的需求中增加了一个新的需求,要在android的页面中增加向右滑动的时候返回上一级页面.我刚知道这个需求的时候,感觉有点坑,可能设计那边最近接触到知乎的客户端或者是IOS的滑动可 ...
- css渐变
常这样去定义一个渐变的div: 渐变1:(双色) background: -moz-linear-gradient(top, #456d6c %, #32b66a %); %,#456d6c), co ...
- 第三十四课:jQuery Deferred详解2
上一课主要分析了jQuery1.51版本的jQuery Deferred.在jQuery1.6中,jQuery Deferred添加了两个方法,always,pipe. always用来添加回调,无论 ...
- Daily Scrum – 1/11
Meeting Minutes 发现了一个新的bug,即当背诵单词过多时,会出现统计信息超出文字框的现象: 更新了tfs,明白了打包的方式: Burndown Progress part ...
- 练习一_使用Git进行代码管理的心得
2015年9月19日,第一次软工实践课.助教给我们介绍了git,GitHub.显而易见,我并没有听懂.所以整个上午都在找教程,一个字一个字对着敲,然后敲着敲着就出错,回宿舍,继续敲,也是一样的... ...