专栏首页10km的专栏C++11:变长参数模板模拟java.lang.String.format格式化输出

C++11:变长参数模板模拟java.lang.String.format格式化输出

版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net/10km/article/details/52355224

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;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++11:模板函数实现支持变长参数的简单日志输出

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • c++11:基于STL实现字符串分割更简单 wstring,string split

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • c++11模板:容器(map,set,list,vector)中元素类型转换

    版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net...

    用户1148648
  • 移动开发之浅析cocos2d-x的中文支持问题

      题记:这阵子一直在学习cocos2d-x,其跨平台的特性确实让人舒爽,引擎的框架概念也很成熟,虽然相应的第三方工具略显单薄,但也无愧是一件移动开发的利器啊,...

    用户2615200
  • 使用libev监视文件夹下文件(夹)属性变动的方案和实现

            在《libev源码解析》系列中,我们分析了libev的基本原理。本文我们介绍一套使用libev封装的文件(夹)变动监视方案和实现。(转载请指明出...

    方亮
  • 常用公差及配合

    1.1.1 零线---在极限与配合图解中,表示基本尺寸的一条直线.以其为基准确定偏差和公差;

    用户7505898
  • OpenStack中彻底删除计算节点

    上一节我们尝试了追加安装一台计算节点,这一节我们讲一讲,怎么彻底删除。 下面记录了在openstack中彻底删除计算节点nova-node2.openstack...

    院长技术
  • Python在VSCode中进入交互界面调试

    VSCode非常强大,断点好用,美中不足,每次只能通过下面窄窄一行进行各种检查,而python的优点就在于交互式的调试,所以希望能够在断点时能够进入到正常的交互...

    用户1075292
  • .NET代码错误日志

    DougWang
  • (数据科学学习手札47)基于Python的网络数据采集实战(2)

      马上大四了,最近在暑期实习,在数据挖掘的主业之外,也帮助同事做了很多网络数据采集的内容,接下来的数篇文章就将一一罗列出来,来续写几个月前开的这个网络数据采集...

    Feffery

扫码关注云+社区

领取腾讯云代金券