C/C++使用fmt库实现格式化字符串

 更新时间:2023年12月25日 14:35:43   作者:liulilittle  
fmt库是一个高效、易用的C++格式化库,可以帮助我们方便地进行字符串格式化、输出、日志记录等操作,下面我们就来学习一下fmt格式化字符串的具体操作吧

实现的目的;提高 C/C++ 编译速度,fmt 库模板嵌套过多编译速度非常慢,且编译后程序体积也过大,函数步入的栈帧过多!

只支持格式;{}

不支持格式;{:02x}

class fmt
{
public:
    template <typename S, typename ...T>
    static std::string              format(const S& fmt, T ... args) noexcept
    {
        std::string str;
        if constexpr (std::is_same<S, std::string>::value)
        {
            str = fmt;
        }
        else if constexpr (std::is_same<S, std::string_view>::value)
        {
            str = std::string(fmt.data(), fmt.size());
        }
        else
        {
            str = fmt;
        }
 
        (..., format_string(str, args));
        return str;
    }
 
    template <typename OutputIt, typename ...T>
    static void                     format_to(OutputIt&& out, const std::string& fmt, T ... args)
    {
        std::string result = format(fmt, std::forward<T&&>(args)...);
        for (char ch : result)
        {
            *out = ch;
        }
    }
 
private:
    template <typename T>
    static std::string              to_string(const T& value) noexcept
    {
        if constexpr (std::is_same<T, bool>::value)
        {
            return value ? "true" : "false";
        }
        else if constexpr (std::is_pointer<T>::value)
        {
            using DECAY_T = typename std::decay<T>::type;
 
            if constexpr (std::is_same<char*, DECAY_T>::value || std::is_same<const char*, DECAY_T>::value)
            {
                return value ? value : "";
            }
            else 
            {
                if (value)
                {
                    char buf[sizeof(value) << 2];
                    snprintf(buf, sizeof(buf), "%p", reinterpret_cast<const void*>(value));
                    return buf;
                }
                return "null";
            }
        }
        else if constexpr (std::is_same<T, std::string>::value)
        {
            return value;
        }
        else if constexpr (std::is_same<T, std::string_view>::value)
        {
            return std::string(value.data(), value.size());
        }
        else
        {
            return std::to_string(value);
        }
    }
 
    template <typename T>
    static std::string              to_string(const std::shared_ptr<T>& value) noexcept
    {
        return fmt::to_string(value.get());
    }
 
    template <typename T>
    static void                     format_string(std::string& out, const T& value) noexcept
    {
        replace_string(out, "{}"sv, fmt::to_string(value));
    }
 
public:
    static bool                     replace_string(std::string& str, const std::string_view& old_string, const std::string_view& new_string) noexcept;
};
 
inline bool fmt::replace_string(std::string& str, const std::string_view& old_string, const std::string_view& new_string) noexcept
{
    size_t pos = str.find(old_string);
    if (pos == std::string::npos)
    {
        return false;
    }
 
    str.replace(pos, old_string.length(), new_string);
    return true;
}

方法补充

除了上文的方法,小编还为大家整理了其他C++格式化字符串的方法,希望对大家有所帮助

1.使用C++中的字符串流(stringstream)

例如:

#include <sstream>
std::stringstream ss;
int num = 42;
const char* str = "hello";
ss << "Num: " << num << ", str: " << str;
std::string result = ss.str();

上述代码中,我们使用字符串流将数字和字符串插入到字符串中,得到了最终的格式化结果。

需要注意的是,当处理浮点数时,可能会出现精度误差的问题,可以使用std::setprecision函数来指定小数点后的位数。

示例说明

下面是一个例子,展示了使用字符串流格式化浮点数的方法:

#include <sstream>
#include <iomanip>
std::stringstream ss;
double num = 3.14159265358979323846;
ss << "The value of pi is approximately " << std::setprecision(6) << std::fixed << num;
std::string result = ss.str();

上述代码中,我们使用字符串流将浮点数插入到字符串中,并设置小数点后6位的精度,输出结果为:

The value of pi is approximately 3.141593.

2.使用format库

format库是C++11格式化字符串的一种解决方案,它的设计目标是提供简单、便捷的格式化语法,并且不需要调用大量的函数来实现字符串的格式化。

format库可以被看作是一个功能强大的printf的替代品。在使用上它更加灵活,更加安全,而且能够提供更加友好的错误提示。

format库的使用方式和Python的字符串格式化方式非常相似,适合需要频繁使用字符串格式化的场景。

具体用法

#include <fmt/format.h>
#include <iostream>

int main(){
    std::cout << fmt::format("{} {} {}!\n", "Hello", "World", 123);
    std::cout << fmt::format("{2} {1} {0}!\n", "Hello", "World", 123);
    std::cout << fmt::format("{0:+} {0:-} {0:#}\n", 123);
    std::cout << fmt::format("{0:.3f} {0:7.3f}\n", 3.1415926535);
    std::cout << fmt::format("{{ }}\n");
    return 0;
}

到此这篇关于C/C++使用fmt库实现格式化字符串的文章就介绍到这了,更多相关C++格式化字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言陷阱与缺陷之数组越界访问详解

    C语言陷阱与缺陷之数组越界访问详解

    这篇文章主要为大家详细介绍了C语言的数组越界访问,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • TensorFlow源代码构建流程记录解析

    TensorFlow源代码构建流程记录解析

    这篇文章主要为大家介绍了TensorFlow源代码构建流程记录解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Qt项目实战之方块游戏的实现

    Qt项目实战之方块游戏的实现

    这篇文章主要为大家详细介绍了如何利用Qt实现简易的方块游戏,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以了解一下
    2023-03-03
  • C/C++如何实现循环左移,循环右移

    C/C++如何实现循环左移,循环右移

    这篇文章主要介绍了C/C++如何实现循环左移,循环右移,具有很好的参考价值,希望对大家有所帮助。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • C语言实现为无声avi视频添加wave音乐

    C语言实现为无声avi视频添加wave音乐

    这篇文章主要为大家详细介绍了C语言如何实现为无声avi视频添加wave音乐,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以了解一下
    2023-11-11
  • 深入浅出分析C++ string底层原理

    深入浅出分析C++ string底层原理

    C ++的string对象实质上就是一个容器,其内部有一个c_str方法能够返回一个指向的实质存储字符串副本的数据成员。即通过string::c_str()配合printf函数可以获取的字符串副本的内存地址
    2021-11-11
  • Qt绘制时钟效果

    Qt绘制时钟效果

    这篇文章主要为大家详细介绍了Qt绘制时钟效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C++ 实现L2-002 链表去重

    C++ 实现L2-002 链表去重

    这篇文章主要介绍了C++ 实现L2-002 链表去重,本文通过简要的案例,解题思路讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++通过类实现线性表

    C++通过类实现线性表

    这篇文章主要为大家详细介绍了C++通过类实现线性表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • Qt实现验证码相关功能的代码示例

    Qt实现验证码相关功能的代码示例

    验证码的原理基于人类视觉和计算机视觉的差异性,通过给用户显示一些难以被机器识别的图形或文字,让用户进行人机交互,确认自己的身份,这样可以有效保护网站安全,所以本给大家介绍了Qt实现验证码相关功能的代码示例,感兴趣的朋友可以参考下
    2024-01-01

最新评论