类型安全且自动管理内存的返回 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++接口,利用自动内存管理给出了解决问题的新方法.使用这个 ...
随机推荐
- LeetCode:Convert Sorted Array to Binary Search Tree,Convert Sorted List to Binary Search Tree
LeetCode:Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in asce ...
- [MetaHook] R_SparkShower
By hzqst void R_SparkShower(float *pos) { TEMPENTITY *tent; tent = efx.CL_TempEntAllocNoModel(pos); ...
- UIStepper步进器 ——事件驱动型控件,(一个+和-按钮的)
- (void)viewDidLoad { [super viewDidLoad]; //步进器 固定的size (94*27), 事件驱动型控件 UIStepper *st ...
- python的闭包与装饰器
原文发表在我的博客主页,转载请注明出处 前言 如果把python当作脚本语言,每次就是写个几十行上百行来处理数据的话,装饰器也许不是很必要,但是如果要开发一个大型系统,装饰器是躲不开的,最开始体会ry ...
- Javascript日期时间总结
写这篇文章,总结一下前端JavaScript遇到的时间格式处理. 1 C#时间戳处理 从后台返回的C#时间为:/Date(-62135596800000)/,这个是C#的DateTime.MinVal ...
- Java学习笔记(十七)——java序列化
[前面的话] 做项目总是要用到很多东西,遇到一个新的知识,并不是这个知识出来的时间短,而是对于自己来说是新的,所以就需要自己去学习,希望今后可以提高学习的效率. 这篇文章是关于Java 序列化的,选择 ...
- Android--按钮点击事件
Android中Button的点击事件非常简单,主要是一个内部类的问题 在界面上存在两个按钮和一个文本框,点击不同按钮的时候文本框中显示不同按钮的文字信息 <?xml version=" ...
- jquery hasClass、removeClass、addClass方法
hasClass(class) 检查当前的元素是否含有某个特定的类,如果有,则返回true. 参数: class:用于匹配的类名. ---------------------------------- ...
- java设计优化-享元模式
享元模式是设计模式中少数几个以调高系统性能为目的的设计模式.它的核心思想是:如果在一个系统中存在多个相同的对象,那么只需共享一份对象的拷贝,而不必为每一次使用都创建新的对象.在享元模式中,由于需要构建 ...
- JMeter 测试Web登录
JMeter测试 前置条件: 1安装JMeter 下载地址:http://jmeter.apache.org/ 2安装badBoy http://www.badboy.com.au/download/ ...